视频驱动V4L2子系统驱动架构 - 驱动框架
V4L2驱动框架
v4l2驱动架构如图所示,v4l2也就是video for linux two,那么也就是说还有One了,v4l2前面还有v4l
图中芯片模块对应Soc的各个子模块,video_device结构体主要用来控制Soc的video模块,v4l2_device会包含多个v4l2_subdev ,每个v4l2_subdev 用来控制各自的子模块,某些驱动不需要v4l2_subdev ,依靠video模块就能实现功能
v4l2驱动代码在drivers\media\v4l2-core文件夹下,文件看起来很多,但是根据字面意思来理解基本的功能都了解差不多了。videobuf是实现视频的内存分配的,对于v4l2和v4l分别对应不同的文件,如videobuf-core和videobuf2-core;v4l2-dev,v4l2-device,v4l2-subdev分别对应video_device,v4l2_device ,v4l2_subdev 的实现;v4l2-ioctl是实现ioctl等等。
video驱动代码在driver/media/目录下,下面分好多子目录,platform目录存放的是不同SoC的驱动代码,对应video_device,其他大多子目录如i2c、mmc、usb、tuners、radio等对应subdev的实现
v4l2驱动框架最重要的是理解ioctl,本文章系列另一篇会详细介绍,另外v4l2驱动框架最主要的是各个ioctl实现的功能,这些实现方式需要在实际操作中多加理解,不是难点。
V4L2 core介绍
video_device
用于实现SoC的video模块
struct video_device
{
#if defined(CONFIG_MEDIA_CONTROLLER)
struct media_entity entity;
struct media_intf_devnode *intf_devnode;
struct media_pipeline pipe;
#endif
/* device ops */
const struct v4l2_file_operations *fops;--------------------------具体video模块实现函数
/* sysfs */
struct device dev; /* v4l device */
struct cdev *cdev; /* character device */--------------------上层接口
struct v4l2_device *v4l2_dev; /* v4l2_device parent */----------v4l2_device
/* Only set parent if that can't be deduced from v4l2_dev */
struct device *dev_parent; /* device parent */
/* Control handler associated with this device node. May be NULL. */
struct v4l2_ctrl_handler *ctrl_handler;
/* vb2_queue associated with this device node. May be NULL. */
struct vb2_queue *queue;
/* Priority state. If NULL, then v4l2_dev->prio will be used. */
struct v4l2_prio_state *prio;
/* device info */
char name[32];
int vfl_type; /* device type */
int vfl_dir; /* receiver, transmitter or m2m */
/* 'minor' is set to -1 if the registration failed */
int minor;--------------------------------------------------------video-x的次设备号
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 */
/* Internal device debug flags, not for use by drivers */
int dev_debug;
/* Video standard vars */
v4l2_std_id tvnorms; /* Supported tv norms */
/* callbacks */
void (*release)(struct video_device *vdev);
/* ioctl callbacks */
const struct v4l2_ioctl_ops *ioctl_ops;-------------------------具体功能的实现函数
DECLARE_BITMAP(valid_ioctls, BASE_VIDIOC_PRIVATE);
/* serialization lock */
DECLARE_BITMAP(disable_locking, BASE_VIDIOC_PRIVATE);
struct mutex *lock;
};
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
函数介绍:
//注册函数
static inline int __must_check video_register_device(struct video_device *vdev,
int type, int nr)
//卸载函数
void video_unregister_device(struct video_device *vdev);
- 1
- 2
- 3
- 4
- 5
v4l2_device
对应子模块的实现,包含多个子模块
struct v4l2_device {
/* 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;
#if defined(CONFIG_MEDIA_CONTROLLER)
struct media_device *mdev;
#endif
/* used to keep track of the registered subdevs */
struct list_head subdevs;
/* lock this struct; can be used by the driver as well if this
struct is embedded into a larger struct. */
spinlock_t lock;
/* unique device name, by default the driver name + bus ID */
char name[V4L2_DEVICE_NAME_SIZE];
/* notify callback called by some sub-devices. */
void (*notify)(struct v4l2_subdev *sd,
unsigned int notification, void *arg);
/* The control handler. May be NULL. */
struct v4l2_ctrl_handler *ctrl_handler;
/* Device's priority state */
struct v4l2_prio_state prio;
/* Keep track of the references to this struct. */
struct kref ref;
/* Release function that is called when the ref count goes to 0. */
void (*release)(struct v4l2_device *v4l2_dev);
};
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
函数介绍:
//注册函数
int __must_check v4l2_device_register(struct device *dev, struct v4l2_device *v4l2_dev);
int __must_check v4l2_device_register_subdev(struct v4l2_device *v4l2_dev,
struct v4l2_subdev *sd);
//卸载函数
void v4l2_device_unregister(struct v4l2_device *v4l2_dev);
int __must_check v4l2_device_register_subdev(struct v4l2_device *v4l2_dev,
struct v4l2_subdev *sd);
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
v4l2_subdev
具体子模块的实现
struct v4l2_subdev {
#if defined(CONFIG_MEDIA_CONTROLLER)
struct media_entity entity;
#endif
struct list_head list;
struct module *owner;
bool owner_v4l2_dev;
u32 flags;
struct v4l2_device *v4l2_dev;
const struct v4l2_subdev_ops *ops;--------------------------功能实现函数
/* Never call these internal ops from within a driver! */
const struct v4l2_subdev_internal_ops *internal_ops;
/* The control handler of this subdev. May be NULL. */
struct v4l2_ctrl_handler *ctrl_handler;
/* name must be unique */
char name[V4L2_SUBDEV_NAME_SIZE];
/* can be used to group similar subdevs, value is driver-specific */
u32 grp_id;
/* pointer to private data */
void *dev_priv;
void *host_priv;
/* subdev device node */
struct video_device *devnode;
/* pointer to the physical device, if any */
struct device *dev;
/* The device_node of the subdev, usually the same as dev->of_node. */
struct device_node *of_node;
/* Links this subdev to a global subdev_list or @notifier->done list. */
struct list_head async_list;
/* Pointer to respective struct v4l2_async_subdev. */
struct v4l2_async_subdev *asd;
/* Pointer to the managing notifier. */
struct v4l2_async_notifier *notifier;
/* common part of subdevice platform data */
struct v4l2_subdev_platform_data *pdata;
};
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
每个模块对应的实现函数
struct v4l2_subdev_ops {
const struct v4l2_subdev_core_ops *core;
const struct v4l2_subdev_tuner_ops *tuner;
const struct v4l2_subdev_audio_ops *audio;
const struct v4l2_subdev_video_ops *video;
const struct v4l2_subdev_vbi_ops *vbi;
const struct v4l2_subdev_ir_ops *ir;
const struct v4l2_subdev_sensor_ops *sensor;
const struct v4l2_subdev_pad_ops *pad;
};
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
函数介绍:
//注册函数
struct v4l2_subdev *v4l2_i2c_new_subdev(struct v4l2_device *v4l2_dev,
struct i2c_adapter *adapter, const char *client_type,
u8 addr, const unsigned short *probe_addrs);
struct v4l2_subdev *v4l2_spi_new_subdev(struct v4l2_device *v4l2_dev,
struct spi_master *master, struct spi_board_info *info);
上一篇: STM32 基于HAL库的CAN配置
推荐阅读
-
视频驱动V4L2子系统驱动架构 - 驱动框架
-
嵌入式Linux驱动笔记(十九)------音频子系统(ASOC框架)之Machine
-
linux驱动input子系统学习二(框架)
-
Linux设备驱动之IIO子系统——IIO框架及IIO数据结构
-
Linux设备驱动之IIO子系统——IIO框架数据读取
-
Linux音频设备驱动_OSS驱动框架(二)————OSS驱动架构代码vmsnd.c
-
基于V4L2的视频驱动开发(2)
-
Linux设备驱动之IIO子系统——IIO框架数据读取
-
Linux设备驱动之IIO子系统——IIO框架及IIO数据结构
-
thinkPHP5.0框架整体架构总览【应用,模块,MVC,驱动,行为,命名空间等】