V4L2 -- Videobuf2

struct vb2_queue { unsigned int type; unsigned int io_modes; struct device *dev; unsigned long dma_attrs; unsigned int bidirectional:1; unsigned int fileio_read_once:1; unsigned int fileio_write_immediately:1; unsigned int allow_zero_bytesused:1; unsigned int quirk_poll_must_check_waiting_for_buffers:1; unsigned int supports_requests:1; unsigned int requires_requests:1; unsigned int uses_qbuf:1; unsigned int uses_requests:1; unsigned int allow_cache_hints:1; unsigned int non_coherent_mem:1; struct mutex *lock; void *owner; const struct vb2_ops *ops; const struct vb2_mem_ops *mem_ops; const struct vb2_buf_ops *buf_ops; void *drv_priv; u32 subsystem_flags; unsigned int buf_struct_size; u32 timestamp_flags; gfp_t gfp_flags; u32 min_queued_buffers; u32 min_reqbufs_allocation; struct device *alloc_devs[VB2_MAX_PLANES]; /* private: internal use only */ struct mutex mmap_lock; unsigned int memory; enum dma_data_direction dma_dir; struct vb2_buffer **bufs; unsigned long *bufs_bitmap; unsigned int max_num_buffers; struct list_head queued_list; unsigned int queued_count; atomic_t owned_by_drv_count; struct list_head done_list; spinlock_t done_lock; wait_queue_head_t done_wq; unsigned int streaming:1; unsigned int start_streaming_called:1; unsigned int error:1; unsigned int waiting_for_buffers:1; unsigned int waiting_in_dqbuf:1; unsigned int is_multiplanar:1; unsigned int is_output:1; unsigned int is_busy:1; unsigned int copy_timestamp:1; unsigned int last_buffer_dequeued:1; struct vb2_fileio_data *fileio; struct vb2_threadio_data *threadio; char name[32]; }; type: buffer 的类型,enum v4l2_buf_type, vendor driver 初始化时设置。...

2025-06-19 · 3 min

V4L2 -- Controls

2.15 V4L2 controls V4L2 controls 用于控制和调整视频设备的各种参数。 2.15.2 Objects in the framework struct v4l2_ctrl 描述了 control properties 和对应的 value. struct v4l2_ctrl_handler 用来跟踪 v4l2_ctrl objects. 2.15.3 Basic usage for V4L2 and sub-device drivers prepare the driver 通常把 v4l2_ctrl_handler 放在 top-level struct: // v4l2 drvier: struct foo_dev { ... struct v4l2_device v4l2_dev; ... struct v4l2_ctrl_handler ctrl_handler; ... }; // sub-dev driver: struct foo_dev { ... struct v4l2_subdev sd; ... struct v4l2_ctrl_handler ctrl_handler; ... }; 通过 v4l2_ctrl_handler_init(&foo->ctrl_handler, nr_of_controls) 初始化 v4l2_ctrl_handler....

2025-06-19 · 3 min

V4L2 -- Event

2.14 V4L2 events V4L2 events 提供了一种方法给 userspace 传递 events. struct v4l2_subscribed_event { struct list_head list; u32 type; u32 id; u32 flags; struct v4l2_fh *fh; struct list_head node; const struct v4l2_subscribed_event_ops *ops; unsigned int elems; unsigned int first; unsigned int in_use; struct v4l2_kevent events[] __counted_by(elems); }; list: 加入到 v4l2_fh->subscribed list 的链表节点。 type: event type, 在 videodev2.h 中定义。 id: event 的 control id, 根据 event 的 (type, id) 二元组就能找到对应的 event. flags: 从 userspace 传入的 v4l2_event_subscription->flags 中拷贝过来。...

2025-06-19 · 1 min

V4L2 -- Subdev

