文章系列
视频驱动V4L2子系统驱动架构 - 驱动框架
视频驱动V4L2子系统驱动架构 - ioctl
基于linux4.6.3
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;
};
函数介绍:
//注册函数
static inline int __must_check video_register_device(struct video_device *vdev,int type, int nr)
//卸载函数
void video_unregister_device(struct video_device *vdev);
v4l2_device
对应子模块的实现,包含多个子模块
struct v4l2_device {/* dev->driver_data points to this struct.Note: dev might be NULL if there is no parent deviceas 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 thisstruct 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);
};
函数介绍:
//注册函数
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);
v4l2_subdev
具体子模块的实现
struct v4l2_subdev {
#if defined(CONFIG_MEDIA_CONTROLLER)struct media_entity entity;
#endifstruct 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;
};
每个模块对应的实现函数
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;
};
函数介绍:
//注册函数
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);