include cleanup: Update gfp.h and slab.h includes to prepare for breaking implicit...
[safe/jmp/linux-2.6] / drivers / media / video / em28xx / em28xx-video.c
index 55bc8ea..0fe2011 100644 (file)
@@ -35,6 +35,7 @@
 #include <linux/version.h>
 #include <linux/mm.h>
 #include <linux/mutex.h>
+#include <linux/slab.h>
 
 #include "em28xx.h"
 #include <media/v4l2-common.h>
@@ -256,7 +257,8 @@ static void em28xx_copy_video(struct em28xx *dev,
 
                if ((char *)startwrite + lencopy > (char *)outp +
                    buf->vb.size) {
-                       em28xx_isocdbg("Overflow of %zi bytes past buffer end (2)\n",
+                       em28xx_isocdbg("Overflow of %zi bytes past buffer end"
+                                      "(2)\n",
                                       ((char *)startwrite + lencopy) -
                                       ((char *)outp + buf->vb.size));
                        lencopy = remain = (char *)outp + buf->vb.size -
@@ -281,26 +283,26 @@ static void em28xx_copy_vbi(struct em28xx *dev,
 {
        void *startwrite, *startread;
        int  offset;
-       int bytesperline = 720;
+       int bytesperline = dev->vbi_width;
 
        if (dev == NULL) {
-               printk("dev is null\n");
+               em28xx_isocdbg("dev is null\n");
                return;
        }
 
        if (dma_q == NULL) {
-               printk("dma_q is null\n");
+               em28xx_isocdbg("dma_q is null\n");
                return;
        }
        if (buf == NULL) {
                return;
        }
        if (p == NULL) {
-               printk("p is null\n");
+               em28xx_isocdbg("p is null\n");
                return;
        }
        if (outp == NULL) {
-               printk("outp is null\n");
+               em28xx_isocdbg("outp is null\n");
                return;
        }
 
@@ -322,8 +324,8 @@ static void em28xx_copy_vbi(struct em28xx *dev,
 
        /* Make sure the bottom field populates the second half of the frame */
        if (buf->top_field == 0) {
-               startwrite += bytesperline * 0x0c;
-               offset += bytesperline * 0x0c;
+               startwrite += bytesperline * dev->vbi_height;
+               offset += bytesperline * dev->vbi_height;
        }
 
        memcpy(startwrite, startread, len);
@@ -577,14 +579,13 @@ static inline int em28xx_isoc_copy_vbi(struct em28xx *dev, struct urb *urb)
                        dev->cur_field = p[2];
                }
 
-               /* FIXME: get rid of hard-coded value */
-               vbi_size = 720 * 0x0c;
+               vbi_size = dev->vbi_width * dev->vbi_height;
 
                if (dev->capture_type == 0) {
                        if (dev->vbi_read >= vbi_size) {
                                /* We've already read all the VBI data, so
                                   treat the rest as video */
-                               printk("djh c should never happen\n");
+                               em28xx_isocdbg("dev->vbi_read > vbi_size\n");
                        } else if ((dev->vbi_read + len) < vbi_size) {
                                /* This entire frame is VBI data */
                                if (dev->vbi_read == 0 &&
@@ -597,9 +598,9 @@ static inline int em28xx_isoc_copy_vbi(struct em28xx *dev, struct urb *urb)
                                        vbi_get_next_buf(vbi_dma_q, &vbi_buf);
                                        if (vbi_buf == NULL)
                                                vbioutp = NULL;
-                                       else {
-                                               vbioutp = videobuf_to_vmalloc(&vbi_buf->vb);
-                                       }
+                                       else
+                                               vbioutp = videobuf_to_vmalloc(
+                                                       &vbi_buf->vb);
                                }
 
                                if (dev->vbi_read == 0) {
@@ -669,7 +670,8 @@ buffer_setup(struct videobuf_queue *vq, unsigned int *count, unsigned int *size)
        struct em28xx        *dev = fh->dev;
        struct v4l2_frequency f;
 
-       *size = (fh->dev->width * fh->dev->height * dev->format->depth + 7) >> 3;
+       *size = (fh->dev->width * fh->dev->height * dev->format->depth + 7)
+               >> 3;
 
        if (0 == *count)
                *count = EM28XX_DEF_BUF;
@@ -723,7 +725,8 @@ buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb,
        struct em28xx        *dev = fh->dev;
        int                  rc = 0, urb_init = 0;
 
-       buf->vb.size = (fh->dev->width * fh->dev->height * dev->format->depth + 7) >> 3;
+       buf->vb.size = (fh->dev->width * fh->dev->height * dev->format->depth
+                       + 7) >> 3;
 
        if (0 != buf->vb.baddr  &&  buf->vb.bsize < buf->vb.size)
                return -EINVAL;
@@ -833,34 +836,63 @@ static void video_mux(struct em28xx *dev, int index)
 }
 
 /* Usage lock check functions */
-static int res_get(struct em28xx_fh *fh)
+static int res_get(struct em28xx_fh *fh, unsigned int bit)
 {
        struct em28xx    *dev = fh->dev;
-       int              rc   = 0;
 
-       /* This instance already has stream_on */
-       if (fh->stream_on)
-               return rc;
+       if (fh->resources & bit)
+               /* have it already allocated */
+               return 1;
 
-       if (dev->stream_on)
-               return -EBUSY;
+       /* is it free? */
+       mutex_lock(&dev->lock);
+       if (dev->resources & bit) {
+               /* no, someone else uses it */
+               mutex_unlock(&dev->lock);
+               return 0;
+       }
+       /* it's free, grab it */
+       fh->resources  |= bit;
+       dev->resources |= bit;
+       em28xx_videodbg("res: get %d\n", bit);
+       mutex_unlock(&dev->lock);
+       return 1;
+}
 
-       dev->stream_on = 1;
-       fh->stream_on  = 1;
-       return rc;
+static int res_check(struct em28xx_fh *fh, unsigned int bit)
+{
+       return fh->resources & bit;
 }
 
-static int res_check(struct em28xx_fh *fh)
+static int res_locked(struct em28xx *dev, unsigned int bit)
 {
-       return fh->stream_on;
+       return dev->resources & bit;
 }
 
-static void res_free(struct em28xx_fh *fh)
+static void res_free(struct em28xx_fh *fh, unsigned int bits)
 {
        struct em28xx    *dev = fh->dev;
 
-       fh->stream_on = 0;
-       dev->stream_on = 0;
+       BUG_ON((fh->resources & bits) != bits);
+
+       mutex_lock(&dev->lock);
+       fh->resources  &= ~bits;
+       dev->resources &= ~bits;
+       em28xx_videodbg("res: put %d\n", bits);
+       mutex_unlock(&dev->lock);
+}
+
+static int get_ressource(struct em28xx_fh *fh)
+{
+       switch (fh->type) {
+       case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+               return EM28XX_RESOURCE_VIDEO;
+       case V4L2_BUF_TYPE_VBI_CAPTURE:
+               return EM28XX_RESOURCE_VBI;
+       default:
+               BUG();
+               return 0;
+       }
 }
 
 /*
@@ -1028,16 +1060,11 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
                /* the em2800 can only scale down to 50% */
                height = height > (3 * maxh / 4) ? maxh : maxh / 2;
                width = width > (3 * maxw / 4) ? maxw : maxw / 2;
-               /* According to empiatech support the MaxPacketSize is too small
-                * to support framesizes larger than 640x480 @ 30 fps or 640x576
-                * @ 25 fps.  As this would cut of a part of the image we prefer
-                * 360x576 or 360x480 for now */
-               if (width == maxw && height == maxh)
-                       width /= 2;
        } else {
                /* width must even because of the YUYV format
                   height must be even because of interlacing */
-               v4l_bound_align_image(&width, 48, maxw, 1, &height, 32, maxh, 1, 0);
+               v4l_bound_align_image(&width, 48, maxw, 1, &height, 32, maxh,
+                                     1, 0);
        }
 
        get_scale(dev, width, height, &hscale, &vscale);
@@ -1103,12 +1130,6 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
                goto out;
        }
 
-       if (dev->stream_on && !fh->stream_on) {
-               em28xx_errdev("%s device in use by another fh\n", __func__);
-               rc = -EBUSY;
-               goto out;
-       }
-
        rc = em28xx_set_video_format(dev, f->fmt.pix.pixelformat,
                                f->fmt.pix.width, f->fmt.pix.height);
 
@@ -1117,6 +1138,21 @@ out:
        return rc;
 }
 
+static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *norm)
+{
+       struct em28xx_fh   *fh  = priv;
+       struct em28xx      *dev = fh->dev;
+       int                rc;
+
+       rc = check_dev(dev);
+       if (rc < 0)
+               return rc;
+
+       *norm = dev->norm;
+
+       return 0;
+}
+
 static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *norm)
 {
        struct em28xx_fh   *fh  = priv;
@@ -1668,24 +1704,25 @@ static int vidioc_streamon(struct file *file, void *priv,
 {
        struct em28xx_fh      *fh  = priv;
        struct em28xx         *dev = fh->dev;
-       int                   rc;
+       int                   rc = -EINVAL;
 
        rc = check_dev(dev);
        if (rc < 0)
                return rc;
 
+       if (unlikely(type != fh->type))
+               return -EINVAL;
 
-       mutex_lock(&dev->lock);
-       rc = res_get(fh);
+       em28xx_videodbg("vidioc_streamon fh=%p t=%d fh->res=%d dev->res=%d\n",
+                       fh, type, fh->resources, dev->resources);
 
-       if (likely(rc >= 0)) {
-               if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
-                       rc = videobuf_streamon(&fh->vb_vidq);
-               else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE)
-                       rc = videobuf_streamon(&fh->vb_vbiq);
-       }
+       if (unlikely(!res_get(fh, get_ressource(fh))))
+               return -EBUSY;
 
-       mutex_unlock(&dev->lock);
+       if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
+               rc = videobuf_streamon(&fh->vb_vidq);
+       else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE)
+               rc = videobuf_streamon(&fh->vb_vbiq);
 
        return rc;
 }
@@ -1707,16 +1744,16 @@ static int vidioc_streamoff(struct file *file, void *priv,
        if (type != fh->type)
                return -EINVAL;
 
-       mutex_lock(&dev->lock);
+       em28xx_videodbg("vidioc_streamoff fh=%p t=%d fh->res=%d dev->res=%d\n",
+                       fh, type, fh->resources, dev->resources);
 
-       if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
+       if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
                videobuf_streamoff(&fh->vb_vidq);
-       else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE)
+               res_free(fh, EM28XX_RESOURCE_VIDEO);
+       } else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
                videobuf_streamoff(&fh->vb_vbiq);
-
-       res_free(fh);
-
-       mutex_unlock(&dev->lock);
+               res_free(fh, EM28XX_RESOURCE_VBI);
+       }
 
        return 0;
 }