2.7 V4L2 sub-devices 许多 drivers 需要和 sub-devices 交流,这些子设备可以处理 audio, video muxing, encoding, decoding 等等。 对于 webcams, 常见的 sub-devices 有 sensors, camera controllers. 通过 v4l2_subdev_init(sd, &ops) 来初始化 v4l2_subdev. 接着需要设置 sd->name. 如果需要和 media framework 聚合,那么需要初始化 media_entity 成员,如果 entity 有 pads 还需要调用media_entity_pads_init. 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; const struct v4l2_subdev_internal_ops *internal_ops; struct v4l2_ctrl_handler *ctrl_handler; char name[52]; u32 grp_id; void *dev_priv; void *host_priv; struct video_device *devnode; struct device *dev; struct fwnode_handle *fwnode; struct list_head async_list; struct list_head async_subdev_endpoint_list; struct v4l2_async_notifier *subdev_notifier; struct list_head asc_list; struct v4l2_subdev_platform_data *pdata; struct mutex *state_lock; struct led_classdev *privacy_led; struct v4l2_subdev_state *active_state; u64 enabled_streams; }; owner_v4l2_dev: 如果和 v4l2_dev->dev 的 owner 一致,则为 true....

2025-06-19 · 6 min

V4L2 -- File Handler

2.6 V4L2 File handlers struct v4l2_fh 提供了一种方式,使得 file 方便地处理 V4L2 中的一些 specific data. 初始化:v4l2_fh_init(), 必须在 driver 的 v4l2_file_operations->open() 回调中调用, 会置起 video_device 的 V4L2_FL_USES_V4L2_FH flag. 在 userspace open device node 后,调用到 v4l2_fh_open, 会把 file->private_data 设置为 fh. 许多情况下 v4l2_fh 都会嵌入在更大的结构体中,这时需要调用 v4l2_fh_init() 和 v4l2_fh_add 在.open() 回调 v4l2_fh_del() 和 v4l2_fh_exit() 在.release() 回调 struct v4l2_fh { struct list_head list; struct video_device *vdev; struct v4l2_ctrl_handler *ctrl_handler; enum v4l2_priority prio; wait_queue_head_t wait; struct mutex subscribe_lock; struct list_head subscribed; struct list_head available; unsigned int navailable; u32 sequence; struct v4l2_m2m_ctx *m2m_ctx; }; list: 链接到 video_device 的 fh_list....

2025-06-19 · 1 min

V4L2 -- V4L2 Device

2.5 V4L2 device v4l2 用来抽象最顶层的 v4l2 设备,包含一系列子设备。 通过v4l2_device_register(dev, v4l2_dev)注册。 还需要设置好 v4l2->mdev 为 media_device 结构体。 在调用 v4l2_device_register 之前如果没有设置 v4l2_device->name,那么会自动分配。 还可以提供一个 notify 回调,给 subdev 向 v4l2_device 发送 event,events 定义在v4l2-subdev.h,官方文档里写只能使用 v4l2-subdev.h 中定义的 event,但看到有的 driver 自定义了一些 event。 通过v4l2_device_unregister()注销,如果是 hotpluggable 设备,在此之前还需要调用v4l2_device_disconnect() v4l2-device.h: Data Structure and APIs struct v4l2_device { struct device *dev; struct media_device *mdev; struct list_head subdevs; spinlock_t lock; char name[36]; void (*notify)(struct v4l2_subdev *sd, unsigned int notification, void *arg); struct v4l2_ctrl_handler *ctrl_handler; struct v4l2_prio_state prio; struct kref ref; void (*release)(struct v4l2_device *v4l2_dev); }; dev: 底层 device 设备。...

2025-06-19 · 1 min

V4L2 -- Video Device

Introduction linux/samples/v4l/v4l2-pci-skeleton.c 有一个 driver 模板。 2.2 Structure of a V4L driver device instances | +-sub-device instances | \-V4L2 device nodes | \-filehandle instances 2.3 Structure of the V4L2 framework v4l2 framework 中分别使用以下几个结构体来依次代表上面的结构: struct v4l2_device struct v4l2_subdev struct video_device struct v4l2_fh 2.4 Video device video device 用于抽象系统注册的 v4l2 /dev 设备节点,以便用户空间可以进行交互。 可以通过 video_device_alloc() 分配,也可以嵌入在更大的结构体中,这样则需要自定义 release 函数。 如果是嵌入在更大的结构体中,并且没有要释放的资源,可以使用 video_device_release_empty()。 最后通过 video_register_device() 注册。 struct video_device 其中一些 fields 需要我们手动去初始化,包括: fops, device_caps, queue, ioctl_ops, lock, prio....

