mirror of
https://github.com/FEX-Emu/linux.git
synced 2024-12-26 03:17:48 +00:00
8ab75e3ecd
Using the V4L2 core lock is a very robust method that is usually very good at doing the right thing. But some drivers, particularly USB drivers, may want to prevent the core from taking the lock for specific ioctls, particularly buffer queuing ioctls. The reason is that certain commands like S_CTRL can take a long time to process over USB and all the time the core has the lock, preventing VIDIOC_DQBUF from proceeding, even though a frame may be ready in the queue. This introduces unwanted latency. Since the buffer queuing commands often have their own internal lock it is often not necessary to take the core lock. Drivers can now say that they don't want the core to take the lock for specific ioctls. As it is a specific opt-out it makes it clear to the reviewer that those ioctls will need more care when reviewing. Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com> Acked-by: Hans de Goede <hdegoede@redhat.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
218 lines
6.6 KiB
C
218 lines
6.6 KiB
C
/*
|
|
*
|
|
* V 4 L 2 D R I V E R H E L P E R A P I
|
|
*
|
|
* Moved from videodev2.h
|
|
*
|
|
* Some commonly needed functions for drivers (v4l2-common.o module)
|
|
*/
|
|
#ifndef _V4L2_DEV_H
|
|
#define _V4L2_DEV_H
|
|
|
|
#include <linux/poll.h>
|
|
#include <linux/fs.h>
|
|
#include <linux/device.h>
|
|
#include <linux/cdev.h>
|
|
#include <linux/mutex.h>
|
|
#include <linux/videodev2.h>
|
|
|
|
#include <media/media-entity.h>
|
|
|
|
#define VIDEO_MAJOR 81
|
|
|
|
#define VFL_TYPE_GRABBER 0
|
|
#define VFL_TYPE_VBI 1
|
|
#define VFL_TYPE_RADIO 2
|
|
#define VFL_TYPE_SUBDEV 3
|
|
#define VFL_TYPE_MAX 4
|
|
|
|
struct v4l2_ioctl_callbacks;
|
|
struct video_device;
|
|
struct v4l2_device;
|
|
struct v4l2_ctrl_handler;
|
|
|
|
/* Flag to mark the video_device struct as registered.
|
|
Drivers can clear this flag if they want to block all future
|
|
device access. It is cleared by video_unregister_device. */
|
|
#define V4L2_FL_REGISTERED (0)
|
|
/* file->private_data points to struct v4l2_fh */
|
|
#define V4L2_FL_USES_V4L2_FH (1)
|
|
/* Use the prio field of v4l2_fh for core priority checking */
|
|
#define V4L2_FL_USE_FH_PRIO (2)
|
|
|
|
/* Priority helper functions */
|
|
|
|
struct v4l2_prio_state {
|
|
atomic_t prios[4];
|
|
};
|
|
|
|
void v4l2_prio_init(struct v4l2_prio_state *global);
|
|
int v4l2_prio_change(struct v4l2_prio_state *global, enum v4l2_priority *local,
|
|
enum v4l2_priority new);
|
|
void v4l2_prio_open(struct v4l2_prio_state *global, enum v4l2_priority *local);
|
|
void v4l2_prio_close(struct v4l2_prio_state *global, enum v4l2_priority local);
|
|
enum v4l2_priority v4l2_prio_max(struct v4l2_prio_state *global);
|
|
int v4l2_prio_check(struct v4l2_prio_state *global, enum v4l2_priority local);
|
|
|
|
|
|
struct v4l2_file_operations {
|
|
struct module *owner;
|
|
ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);
|
|
ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);
|
|
unsigned int (*poll) (struct file *, struct poll_table_struct *);
|
|
long (*ioctl) (struct file *, unsigned int, unsigned long);
|
|
long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);
|
|
#ifdef CONFIG_COMPAT
|
|
long (*compat_ioctl32) (struct file *, unsigned int, unsigned long);
|
|
#endif
|
|
unsigned long (*get_unmapped_area) (struct file *, unsigned long,
|
|
unsigned long, unsigned long, unsigned long);
|
|
int (*mmap) (struct file *, struct vm_area_struct *);
|
|
int (*open) (struct file *);
|
|
int (*release) (struct file *);
|
|
};
|
|
|
|
/*
|
|
* Newer version of video_device, handled by videodev2.c
|
|
* This version moves redundant code from video device code to
|
|
* the common handler
|
|
*/
|
|
|
|
struct video_device
|
|
{
|
|
#if defined(CONFIG_MEDIA_CONTROLLER)
|
|
struct media_entity entity;
|
|
#endif
|
|
/* device ops */
|
|
const struct v4l2_file_operations *fops;
|
|
|
|
/* sysfs */
|
|
struct device dev; /* v4l device */
|
|
struct cdev *cdev; /* character device */
|
|
|
|
/* Set either parent or v4l2_dev if your driver uses v4l2_device */
|
|
struct device *parent; /* device parent */
|
|
struct v4l2_device *v4l2_dev; /* v4l2_device parent */
|
|
|
|
/* Control handler associated with this device node. May be NULL. */
|
|
struct v4l2_ctrl_handler *ctrl_handler;
|
|
|
|
/* Priority state. If NULL, then v4l2_dev->prio will be used. */
|
|
struct v4l2_prio_state *prio;
|
|
|
|
/* device info */
|
|
char name[32];
|
|
int vfl_type;
|
|
/* 'minor' is set to -1 if the registration failed */
|
|
int minor;
|
|
u16 num;
|
|
/* use bitops to set/clear/test flags */
|
|
unsigned long flags;
|
|
/* attribute to differentiate multiple indices on one physical device */
|
|
int index;
|
|
|
|
/* V4L2 file handles */
|
|
spinlock_t fh_lock; /* Lock for all v4l2_fhs */
|
|
struct list_head fh_list; /* List of struct v4l2_fh */
|
|
|
|
int debug; /* Activates debug level*/
|
|
|
|
/* Video standard vars */
|
|
v4l2_std_id tvnorms; /* Supported tv norms */
|
|
v4l2_std_id current_norm; /* Current tvnorm */
|
|
|
|
/* callbacks */
|
|
void (*release)(struct video_device *vdev);
|
|
|
|
/* ioctl callbacks */
|
|
const struct v4l2_ioctl_ops *ioctl_ops;
|
|
|
|
/* serialization lock */
|
|
DECLARE_BITMAP(dont_use_lock, BASE_VIDIOC_PRIVATE);
|
|
struct mutex *lock;
|
|
};
|
|
|
|
#define media_entity_to_video_device(__e) \
|
|
container_of(__e, struct video_device, entity)
|
|
/* dev to video-device */
|
|
#define to_video_device(cd) container_of(cd, struct video_device, dev)
|
|
|
|
int __must_check __video_register_device(struct video_device *vdev, int type,
|
|
int nr, int warn_if_nr_in_use, struct module *owner);
|
|
|
|
/* Register video devices. Note that if video_register_device fails,
|
|
the release() callback of the video_device structure is *not* called, so
|
|
the caller is responsible for freeing any data. Usually that means that
|
|
you call video_device_release() on failure. */
|
|
static inline int __must_check video_register_device(struct video_device *vdev,
|
|
int type, int nr)
|
|
{
|
|
return __video_register_device(vdev, type, nr, 1, vdev->fops->owner);
|
|
}
|
|
|
|
/* Same as video_register_device, but no warning is issued if the desired
|
|
device node number was already in use. */
|
|
static inline int __must_check video_register_device_no_warn(
|
|
struct video_device *vdev, int type, int nr)
|
|
{
|
|
return __video_register_device(vdev, type, nr, 0, vdev->fops->owner);
|
|
}
|
|
|
|
/* Unregister video devices. Will do nothing if vdev == NULL or
|
|
video_is_registered() returns false. */
|
|
void video_unregister_device(struct video_device *vdev);
|
|
|
|
/* helper functions to alloc/release struct video_device, the
|
|
latter can also be used for video_device->release(). */
|
|
struct video_device * __must_check video_device_alloc(void);
|
|
|
|
/* this release function frees the vdev pointer */
|
|
void video_device_release(struct video_device *vdev);
|
|
|
|
/* this release function does nothing, use when the video_device is a
|
|
static global struct. Note that having a static video_device is
|
|
a dubious construction at best. */
|
|
void video_device_release_empty(struct video_device *vdev);
|
|
|
|
/* returns true if cmd is a known V4L2 ioctl */
|
|
bool v4l2_is_known_ioctl(unsigned int cmd);
|
|
|
|
/* mark that this command shouldn't use core locking */
|
|
static inline void v4l2_dont_use_lock(struct video_device *vdev, unsigned int cmd)
|
|
{
|
|
if (_IOC_NR(cmd) < BASE_VIDIOC_PRIVATE)
|
|
set_bit(_IOC_NR(cmd), vdev->dont_use_lock);
|
|
}
|
|
|
|
/* helper functions to access driver private data. */
|
|
static inline void *video_get_drvdata(struct video_device *vdev)
|
|
{
|
|
return dev_get_drvdata(&vdev->dev);
|
|
}
|
|
|
|
static inline void video_set_drvdata(struct video_device *vdev, void *data)
|
|
{
|
|
dev_set_drvdata(&vdev->dev, data);
|
|
}
|
|
|
|
struct video_device *video_devdata(struct file *file);
|
|
|
|
/* Combine video_get_drvdata and video_devdata as this is
|
|
used very often. */
|
|
static inline void *video_drvdata(struct file *file)
|
|
{
|
|
return video_get_drvdata(video_devdata(file));
|
|
}
|
|
|
|
static inline const char *video_device_node_name(struct video_device *vdev)
|
|
{
|
|
return dev_name(&vdev->dev);
|
|
}
|
|
|
|
static inline int video_is_registered(struct video_device *vdev)
|
|
{
|
|
return test_bit(V4L2_FL_REGISTERED, &vdev->flags);
|
|
}
|
|
|
|
#endif /* _V4L2_DEV_H */
|