@@ -1734,11 +1771,13 @@ static int vidioc_querycap(struct file *file, void  *priv,
        cap->version = EM28XX_VERSION_CODE;
 
        cap->capabilities =
-                       V4L2_CAP_VBI_CAPTURE |
                        V4L2_CAP_SLICED_VBI_CAPTURE |
                        V4L2_CAP_VIDEO_CAPTURE |
                        V4L2_CAP_READWRITE | V4L2_CAP_STREAMING;
 
+       if (dev->vbi_dev)
+               cap->capabilities |= V4L2_CAP_VBI_CAPTURE;
+
        if (dev->audio_mode.has_audio)
                cap->capabilities |= V4L2_CAP_AUDIO;
 
@@ -1811,18 +1850,27 @@ static int vidioc_try_set_sliced_vbi_cap(struct file *file, void *priv,
 static int vidioc_g_fmt_vbi_cap(struct file *file, void *priv,
                                struct v4l2_format *format)
 {
-       format->fmt.vbi.samples_per_line = 720;
+       struct em28xx_fh      *fh  = priv;
+       struct em28xx         *dev = fh->dev;
+
+       format->fmt.vbi.samples_per_line = dev->vbi_width;
        format->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY;
        format->fmt.vbi.offset = 0;
        format->fmt.vbi.flags = 0;
+       format->fmt.vbi.sampling_rate = 6750000 * 4 / 2;
+       format->fmt.vbi.count[0] = dev->vbi_height;
+       format->fmt.vbi.count[1] = dev->vbi_height;
 
        /* Varies by video standard (NTSC, PAL, etc.) */
-       /* FIXME: hard-coded for NTSC support */
-       format->fmt.vbi.sampling_rate = 6750000 * 4 / 2; /* FIXME: ??? */
-       format->fmt.vbi.count[0] = 12;
-       format->fmt.vbi.count[1] = 12;
-       format->fmt.vbi.start[0] = 10;
-       format->fmt.vbi.start[1] = 273;
+       if (dev->norm & V4L2_STD_525_60) {
+               /* NTSC */
+               format->fmt.vbi.start[0] = 10;
+               format->fmt.vbi.start[1] = 273;
+       } else if (dev->norm & V4L2_STD_625_50) {
+               /* PAL */
+               format->fmt.vbi.start[0] = 6;
+               format->fmt.vbi.start[1] = 318;
+       }
 
        return 0;
 }
@@ -1830,18 +1878,27 @@ static int vidioc_g_fmt_vbi_cap(struct file *file, void *priv,
 static int vidioc_s_fmt_vbi_cap(struct file *file, void *priv,
                                struct v4l2_format *format)
 {
-       format->fmt.vbi.samples_per_line = 720;
+       struct em28xx_fh      *fh  = priv;
+       struct em28xx         *dev = fh->dev;
+
+       format->fmt.vbi.samples_per_line = dev->vbi_width;
        format->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY;
        format->fmt.vbi.offset = 0;
        format->fmt.vbi.flags = 0;
+       format->fmt.vbi.sampling_rate = 6750000 * 4 / 2;
+       format->fmt.vbi.count[0] = dev->vbi_height;
+       format->fmt.vbi.count[1] = dev->vbi_height;
 
        /* Varies by video standard (NTSC, PAL, etc.) */
-       /* FIXME: hard-coded for NTSC support */
-       format->fmt.vbi.sampling_rate = 6750000 * 4 / 2; /* FIXME: ??? */
-       format->fmt.vbi.count[0] = 12;
-       format->fmt.vbi.count[1] = 12;
-       format->fmt.vbi.start[0] = 10;
-       format->fmt.vbi.start[1] = 273;
+       if (dev->norm & V4L2_STD_525_60) {
+               /* NTSC */
+               format->fmt.vbi.start[0] = 10;
+               format->fmt.vbi.start[1] = 273;
+       } else if (dev->norm & V4L2_STD_625_50) {
+               /* PAL */
+               format->fmt.vbi.start[0] = 6;
+               format->fmt.vbi.start[1] = 318;
+       }
 
        return 0;
 }
@@ -1883,7 +1940,8 @@ static int vidioc_querybuf(struct file *file, void *priv,
                   At a minimum, it causes a crash in zvbi since it does
                   a memcpy based on the source buffer length */
                int result = videobuf_querybuf(&fh->vb_vbiq, b);
-               b->length = 17280;
+               b->length = dev->vbi_width * dev->vbi_height * 2;
+
                return result;
        }
 }
@@ -1900,9 +1958,8 @@ static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *b)
 
        if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
                return videobuf_qbuf(&fh->vb_vidq, b);
-       else {
+       else
                return videobuf_qbuf(&fh->vb_vbiq, b);
-       }
 }
 
 static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b)