2025-06-19 · 3 min

DMA Buf

Data Structure struct dma_buf { size_t size; struct file *file; struct list_head attachments; const struct dma_buf_ops *ops; unsigned vmapping_counter; struct iosys_map vmap_ptr; const char *exp_name; const char *name; spinlock_t name_lock; struct module *owner; void *priv; struct dma_resv *resv; wait_queue_head_t poll; struct dma_buf_poll_cb_t { struct dma_fence_cb cb; wait_queue_head_t *poll; __poll_t active; } cb_in, cb_out; #endif } struct dma_buf_ops { bool cache_sgt_mapping; int (*attach)(struct dma_buf *, struct dma_buf_attachment *); void (*detach)(struct dma_buf *, struct dma_buf_attachment *); int (*pin)(struct dma_buf_attachment *attach); void (*unpin)(struct dma_buf_attachment *attach); struct sg_table * (*map_dma_buf)(struct dma_buf_attachment *, enum dma_data_direction); void (*unmap_dma_buf)(struct dma_buf_attachment *, struct sg_table *, enum dma_data_direction); void (*release)(struct dma_buf *); int (*begin_cpu_access)(struct dma_buf *, enum dma_data_direction); int (*end_cpu_access)(struct dma_buf *, enum dma_data_direction); int (*mmap)(struct dma_buf *, struct vm_area_struct *vma); int (*vmap)(struct dma_buf *dmabuf, struct iosys_map *map); void (*vunmap)(struct dma_buf *dmabuf, struct iosys_map *map); }; cache_sgt_mapping, ....

2025-04-24 · 3 min

DRM(1) -- DRM internals

DRM Internals Driver Initialization driver 首先需要静态初始化一个 struct drm_driver 结构体,然后调用 drm_dev_alloc() 来 创建一个 struct drm_device 结构体,初始化必要的 fields 后,最后调用 drm_dev_register() 注册 drm_device. Driver Information 在 struct drm_driver 结构体中的.major, .minor, .patchlevel, .name, .desc .date 字段用于描述 driver 的基本信息。 通过 DRM_IOCTL_VERSION 和 DRM_IOCTL_SET_VERSION 两个 ioctl 可以获取和设置 driver 基本信息。 Module Initialization 在 drm_module.h 中提供了一些封装的 api 来注册 module platform/pci driver: drm_module_pci_driver(__pci_drv); drm_module_platform_driver(__platform_drv); Device Instance and Driver Handling 这里有一个 driver 的 template, 具体查看官方文档。 如果需要支持热插拔 drm 设备,比如 USB, DT overlay unload, 需要使用 drm_dev_unplug() 代替 drm_dev_unregister()....

2025-04-15 · 5 min

DRM(11) -- Bridge

Overview struct drm_bridge 代表挂在 encoder 后面的设备。当 drm_encoder 不能完全代表整个 encoder chain 的时候, drm_bridge 就有用了。 Encoder –> Bridge A –> Bridge B drm bridge 和 drm panel 一样,不是 drm_mode_object, 对 userspace 是不可见的。他们只是用来提供额外的 hooks 来得到 encoder chain 最终的理想输出。 Display driver 负责把 encoder link 到第一个 bridge,通过devm_drm_of_get_bridge()获取 bridge,再通过drm_bridge_attach()将 bridge attach 到 encoder 上。 Bridge driver 负责把自己 link 到下一级 bridge,通过在 drm_bridges_funcs.attach 中调用drm_bridge_attach()。 bridge driver 在这里我们考虑设备树中只存在 panel node,而不存在 bridge node 的情况。 Data Structure struct drm_bridge { struct drm_private_obj base; struct drm_device *dev; struct drm_encoder *encoder; struct list_head chain_node; struct device_node *of_node; struct list_head list; const struct drm_bridge_timings *timings; const struct drm_bridge_funcs *funcs; void *driver_private; enum drm_bridge_ops ops; int type; bool interlace_allowed; struct i2c_adapter *ddc; struct mutex hpd_mutex; void (*hpd_cb)(void *data, enum drm_connector_status status); void *hpd_data; }; encoder: bridge 连接的 encoder...

2025-04-15 · 4 min