视频驱动V4L2子系统驱动架构 - 驱动框架

文章系列

视频驱动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子系统驱动架构 - 驱动框架_第1张图片

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 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);
};

函数介绍:

//注册函数
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;
#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;
};
每个模块对应的实现函数
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);

你可能感兴趣的:(Linux驱动)