@@ -2043,22 +2100,30 @@ static int radio_queryctrl(struct file *file, void *priv,
  */
 static int em28xx_v4l2_open(struct file *filp)
 {
-       int minor = video_devdata(filp)->minor;
-       int errCode = 0, radio;
-       struct em28xx *dev;
-       enum v4l2_buf_type fh_type;
+       int errCode = 0, radio = 0;
+       struct video_device *vdev = video_devdata(filp);
+       struct em28xx *dev = video_drvdata(filp);
+       enum v4l2_buf_type fh_type = 0;
        struct em28xx_fh *fh;
        enum v4l2_field field;
 
-       dev = em28xx_get_device(minor, &fh_type, &radio);
-
-       if (NULL == dev)
-               return -ENODEV;
+       switch (vdev->vfl_type) {
+       case VFL_TYPE_GRABBER:
+               fh_type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+               break;
+       case VFL_TYPE_VBI:
+               fh_type = V4L2_BUF_TYPE_VBI_CAPTURE;
+               break;
+       case VFL_TYPE_RADIO:
+               radio = 1;
+               break;
+       }
 
        mutex_lock(&dev->lock);
 
-       em28xx_videodbg("open minor=%d type=%s users=%d\n",
-                               minor, v4l2_type_names[fh_type], dev->users);
+       em28xx_videodbg("open dev=%s type=%s users=%d\n",
+                       video_device_node_name(vdev), v4l2_type_names[fh_type],
+                       dev->users);
 
 
        fh = kzalloc(sizeof(struct em28xx_fh), GFP_KERNEL);
@@ -2095,17 +2160,16 @@ static int em28xx_v4l2_open(struct file *filp)
        else
                field = V4L2_FIELD_INTERLACED;
 
-       if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
-               videobuf_queue_vmalloc_init(&fh->vb_vidq, &em28xx_video_qops,
-                                           NULL, &dev->slock, fh->type, field,
-                                           sizeof(struct em28xx_buffer), fh);
+       videobuf_queue_vmalloc_init(&fh->vb_vidq, &em28xx_video_qops,
+                                   NULL, &dev->slock,
+                                   V4L2_BUF_TYPE_VIDEO_CAPTURE, field,
+                                   sizeof(struct em28xx_buffer), fh);
 
-       if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE)
-               videobuf_queue_vmalloc_init(&fh->vb_vbiq, &em28xx_vbi_qops,
-                                           NULL, &dev->slock,
-                                           V4L2_BUF_TYPE_VBI_CAPTURE,
-                                           V4L2_FIELD_SEQ_TB,
-                                           sizeof(struct em28xx_buffer), fh);
+       videobuf_queue_vmalloc_init(&fh->vb_vbiq, &em28xx_vbi_qops,
+                                   NULL, &dev->slock,
+                                   V4L2_BUF_TYPE_VBI_CAPTURE,
+                                   V4L2_FIELD_SEQ_TB,
+                                   sizeof(struct em28xx_buffer), fh);
 
        mutex_unlock(&dev->lock);
 
@@ -2123,25 +2187,25 @@ void em28xx_release_analog_resources(struct em28xx *dev)
        /*FIXME: I2C IR should be disconnected */
 
        if (dev->radio_dev) {
-               if (-1 != dev->radio_dev->minor)
+               if (video_is_registered(dev->radio_dev))
                        video_unregister_device(dev->radio_dev);
                else
                        video_device_release(dev->radio_dev);
                dev->radio_dev = NULL;
        }
        if (dev->vbi_dev) {
-               em28xx_info("V4L2 device /dev/vbi%d deregistered\n",
-                           dev->vbi_dev->num);
-               if (-1 != dev->vbi_dev->minor)
+               em28xx_info("V4L2 device %s deregistered\n",
+                           video_device_node_name(dev->vbi_dev));
+               if (video_is_registered(dev->vbi_dev))
                        video_unregister_device(dev->vbi_dev);
                else
                        video_device_release(dev->vbi_dev);
                dev->vbi_dev = NULL;
        }
        if (dev->vdev) {
-               em28xx_info("V4L2 device /dev/video%d deregistered\n",
-                           dev->vdev->num);
-               if (-1 != dev->vdev->minor)
+               em28xx_info("V4L2 device %s deregistered\n",
+                           video_device_node_name(dev->vdev));
+               if (video_is_registered(dev->vdev))
                        video_unregister_device(dev->vdev);
                else
                        video_device_release(dev->vdev);
@@ -2162,26 +2226,27 @@ static int em28xx_v4l2_close(struct file *filp)
 
        em28xx_videodbg("users=%d\n", dev->users);
 
-
-       mutex_lock(&dev->lock);
-       if (res_check(fh))
-               res_free(fh);
-
-       if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE && dev->users == 1) {
+       if (res_check(fh, EM28XX_RESOURCE_VIDEO)) {
                videobuf_stop(&fh->vb_vidq);
-               videobuf_mmap_free(&fh->vb_vidq);
+               res_free(fh, EM28XX_RESOURCE_VIDEO);
+       }
 
+       if (res_check(fh, EM28XX_RESOURCE_VBI)) {
+               videobuf_stop(&fh->vb_vbiq);
+               res_free(fh, EM28XX_RESOURCE_VBI);
+       }
+
+       if (dev->users == 1) {
                /* the device is already disconnect,
                   free the remaining resources */
                if (dev->state & DEV_DISCONNECTED) {
                        em28xx_release_resources(dev);
-                       mutex_unlock(&dev->lock);
                        kfree(dev);
                        return 0;
                }
 
                /* Save some power by putting tuner to sleep */
-               v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_standby);
+               v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_power, 0);
 
                /* do this before setting alternate! */
                em28xx_uninit_isoc(dev);
@@ -2197,15 +2262,11 @@ static int em28xx_v4l2_close(struct file *filp)
                }
        }
 
