mirror of
https://github.com/torvalds/linux.git
synced 2024-11-01 17:51:43 +00:00
V4L/DVB (10645): vivi: introduce v4l2_device and do several cleanups
- add v4l2_device - remove BKL - make the debug parameter settable on the fly - set bus_info in querycap Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
This commit is contained in:
parent
b016760054
commit
5ab6c9af37
@ -33,12 +33,13 @@
|
||||
#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>
|
||||
#include <linux/freezer.h>
|
||||
#include <media/videobuf-vmalloc.h>
|
||||
#include <media/v4l2-device.h>
|
||||
#include <media/v4l2-ioctl.h>
|
||||
#include "font.h"
|
||||
|
||||
#define VIVI_MODULE_NAME "vivi"
|
||||
|
||||
@ -47,18 +48,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[] = {
|
||||
@ -112,11 +127,8 @@ static struct v4l2_queryctrl vivi_qctrl[] = {
|
||||
|
||||
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)
|
||||
#define dprintk(dev, level, fmt, arg...) \
|
||||
v4l2_dbg(level, debug, &dev->v4l2_dev, fmt, ## arg)
|
||||
|
||||
/* ------------------------------------------------------------------
|
||||
Basic structures
|
||||
@ -206,6 +218,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;
|
||||
@ -656,7 +669,7 @@ static int vivi_start_thread(struct vivi_fh *fh)
|
||||
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 */
|
||||
@ -799,8 +812,12 @@ static struct videobuf_queue_ops vivi_video_qops = {
|
||||
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 |
|
||||
@ -1124,32 +1141,21 @@ static int vidioc_s_ctrl(struct file *file, void *priv,
|
||||
|
||||
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;
|
||||
mutex_unlock(&dev->mutex);
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
dprintk(dev, 1, "open minor=%d type=%s users=%d\n", minor,
|
||||
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 */
|
||||
@ -1157,14 +1163,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;
|
||||
@ -1193,7 +1196,6 @@ unlock:
|
||||
sizeof(struct vivi_buffer), fh);
|
||||
|
||||
vivi_start_thread(fh);
|
||||
unlock_kernel();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -1249,32 +1251,6 @@ static int vivi_close(struct file *file)
|
||||
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;
|
||||
}
|
||||
|
||||
static int vivi_mmap(struct file *file, struct vm_area_struct *vma)
|
||||
{
|
||||
struct vivi_fh *fh = file->private_data;
|
||||
@ -1337,10 +1313,91 @@ 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 i)
|
||||
{
|
||||
struct vivi_dev *dev;
|
||||
struct video_device *vfd;
|
||||
int ret;
|
||||
|
||||
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, i);
|
||||
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);
|
||||
|
||||
/* 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
|
||||
@ -1349,72 +1406,33 @@ static struct video_device vivi_template = {
|
||||
*/
|
||||
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);
|
||||
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 */
|
||||
ret = vivi_create_instance(i);
|
||||
if (ret) {
|
||||
/* If some instantiations 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;
|
||||
}
|
||||
@ -1426,19 +1444,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");
|
||||
|
Loading…
Reference in New Issue
Block a user