The patch number 10648 was added via Mauro Carvalho Chehab <[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: Mauro Carvalho Chehab  <[email protected]>
merge: http://www.linuxtv.org/hg/~hverkuil/v4l-dvb


Priority: normal

Signed-off-by: Mauro Carvalho Chehab <[email protected]>


---

 linux/Documentation/video4linux/v4l2-framework.txt |   12 
 linux/drivers/media/video/v4l2-dev.c               |   25 -
 linux/drivers/media/video/v4l2-device.c            |   47 +
 linux/drivers/media/video/vivi.c                   |  323 ++++++-------
 linux/include/media/v4l2-device.h                  |   31 -
 linux/include/media/v4l2-subdev.h                  |    4 
 6 files changed, 232 insertions(+), 210 deletions(-)

diff -r 4f6c3f9efa58 -r e471b963bef6 
linux/Documentation/video4linux/v4l2-framework.txt
--- a/linux/Documentation/video4linux/v4l2-framework.txt        Tue Feb 17 
23:32:03 2009 -0300
+++ b/linux/Documentation/video4linux/v4l2-framework.txt        Tue Feb 17 
23:44:45 2009 -0300
@@ -84,12 +84,14 @@ You must register the device instance:
        v4l2_device_register(struct device *dev, struct v4l2_device *v4l2_dev);
 
 Registration will initialize the v4l2_device struct and link dev->driver_data
-to v4l2_dev. Registration will also set v4l2_dev->name to a value derived from
-dev (driver name followed by the bus_id, to be precise). You may change the
-name after registration if you want.
+to v4l2_dev. If v4l2_dev->name is empty then it will be set to a value derived
+from dev (driver name followed by the bus_id, to be precise). If you set it
+up before calling v4l2_device_register then it will be untouched. If dev is
+NULL, then you *must* setup v4l2_dev->name before calling v4l2_device_register.
 
 The first 'dev' argument is normally the struct device pointer of a pci_dev,
-usb_device or platform_device.
+usb_device or platform_device. It is rare for dev to be NULL, but it happens
+with ISA devices, for example.
 
 You unregister with:
 
@@ -266,7 +268,7 @@ errors (except -ENOIOCTLCMD) occured, th
 
 The second argument to both calls is a group ID. If 0, then all subdevs are
 called. If non-zero, then only those whose group ID match that value will
-be called. Before a bridge driver registers a subdev it can set subdev->grp_id
+be called. Before a bridge driver registers a subdev it can set sd->grp_id
 to whatever value it wants (it's 0 by default). This value is owned by the
 bridge driver and the sub-device driver will never modify or use it.
 
diff -r 4f6c3f9efa58 -r e471b963bef6 linux/drivers/media/video/v4l2-dev.c
--- a/linux/drivers/media/video/v4l2-dev.c      Tue Feb 17 23:32:03 2009 -0300
+++ b/linux/drivers/media/video/v4l2-dev.c      Tue Feb 17 23:44:45 2009 -0300
@@ -326,37 +326,38 @@ static const struct file_operations v4l2
  */
 static int get_index(struct video_device *vdev, int num)
 {
-       u32 used = 0;
-       const int max_index = sizeof(used) * 8 - 1;
+       /* This can be static since this function is called with the global
+          videodev_lock held. */
+       static DECLARE_BITMAP(used, VIDEO_NUM_DEVICES);
        int i;
 
-       /* Currently a single v4l driver instance cannot create more than
-          32 devices.
-          Increase to u64 or an array of u32 if more are needed. */
-       if (num > max_index) {
+       if (num >= VIDEO_NUM_DEVICES) {
                printk(KERN_ERR "videodev: %s num is too large\n", __func__);
                return -EINVAL;
        }
 
-       /* Some drivers do not set the parent. In that case always return 0. */
+       /* Some drivers do not set the parent. In that case always return
+          num or 0. */
        if (vdev->parent == NULL)
-               return 0;
+               return num >= 0 ? num : 0;
+
+       bitmap_zero(used, VIDEO_NUM_DEVICES);
 
        for (i = 0; i < VIDEO_NUM_DEVICES; i++) {
                if (video_device[i] != NULL &&
                    video_device[i]->parent == vdev->parent) {
-                       used |= 1 << video_device[i]->index;
+                       set_bit(video_device[i]->index, used);
                }
        }
 
        if (num >= 0) {
-               if (used & (1 << num))
+               if (test_bit(num, used))
                        return -ENFILE;
                return num;
        }
 
-       i = ffz(used);
-       return i > max_index ? -ENFILE : i;
+       i = find_first_zero_bit(used, VIDEO_NUM_DEVICES);
+       return i == VIDEO_NUM_DEVICES ? -ENFILE : i;
 }
 
 int video_register_device(struct video_device *vdev, int type, int nr)
diff -r 4f6c3f9efa58 -r e471b963bef6 linux/drivers/media/video/v4l2-device.c
--- a/linux/drivers/media/video/v4l2-device.c   Tue Feb 17 23:32:03 2009 -0300
+++ b/linux/drivers/media/video/v4l2-device.c   Tue Feb 17 23:44:45 2009 -0300
@@ -27,15 +27,24 @@
 
 int v4l2_device_register(struct device *dev, struct v4l2_device *v4l2_dev)
 {
-       if (dev == NULL || v4l2_dev == NULL)
+       if (v4l2_dev == NULL)
                return -EINVAL;
-       /* Warn if we apparently re-register a device */
-       WARN_ON(dev_get_drvdata(dev) != NULL);
+
        INIT_LIST_HEAD(&v4l2_dev->subdevs);
        spin_lock_init(&v4l2_dev->lock);
        v4l2_dev->dev = dev;
-       snprintf(v4l2_dev->name, sizeof(v4l2_dev->name), "%s %s",
+       if (dev == NULL) {
+               /* If dev == NULL, then name must be filled in by the caller */
+               WARN_ON(!v4l2_dev->name[0]);
+               return 0;
+       }
+
+       /* Set name to driver name + device name if it is empty. */
+       if (!v4l2_dev->name[0])
+               snprintf(v4l2_dev->name, sizeof(v4l2_dev->name), "%s %s",
                        dev->driver->name, dev_name(dev));
+       if (dev_get_drvdata(dev))
+               v4l2_warn(v4l2_dev, "Non-NULL drvdata on register\n");
        dev_set_drvdata(dev, v4l2_dev);
        return 0;
 }
@@ -45,10 +54,11 @@ void v4l2_device_unregister(struct v4l2_
 {
        struct v4l2_subdev *sd, *next;
 
-       if (v4l2_dev == NULL || v4l2_dev->dev == NULL)
+       if (v4l2_dev == NULL)
                return;
-       dev_set_drvdata(v4l2_dev->dev, NULL);
-       /* unregister subdevs */
+       if (v4l2_dev->dev)
+               dev_set_drvdata(v4l2_dev->dev, NULL);
+       /* Unregister subdevs */
        list_for_each_entry_safe(sd, next, &v4l2_dev->subdevs, list)
                v4l2_device_unregister_subdev(sd);
 
@@ -56,19 +66,20 @@ void v4l2_device_unregister(struct v4l2_
 }
 EXPORT_SYMBOL_GPL(v4l2_device_unregister);
 
-int v4l2_device_register_subdev(struct v4l2_device *dev, struct v4l2_subdev 
*sd)
+int v4l2_device_register_subdev(struct v4l2_device *v4l2_dev,
+                                               struct v4l2_subdev *sd)
 {
        /* Check for valid input */
-       if (dev == NULL || sd == NULL || !sd->name[0])
+       if (v4l2_dev == NULL || sd == NULL || !sd->name[0])
                return -EINVAL;
        /* Warn if we apparently re-register a subdev */
-       WARN_ON(sd->dev != NULL);
+       WARN_ON(sd->v4l2_dev != NULL);
        if (!try_module_get(sd->owner))
                return -ENODEV;
-       sd->dev = dev;
-       spin_lock(&dev->lock);
-       list_add_tail(&sd->list, &dev->subdevs);
-       spin_unlock(&dev->lock);
+       sd->v4l2_dev = v4l2_dev;
+       spin_lock(&v4l2_dev->lock);
+       list_add_tail(&sd->list, &v4l2_dev->subdevs);
+       spin_unlock(&v4l2_dev->lock);
        return 0;
 }
 EXPORT_SYMBOL_GPL(v4l2_device_register_subdev);
@@ -76,12 +87,12 @@ void v4l2_device_unregister_subdev(struc
 void v4l2_device_unregister_subdev(struct v4l2_subdev *sd)
 {
        /* return if it isn't registered */
-       if (sd == NULL || sd->dev == NULL)
+       if (sd == NULL || sd->v4l2_dev == NULL)
                return;
-       spin_lock(&sd->dev->lock);
+       spin_lock(&sd->v4l2_dev->lock);
        list_del(&sd->list);
-       spin_unlock(&sd->dev->lock);
-       sd->dev = NULL;
+       spin_unlock(&sd->v4l2_dev->lock);
+       sd->v4l2_dev = NULL;
        module_put(sd->owner);
 }
 EXPORT_SYMBOL_GPL(v4l2_device_unregister_subdev);
diff -r 4f6c3f9efa58 -r e471b963bef6 linux/drivers/media/video/vivi.c
--- a/linux/drivers/media/video/vivi.c  Tue Feb 17 23:32:03 2009 -0300
+++ b/linux/drivers/media/video/vivi.c  Tue Feb 17 23:44:45 2009 -0300
@@ -34,14 +34,15 @@
 #include <linux/videodev.h>
 #endif
 #include <linux/interrupt.h>
-#include <media/videobuf-vmalloc.h>
-#include <media/v4l2-common.h>
-#include <media/v4l2-ioctl.h>
 #include <linux/kthread.h>
 #include <linux/highmem.h>
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 20)
 #include <linux/freezer.h>
 #endif
+#include <media/videobuf-vmalloc.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-ioctl.h>
+#include "font.h"
 
 #define VIVI_MODULE_NAME "vivi"
 
@@ -50,18 +51,32 @@
 #define WAKE_DENOMINATOR 1001
 #define BUFFER_TIMEOUT     msecs_to_jiffies(500)  /* 0.5 seconds */
 
-#include "font.h"
-
 #define VIVI_MAJOR_VERSION 0
-#define VIVI_MINOR_VERSION 5
+#define VIVI_MINOR_VERSION 6
 #define VIVI_RELEASE 0
 #define VIVI_VERSION \
        KERNEL_VERSION(VIVI_MAJOR_VERSION, VIVI_MINOR_VERSION, VIVI_RELEASE)
 
-/* Declare static vars that will be used as parameters */
-static unsigned int vid_limit = 16;    /* Video memory limit, in Mb */
-static int video_nr = -1;              /* /dev/videoN, -1 for autodetect */
-static int n_devs = 1;                 /* Number of virtual devices */
+MODULE_DESCRIPTION("Video Technology Magazine Virtual Video Capture Board");
+MODULE_AUTHOR("Mauro Carvalho Chehab, Ted Walther and John Sokol");
+MODULE_LICENSE("Dual BSD/GPL");
+
+static unsigned video_nr = -1;
+module_param(video_nr, uint, 0644);
+MODULE_PARM_DESC(video_nr, "videoX start number, -1 is autodetect");
+
+static unsigned n_devs = 1;
+module_param(n_devs, uint, 0644);
+MODULE_PARM_DESC(n_devs, "number of video devices to create");
+
+static unsigned debug;
+module_param(debug, uint, 0644);
+MODULE_PARM_DESC(debug, "activates debug info");
+
+static unsigned int vid_limit = 16;
+module_param(vid_limit, uint, 0644);
+MODULE_PARM_DESC(vid_limit, "capture memory limit in megabytes");
+
 
 /* supported controls */
 static struct v4l2_queryctrl vivi_qctrl[] = {
@@ -72,7 +87,7 @@ static struct v4l2_queryctrl vivi_qctrl[
                .maximum       = 65535,
                .step          = 65535/100,
                .default_value = 65535,
-               .flags         = 0,
+               .flags         = V4L2_CTRL_FLAG_SLIDER,
                .type          = V4L2_CTRL_TYPE_INTEGER,
        }, {
                .id            = V4L2_CID_BRIGHTNESS,
@@ -82,7 +97,7 @@ static struct v4l2_queryctrl vivi_qctrl[
                .maximum       = 255,
                .step          = 1,
                .default_value = 127,
-               .flags         = 0,
+               .flags         = V4L2_CTRL_FLAG_SLIDER,
        }, {
                .id            = V4L2_CID_CONTRAST,
                .type          = V4L2_CTRL_TYPE_INTEGER,
@@ -91,7 +106,7 @@ static struct v4l2_queryctrl vivi_qctrl[
                .maximum       = 255,
                .step          = 0x1,
                .default_value = 0x10,
-               .flags         = 0,
+               .flags         = V4L2_CTRL_FLAG_SLIDER,
        }, {
                .id            = V4L2_CID_SATURATION,
                .type          = V4L2_CTRL_TYPE_INTEGER,
@@ -100,7 +115,7 @@ static struct v4l2_queryctrl vivi_qctrl[
                .maximum       = 255,
                .step          = 0x1,
                .default_value = 127,
-               .flags         = 0,
+               .flags         = V4L2_CTRL_FLAG_SLIDER,
        }, {
                .id            = V4L2_CID_HUE,
                .type          = V4L2_CTRL_TYPE_INTEGER,
@@ -109,17 +124,12 @@ static struct v4l2_queryctrl vivi_qctrl[
                .maximum       = 127,
                .step          = 0x1,
                .default_value = 0,
-               .flags         = 0,
-       }
-};
-
-static int qctl_regs[ARRAY_SIZE(vivi_qctrl)];
-
-#define dprintk(dev, level, fmt, arg...)                               \
-       do {                                                            \
-               if (dev->vfd->debug >= (level))                         \
-                       printk(KERN_DEBUG "vivi: " fmt , ## arg);       \
-       } while (0)
+               .flags         = V4L2_CTRL_FLAG_SLIDER,
+       }
+};
+
+#define dprintk(dev, level, fmt, arg...) \
+       v4l2_dbg(level, debug, &dev->v4l2_dev, fmt, ## arg)
 
 /* ------------------------------------------------------------------
        Basic structures
@@ -209,6 +219,7 @@ static LIST_HEAD(vivi_devlist);
 
 struct vivi_dev {
        struct list_head           vivi_devlist;
+       struct v4l2_device         v4l2_dev;
 
        spinlock_t                 slock;
        struct mutex               mutex;
@@ -229,6 +240,9 @@ struct vivi_dev {
 
        /* Input Number */
        int                        input;
+
+       /* Control 'registers' */
+       int                        qctl_regs[ARRAY_SIZE(vivi_qctrl)];
 };
 
 struct vivi_fh {
@@ -659,7 +673,7 @@ static int vivi_start_thread(struct vivi
        dma_q->kthread = kthread_run(vivi_thread, fh, "vivi");
 
        if (IS_ERR(dma_q->kthread)) {
-               printk(KERN_ERR "vivi: kernel_thread() failed\n");
+               v4l2_err(&dev->v4l2_dev, "kernel_thread() failed\n");
                return PTR_ERR(dma_q->kthread);
        }
        /* Wakes thread */
@@ -802,8 +816,12 @@ static int vidioc_querycap(struct file *
 static int vidioc_querycap(struct file *file, void  *priv,
                                        struct v4l2_capability *cap)
 {
+       struct vivi_fh  *fh  = priv;
+       struct vivi_dev *dev = fh->dev;
+
        strcpy(cap->driver, "vivi");
        strcpy(cap->card, "vivi");
+       strlcpy(cap->bus_info, dev->v4l2_dev.name, sizeof(cap->bus_info));
        cap->version = VIVI_VERSION;
        cap->capabilities =     V4L2_CAP_VIDEO_CAPTURE |
                                V4L2_CAP_STREAMING     |
@@ -1094,12 +1112,14 @@ static int vidioc_g_ctrl(struct file *fi
 static int vidioc_g_ctrl(struct file *file, void *priv,
                         struct v4l2_control *ctrl)
 {
+       struct vivi_fh *fh = priv;
+       struct vivi_dev *dev = fh->dev;
        int i;
 
        for (i = 0; i < ARRAY_SIZE(vivi_qctrl); i++)
                if (ctrl->id == vivi_qctrl[i].id) {
-                       ctrl->value = qctl_regs[i];
-                       return (0);
+                       ctrl->value = dev->qctl_regs[i];
+                       return 0;
                }
 
        return -EINVAL;
@@ -1107,16 +1127,18 @@ static int vidioc_s_ctrl(struct file *fi
 static int vidioc_s_ctrl(struct file *file, void *priv,
                                struct v4l2_control *ctrl)
 {
+       struct vivi_fh *fh = priv;
+       struct vivi_dev *dev = fh->dev;
        int i;
 
        for (i = 0; i < ARRAY_SIZE(vivi_qctrl); i++)
                if (ctrl->id == vivi_qctrl[i].id) {
-                       if (ctrl->value < vivi_qctrl[i].minimum
-                           || ctrl->value > vivi_qctrl[i].maximum) {
-                                       return (-ERANGE);
-                               }
-                       qctl_regs[i] = ctrl->value;
-                       return (0);
+                       if (ctrl->value < vivi_qctrl[i].minimum ||
+                           ctrl->value > vivi_qctrl[i].maximum) {
+                               return -ERANGE;
+                       }
+                       dev->qctl_regs[i] = ctrl->value;
+                       return 0;
                }
        return -EINVAL;
 }
@@ -1127,32 +1149,20 @@ static int vidioc_s_ctrl(struct file *fi
 
 static int vivi_open(struct file *file)
 {
-       int minor = video_devdata(file)->minor;
-       struct vivi_dev *dev;
+       struct vivi_dev *dev = video_drvdata(file);
        struct vivi_fh *fh = NULL;
-       int i;
        int retval = 0;
 
-       printk(KERN_DEBUG "vivi: open called (minor=%d)\n", minor);
-
-       lock_kernel();
-       list_for_each_entry(dev, &vivi_devlist, vivi_devlist)
-               if (dev->vfd->minor == minor)
-                       goto found;
-       unlock_kernel();
-       return -ENODEV;
-
-found:
        mutex_lock(&dev->mutex);
        dev->users++;
 
        if (dev->users > 1) {
                dev->users--;
-               retval = -EBUSY;
-               goto unlock;
-       }
-
-       dprintk(dev, 1, "open minor=%d type=%s users=%d\n", minor,
+               mutex_unlock(&dev->mutex);
+               return -EBUSY;
+       }
+
+       dprintk(dev, 1, "open /dev/video%d type=%s users=%d\n", dev->vfd->num,
                v4l2_type_names[V4L2_BUF_TYPE_VIDEO_CAPTURE], dev->users);
 
        /* allocate + initialize per filehandle data */
@@ -1160,14 +1170,11 @@ found:
        if (NULL == fh) {
                dev->users--;
                retval = -ENOMEM;
-               goto unlock;
-       }
-unlock:
+       }
        mutex_unlock(&dev->mutex);
-       if (retval) {
-               unlock_kernel();
+
+       if (retval)
                return retval;
-       }
 
        file->private_data = fh;
        fh->dev      = dev;
@@ -1176,10 +1183,6 @@ unlock:
        fh->fmt      = &formats[0];
        fh->width    = 640;
        fh->height   = 480;
-
-       /* Put all controls at a sane state */
-       for (i = 0; i < ARRAY_SIZE(vivi_qctrl); i++)
-               qctl_regs[i] = vivi_qctrl[i].default_value;
 
        /* Resets frame counters */
        dev->h = 0;
@@ -1196,7 +1199,6 @@ unlock:
                        sizeof(struct vivi_buffer), fh);
 
        vivi_start_thread(fh);
-       unlock_kernel();
 
        return 0;
 }
@@ -1248,32 +1250,6 @@ static int vivi_close(struct file *file)
 
        dprintk(dev, 1, "close called (minor=%d, users=%d)\n",
                minor, dev->users);
-
-       return 0;
-}
-
-static int vivi_release(void)
-{
-       struct vivi_dev *dev;
-       struct list_head *list;
-
-       while (!list_empty(&vivi_devlist)) {
-               list = vivi_devlist.next;
-               list_del(list);
-               dev = list_entry(list, struct vivi_dev, vivi_devlist);
-
-               if (-1 != dev->vfd->minor) {
-                       printk(KERN_INFO "%s: unregistering /dev/video%d\n",
-                               VIVI_MODULE_NAME, dev->vfd->num);
-                       video_unregister_device(dev->vfd);
-               } else {
-                       printk(KERN_INFO "%s: releasing /dev/video%d\n",
-                               VIVI_MODULE_NAME, dev->vfd->num);
-                       video_device_release(dev->vfd);
-               }
-
-               kfree(dev);
-       }
 
        return 0;
 }
@@ -1340,87 +1316,130 @@ static struct video_device vivi_template
        .tvnorms              = V4L2_STD_525_60,
        .current_norm         = V4L2_STD_NTSC_M,
 };
+
 /* -----------------------------------------------------------------
        Initialization and module stuff
    ------------------------------------------------------------------*/
 
+static int vivi_release(void)
+{
+       struct vivi_dev *dev;
+       struct list_head *list;
+
+       while (!list_empty(&vivi_devlist)) {
+               list = vivi_devlist.next;
+               list_del(list);
+               dev = list_entry(list, struct vivi_dev, vivi_devlist);
+
+               v4l2_info(&dev->v4l2_dev, "unregistering /dev/video%d\n",
+                       dev->vfd->num);
+               video_unregister_device(dev->vfd);
+               v4l2_device_unregister(&dev->v4l2_dev);
+               kfree(dev);
+       }
+
+       return 0;
+}
+
+static int __init vivi_create_instance(int inst)
+{
+       struct vivi_dev *dev;
+       struct video_device *vfd;
+       int ret, i;
+
+       dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+       if (!dev)
+               return -ENOMEM;
+
+       snprintf(dev->v4l2_dev.name, sizeof(dev->v4l2_dev.name),
+                       "%s-%03d", VIVI_MODULE_NAME, inst);
+       ret = v4l2_device_register(NULL, &dev->v4l2_dev);
+       if (ret)
+               goto free_dev;
+
+       /* init video dma queues */
+       INIT_LIST_HEAD(&dev->vidq.active);
+       init_waitqueue_head(&dev->vidq.wq);
+
+       /* initialize locks */
+       spin_lock_init(&dev->slock);
+       mutex_init(&dev->mutex);
+
+       ret = -ENOMEM;
+       vfd = video_device_alloc();
+       if (!vfd)
+               goto unreg_dev;
+
+       *vfd = vivi_template;
+
+       ret = video_register_device(vfd, VFL_TYPE_GRABBER, video_nr);
+       if (ret < 0)
+               goto rel_vdev;
+
+       video_set_drvdata(vfd, dev);
+
+       /* Set all controls to their default value. */
+       for (i = 0; i < ARRAY_SIZE(vivi_qctrl); i++)
+               dev->qctl_regs[i] = vivi_qctrl[i].default_value;
+
+       /* Now that everything is fine, let's add it to device list */
+       list_add_tail(&dev->vivi_devlist, &vivi_devlist);
+
+       snprintf(vfd->name, sizeof(vfd->name), "%s (%i)",
+                       vivi_template.name, vfd->num);
+
+       if (video_nr >= 0)
+               video_nr++;
+
+       dev->vfd = vfd;
+       v4l2_info(&dev->v4l2_dev, "V4L2 device registered as /dev/video%d\n",
+                       vfd->num);
+       return 0;
+
+rel_vdev:
+       video_device_release(vfd);
+unreg_dev:
+       v4l2_device_unregister(&dev->v4l2_dev);
+free_dev:
+       kfree(dev);
+       return ret;
+}
+
 /* This routine allocates from 1 to n_devs virtual drivers.
 
    The real maximum number of virtual drivers will depend on how many drivers
    will succeed. This is limited to the maximum number of devices that
-   videodev supports. Since there are 64 minors for video grabbers, this is
-   currently the theoretical maximum limit. However, a further limit does
-   exist at videodev that forbids any driver to register more than 32 video
-   grabbers.
+   videodev supports, which is equal to VIDEO_NUM_DEVICES.
  */
 static int __init vivi_init(void)
 {
-       int ret = -ENOMEM, i;
-       struct vivi_dev *dev;
-       struct video_device *vfd;
+       int ret, i;
 
        if (n_devs <= 0)
                n_devs = 1;
 
        for (i = 0; i < n_devs; i++) {
-               dev = kzalloc(sizeof(*dev), GFP_KERNEL);
-               if (!dev)
-                       break;
-
-               /* init video dma queues */
-               INIT_LIST_HEAD(&dev->vidq.active);
-               init_waitqueue_head(&dev->vidq.wq);
-
-               /* initialize locks */
-               spin_lock_init(&dev->slock);
-               mutex_init(&dev->mutex);
-
-               vfd = video_device_alloc();
-               if (!vfd) {
-                       kfree(dev);
+               ret = vivi_create_instance(i);
+               if (ret) {
+                       /* If some instantiations succeeded, keep driver */
+                       if (i)
+                               ret = 0;
                        break;
                }
-
-               *vfd = vivi_template;
-
-               ret = video_register_device(vfd, VFL_TYPE_GRABBER, video_nr);
-               if (ret < 0) {
-                       video_device_release(vfd);
-                       kfree(dev);
-
-                       /* If some registers succeeded, keep driver */
-                       if (i)
-                               ret = 0;
-
-                       break;
-               }
-
-               /* Now that everything is fine, let's add it to device list */
-               list_add_tail(&dev->vivi_devlist, &vivi_devlist);
-
-               snprintf(vfd->name, sizeof(vfd->name), "%s (%i)",
-                        vivi_template.name, vfd->minor);
-
-               if (video_nr >= 0)
-                       video_nr++;
-
-               dev->vfd = vfd;
-               printk(KERN_INFO "%s: V4L2 device registered as /dev/video%d\n",
-                       VIVI_MODULE_NAME, vfd->num);
        }
 
        if (ret < 0) {
-               vivi_release();
                printk(KERN_INFO "Error %d while loading vivi driver\n", ret);
-       } else {
-               printk(KERN_INFO "Video Technology Magazine Virtual Video "
+               return ret;
+       }
+
+       printk(KERN_INFO "Video Technology Magazine Virtual Video "
                        "Capture Board ver %u.%u.%u successfully loaded.\n",
                        (VIVI_VERSION >> 16) & 0xFF, (VIVI_VERSION >> 8) & 0xFF,
                        VIVI_VERSION & 0xFF);
 
-               /* n_devs will reflect the actual number of allocated devices */
-               n_devs = i;
-       }
+       /* n_devs will reflect the actual number of allocated devices */
+       n_devs = i;
 
        return ret;
 }
@@ -1432,19 +1451,3 @@ static void __exit vivi_exit(void)
 
 module_init(vivi_init);
 module_exit(vivi_exit);
-
-MODULE_DESCRIPTION("Video Technology Magazine Virtual Video Capture Board");
-MODULE_AUTHOR("Mauro Carvalho Chehab, Ted Walther and John Sokol");
-MODULE_LICENSE("Dual BSD/GPL");
-
-module_param(video_nr, uint, 0444);
-MODULE_PARM_DESC(video_nr, "video iminor start number");
-
-module_param(n_devs, uint, 0444);
-MODULE_PARM_DESC(n_devs, "number of video devices to create");
-
-module_param_named(debug, vivi_template.debug, int, 0444);
-MODULE_PARM_DESC(debug, "activates debug info");
-
-module_param(vid_limit, int, 0644);
-MODULE_PARM_DESC(vid_limit, "capture memory limit in megabytes");
diff -r 4f6c3f9efa58 -r e471b963bef6 linux/include/media/v4l2-device.h
--- a/linux/include/media/v4l2-device.h Tue Feb 17 23:32:03 2009 -0300
+++ b/linux/include/media/v4l2-device.h Tue Feb 17 23:44:45 2009 -0300
@@ -33,7 +33,9 @@
 #define V4L2_DEVICE_NAME_SIZE (BUS_ID_SIZE + 16)
 
 struct v4l2_device {
-       /* dev->driver_data points to this struct */
+       /* dev->driver_data points to this struct.
+          Note: dev might be NULL if there is no parent device
+          as is the case with e.g. ISA devices. */
        struct device *dev;
        /* used to keep track of the registered subdevs */
        struct list_head subdevs;
@@ -44,7 +46,9 @@ struct v4l2_device {
        char name[V4L2_DEVICE_NAME_SIZE];
 };
 
-/* Initialize v4l2_dev and make dev->driver_data point to v4l2_dev */
+/* Initialize v4l2_dev and make dev->driver_data point to v4l2_dev.
+   dev may be NULL in rare cases (ISA devices). In that case you
+   must fill in the v4l2_dev->name field before calling this function. */
 int __must_check v4l2_device_register(struct device *dev, struct v4l2_device 
*v4l2_dev);
 /* Set v4l2_dev->dev->driver_data to NULL and unregister all sub-devices */
 void v4l2_device_unregister(struct v4l2_device *v4l2_dev);
@@ -52,23 +56,24 @@ void v4l2_device_unregister(struct v4l2_
 /* Register a subdev with a v4l2 device. While registered the subdev module
    is marked as in-use. An error is returned if the module is no longer
    loaded when you attempt to register it. */
-int __must_check v4l2_device_register_subdev(struct v4l2_device *dev, struct 
v4l2_subdev *sd);
+int __must_check v4l2_device_register_subdev(struct v4l2_device *v4l2_dev,
+                                               struct v4l2_subdev *sd);
 /* Unregister a subdev with a v4l2 device. Can also be called if the subdev
    wasn't registered. In that case it will do nothing. */
 void v4l2_device_unregister_subdev(struct v4l2_subdev *sd);
 
 /* Iterate over all subdevs. */
-#define v4l2_device_for_each_subdev(sd, dev)                           \
-       list_for_each_entry(sd, &(dev)->subdevs, list)
+#define v4l2_device_for_each_subdev(sd, v4l2_dev)                      \
+       list_for_each_entry(sd, &(v4l2_dev)->subdevs, list)
 
 /* Call the specified callback for all subdevs matching the condition.
    Ignore any errors. Note that you cannot add or delete a subdev
    while walking the subdevs list. */
-#define __v4l2_device_call_subdevs(dev, cond, o, f, args...)           \
+#define __v4l2_device_call_subdevs(v4l2_dev, cond, o, f, args...)      \
        do {                                                            \
                struct v4l2_subdev *sd;                                 \
                                                                        \
-               list_for_each_entry(sd, &(dev)->subdevs, list)          \
+               list_for_each_entry(sd, &(v4l2_dev)->subdevs, list)     \
                        if ((cond) && sd->ops->o && sd->ops->o->f)      \
                                sd->ops->o->f(sd , ##args);             \
        } while (0)
@@ -77,12 +82,12 @@ void v4l2_device_unregister_subdev(struc
    If the callback returns an error other than 0 or -ENOIOCTLCMD, then
    return with that error code. Note that you cannot add or delete a
    subdev while walking the subdevs list. */
-#define __v4l2_device_call_subdevs_until_err(dev, cond, o, f, args...)  \
+#define __v4l2_device_call_subdevs_until_err(v4l2_dev, cond, o, f, args...) \
 ({                                                                     \
        struct v4l2_subdev *sd;                                         \
        long err = 0;                                                   \
                                                                        \
-       list_for_each_entry(sd, &(dev)->subdevs, list) {                \
+       list_for_each_entry(sd, &(v4l2_dev)->subdevs, list) {           \
                if ((cond) && sd->ops->o && sd->ops->o->f)              \
                        err = sd->ops->o->f(sd , ##args);               \
                if (err && err != -ENOIOCTLCMD)                         \
@@ -94,16 +99,16 @@ void v4l2_device_unregister_subdev(struc
 /* Call the specified callback for all subdevs matching grp_id (if 0, then
    match them all). Ignore any errors. Note that you cannot add or delete
    a subdev while walking the subdevs list. */
-#define v4l2_device_call_all(dev, grpid, o, f, args...)                \
-       __v4l2_device_call_subdevs(dev,                                 \
+#define v4l2_device_call_all(v4l2_dev, grpid, o, f, args...)           \
+       __v4l2_device_call_subdevs(v4l2_dev,                            \
                        !(grpid) || sd->grp_id == (grpid), o, f , ##args)
 
 /* Call the specified callback for all subdevs matching grp_id (if 0, then
    match them all). If the callback returns an error other than 0 or
    -ENOIOCTLCMD, then return with that error code. Note that you cannot
    add or delete a subdev while walking the subdevs list. */
-#define v4l2_device_call_until_err(dev, grpid, o, f, args...)          \
-       __v4l2_device_call_subdevs_until_err(dev,                       \
+#define v4l2_device_call_until_err(v4l2_dev, grpid, o, f, args...)     \
+       __v4l2_device_call_subdevs_until_err(v4l2_dev,                  \
                       !(grpid) || sd->grp_id == (grpid), o, f , ##args)
 
 #endif
diff -r 4f6c3f9efa58 -r e471b963bef6 linux/include/media/v4l2-subdev.h
--- a/linux/include/media/v4l2-subdev.h Tue Feb 17 23:32:03 2009 -0300
+++ b/linux/include/media/v4l2-subdev.h Tue Feb 17 23:44:45 2009 -0300
@@ -137,7 +137,7 @@ struct v4l2_subdev {
 struct v4l2_subdev {
        struct list_head list;
        struct module *owner;
-       struct v4l2_device *dev;
+       struct v4l2_device *v4l2_dev;
        const struct v4l2_subdev_ops *ops;
        /* name must be unique */
        char name[V4L2_SUBDEV_NAME_SIZE];
@@ -176,7 +176,7 @@ static inline void v4l2_subdev_init(stru
        /* ops->core MUST be set */
        BUG_ON(!ops || !ops->core);
        sd->ops = ops;
-       sd->dev = NULL;
+       sd->v4l2_dev = NULL;
        sd->name[0] = '\0';
        sd->grp_id = 0;
        sd->priv = NULL;


---

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

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

Reply via email to