-       if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
-               videobuf_stop(&fh->vb_vbiq);
-               videobuf_mmap_free(&fh->vb_vbiq);
-       }
-
+       videobuf_mmap_free(&fh->vb_vidq);
+       videobuf_mmap_free(&fh->vb_vbiq);
        kfree(fh);
        dev->users--;
        wake_up_interruptible_nr(&dev->open, 1);
-       mutex_unlock(&dev->lock);
        return 0;
 }
 
@@ -2230,12 +2291,8 @@ em28xx_v4l2_read(struct file *filp, char __user *buf, size_t count,
         */
 
        if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
-               mutex_lock(&dev->lock);
-               rc = res_get(fh);
-               mutex_unlock(&dev->lock);
-
-               if (unlikely(rc < 0))
-                       return rc;
+               if (res_locked(dev, EM28XX_RESOURCE_VIDEO))
+                       return -EBUSY;
 
                return videobuf_read_stream(&fh->vb_vidq, buf, count, pos, 0,
                                        filp->f_flags & O_NONBLOCK);
@@ -2243,9 +2300,8 @@ em28xx_v4l2_read(struct file *filp, char __user *buf, size_t count,
 
 
        if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
-               mutex_lock(&dev->lock);
-               rc = res_get(fh);
-               mutex_unlock(&dev->lock);
+               if (!res_get(fh, EM28XX_RESOURCE_VBI))
+                       return -EBUSY;
 
                return videobuf_read_stream(&fh->vb_vbiq, buf, count, pos, 0,
                                        filp->f_flags & O_NONBLOCK);
@@ -2268,19 +2324,17 @@ static unsigned int em28xx_v4l2_poll(struct file *filp, poll_table *wait)
        if (rc < 0)
                return rc;
 
-       mutex_lock(&dev->lock);
-       rc = res_get(fh);
-       mutex_unlock(&dev->lock);
-
-       if (unlikely(rc < 0))
-               return POLLERR;
-
-       if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
+       if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+               if (!res_get(fh, EM28XX_RESOURCE_VIDEO))
+                       return POLLERR;
                return videobuf_poll_stream(filp, &fh->vb_vidq, wait);
-       else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE)
+       } else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
+               if (!res_get(fh, EM28XX_RESOURCE_VBI))
+                       return POLLERR;
                return videobuf_poll_stream(filp, &fh->vb_vbiq, wait);
-       else
+       } else {
                return POLLERR;
+       }
 }
 
 /*
@@ -2296,13 +2350,6 @@ static int em28xx_v4l2_mmap(struct file *filp, struct vm_area_struct *vma)
        if (rc < 0)
                return rc;
 
-       mutex_lock(&dev->lock);
-       rc = res_get(fh);
-       mutex_unlock(&dev->lock);
-
-       if (unlikely(rc < 0))
-               return rc;
-
        if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
                rc = videobuf_mmap_mapper(&fh->vb_vidq, vma);
        else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE)
@@ -2346,6 +2393,7 @@ static const struct v4l2_ioctl_ops video_ioctl_ops = {
        .vidioc_querybuf            = vidioc_querybuf,
        .vidioc_qbuf                = vidioc_qbuf,
        .vidioc_dqbuf               = vidioc_dqbuf,
+       .vidioc_g_std               = vidioc_g_std,
        .vidioc_s_std               = vidioc_s_std,
        .vidioc_g_parm              = vidioc_g_parm,
        .vidioc_s_parm              = vidioc_s_parm,
@@ -2376,12 +2424,8 @@ static const struct video_device em28xx_video_template = {
        .release                    = video_device_release,
        .ioctl_ops                  = &video_ioctl_ops,
 
-       .minor                      = -1,
-
        .tvnorms                    = V4L2_STD_ALL,
-       /* FIXME: we need this to be NTSC for VBI to work - it should
-          be moved to a per-board definition */
-       .current_norm               = V4L2_STD_NTSC,
+       .current_norm               = V4L2_STD_PAL,
 };
 
 static const struct v4l2_file_operations radio_fops = {
@@ -2414,7 +2458,6 @@ static struct video_device em28xx_radio_template = {
        .name                 = "em28xx-radio",
        .fops                 = &radio_fops,
        .ioctl_ops            = &radio_ioctl_ops,
-       .minor                = -1,
 };
 
 /******************************** usb interface ******************************/
@@ -2432,7 +2475,6 @@ static struct video_device *em28xx_vdev_init(struct em28xx *dev,
                return NULL;
 
        *vfd            = *template;
-       vfd->minor      = -1;
        vfd->v4l2_dev   = &dev->v4l2_dev;
        vfd->release    = video_device_release;
        vfd->debug      = video_debug;
@@ -2440,6 +2482,7 @@ static struct video_device *em28xx_vdev_init(struct em28xx *dev,
        snprintf(vfd->name, sizeof(vfd->name), "%s %s",
                 dev->name, type_name);
 
+       video_set_drvdata(vfd, dev);
        return vfd;
 }
 
@@ -2469,13 +2512,10 @@ int em28xx_register_analog_devices(struct em28xx *dev)
        dev->mute = 1;
        dev->volume = 0x1f;
 
-       /* enable vbi capturing */
-
 /*     em28xx_write_reg(dev, EM28XX_R0E_AUDIOSRC, 0xc0); audio register */
        val = (u8)em28xx_read_reg(dev, EM28XX_R0F_XCLK);
        em28xx_write_reg(dev, EM28XX_R0F_XCLK,
                         (EM28XX_XCLK_AUDIO_UNMUTE | val));
-       em28xx_write_reg(dev, EM28XX_R11_VINCTRL, 0x51);
 
        em28xx_set_outfmt(dev);
        em28xx_colorlevels_set_default(dev);
@@ -2498,14 +2538,17 @@ int em28xx_register_analog_devices(struct em28xx *dev)
        }
 
        /* Allocate and fill vbi video_device struct */
-       dev->vbi_dev = em28xx_vdev_init(dev, &em28xx_video_template, "vbi");
+       if (em28xx_vbi_supported(dev) == 1) {
+               dev->vbi_dev = em28xx_vdev_init(dev, &em28xx_video_template,
+                                               "vbi");
 
-       /* register v4l2 vbi video_device */
-       ret = video_register_device(dev->vbi_dev, VFL_TYPE_VBI,
-                                       vbi_nr[dev->devno]);
-       if (ret < 0) {
-               em28xx_errdev("unable to register vbi device\n");
-               return ret;
+               /* register v4l2 vbi video_device */
+               ret = video_register_device(dev->vbi_dev, VFL_TYPE_VBI,
+                                           vbi_nr[dev->devno]);
+               if (ret < 0) {
+                       em28xx_errdev("unable to register vbi device\n");
+                       return ret;
+               }
        }
 
        if (em28xx_boards[dev->model].radio.type == EM28XX_RADIO) {
@@ -2521,12 +2564,16 @@ int em28xx_register_analog_devices(struct em28xx *dev)
                        em28xx_errdev("can't register radio device\n");
                        return ret;
                }
-               em28xx_info("Registered radio device as /dev/radio%d\n",
-                           dev->radio_dev->num);
+               em28xx_info("Registered radio device as %s\n",
+                           video_device_node_name(dev->radio_dev));
        }
 
-       em28xx_info("V4L2 device registered as /dev/video%d and /dev/vbi%d\n",
-                               dev->vdev->num, dev->vbi_dev->num);
+       em28xx_info("V4L2 video device registered as %s\n",
+                   video_device_node_name(dev->vdev));
+
+       if (dev->vbi_dev)
+               em28xx_info("V4L2 VBI device registered as %s\n",
+                           video_device_node_name(dev->vbi_dev));
 
        return 0;
 }