发布: subdev和media子系统

This commit is contained in:
weidongshan
2024-03-02 17:05:15 +08:00
parent 723728c7b7
commit e827d0a2aa
46 changed files with 709 additions and 2 deletions

View File

@@ -395,7 +395,692 @@ vi ./device/config/chips/v853/configs/100ask/linux-4.9/sys_partition.fex
## 4. subdev和media子系统
### 4.1 subdev和media子系统的引入
#### 4.1.1 subdev的引入
##### 1. 简单驱动
对于比较简单的摄像头我们把它当做一个整体它的核心就是一个video_device。以前面讲过的虚拟驱动程序为例它的源码位于如下目录
![image-20240229155411136](pic/v853/45_virtual_video.png)
这个驱动程序的核心是video_device如下
![image-20240229155308464](pic/v853/44_virtual_video.png)
在整个驱动程序中没有subdev没有media子系统。
##### 2. UVC驱动
USB摄像头稍微复杂一点它的内部有各类Unit或Terminal如下图所示
![image-20230725082453370](pic/07_uvc_topology.png)
但是这些Unit或Terminal的独立性不强并且它们遵守UVC规范没必要单独为它们编写驱动程序。在UVC驱动程序里每一个Unit或Terminal都有一个"struct uvc_entity"结构体,每一个"struct uvc_entity"里面也都有一个"struct v4l2_subdev",如下图所示:
![image-20240229160615863](pic/v853/46_subdev_in_uvc_entity.png)
但是这些subdev没有什么作用它们的ops函数都是空的
![image-20240229160728283](pic/v853/47_ops_of_uvc_subdev.png)
##### 3. 复杂驱动
下图是使用v853 mipi摄像头时涉及的内部结构或内部流程
![](pic/v853/07_media0_entity.png)
内部涉及的模块非常多,这些模块相对独立,有必要单独给这些模块编写驱动程序。
这些模块被抽象为subdev原因有2
* 屏蔽硬件操作的细节有些模块是I2C接口的有些模块是SPI接口的它们都被封装为subdev
* 方便内核使用、APP使用可以在内核里调用subdev的函数也可以在用户空间调用subdev的函数很多厂家不愿意公开ISP的源码只能在驱动层面提供最简单的subdev然后通过APP调用subdev的基本读写函数进行复杂的设置。
subdev结构体如下
![image-20240229111816717](pic/v853/42_subdev_ops.png)
里面有各类ops结构体比如core、tuner、audio、video等等。编写subdev驱动程序时核心就是实现各类ops结构体的函数。
以上图中第1个模块gc2053为例它的代码为"drivers\media\platform\sunxi-vin\modules\sensor\gc2053_mipi.c",核心结构体如下:
![image-20240229161428666](pic/v853/48_gc2053_ops.png)
#### 4.1.2 media子系统的引入
即使我们给每一个子模块都编写了驱动程序都构造了subdev但是它们之间的相互关系怎么表示如下图
* 每一个模块都构造了subdev
* 但是,框图里黑色箭头所表示的关系如何描述?
* 比如,从"格式解析"模块出来的数据,到底是输出到"ISP0"还是"ISP1"?用户如何选择?
* 当我们指定"格式解析"模块输出的数据格式后是否也要同步指定ISP0或ISP1模块的输入数据格式
![image-20240301081736905](pic/v853/49_media_import.png)
这就需要引入media子系统简化如下
![image-20240301103416668](pic/v853/50_media_concept.png)
怎么操作上图的各个对象使用subdev。subdev里含有各个对象的操作函数。
怎么表示上图的各个对象之间的关系使用media子系统。在media子系统里
* 每个对象都是一个media_entity
* media_entity有media_pad可以认为是端点不能简单认为是硬件引脚有source pad输出数据sink pad输入数据
* media_entity之间的连接被称为media_link
* media_link仅仅表示两个media_entity之间的连接要构成一个完整的数据通道需要多个系列的连接这被称为pipeline
* media子系统的作用就在于管理"拓扑关系",就是各个对象的连接关系。
把V853的拓扑图精简一下
![image-20240226162803343](pic/v853/29_v853_video0.png)
怎么表示上图的各个对象使用media子系统media子系统的作用在于管理"拓扑关系",就是各个对象的连接关系。
怎么操作上图的各个对象使用subdev。subdev里含有各个对象的操作函数。
命令示例:
```shell
media-ctl -v -l '"gc2053_mipi":0->"sunxi_mipi.0":0[1]'
v4l2-ctl -D -d /dev/v4l-subdev0
```
### 4.2 subdev概览与数据结构
#### 4.2.1 实例
`drivers\media\platform\sunxi-vin\modules\sensor\gc2053_mipi.c`为例:
```c
sensor_probe
/* 分配sensor_info结构体,里面含有v4l2_subdev */
struct v4l2_subdev *sd;
struct sensor_info *info;
info = kzalloc(sizeof(struct sensor_info), GFP_KERNEL);
sd = &info->sd;
cci_dev_probe_helper(sd, client, &sensor_ops, &cci_drv[sensor_dev_id++]);
v4l2_i2c_subdev_init(sd, client, sensor_ops);
v4l2_subdev_init(sd, ops);
```
![image-20240302143026115](pic/v853/52_v4l2_subdev_init.png)
#### 4.2.2 数据结构
一个模块对应一个subdev怎么操作这个模块subdev里面有ops
![image-20240229111816717](pic/v853/42_subdev_ops.png)
怎么管理多个subdev必定是放入一个链表里
![image-20240302144353536](pic/v853/53_v4l2_device.png)
### 4.3 media子系统概览与数据结构
#### 4.3.1 拓扑结构
对于V853精简的拓扑图
![image-20240226162803343](pic/v853/29_v853_video0.png)
在media子系统里怎么表示上面的各个entity的关系以最左边2个entity为例结构体如下
![image-20240301180519100](pic/v853/51_media_topo.png)
#### 4.3.2 数据结构
一个media子系统使用"struct media_device"来表示,结构体如下:
![image-20240227121132964](pic/v853/37_media_device.png)
media_device里有多个entity它使用"struct media_entity"来表示:
![image-20240227174116166](pic/v853/38_media_entity.png)
media_entity里有多个pad它使用"struct media_pad"来表示:
![image-20240227174428532](pic/v853/39_media_pad.png)
entity通过pad跟其他entity相连这被称为link它使用"media_link"来表示:
![image-20240227175654194](pic/v853/40_media_link.png)
两个entity之间的连接被称为link多个已经使能的link构成一条完整的数据通道这被称为pipeline。驱动程序在进行streamon操作时有些驱动会调用"media_entity_pipeline_start"函数,类似下面的代码:
```c
ret = media_entity_pipeline_start(sensor, camif->m_pipeline);
```
第1个参数是第1个entity第2个参数就是pipeline它在media_entity_pipeline_start函数内部构造
media_entity_pipeline_start的目的是从第1个entity开始遍历所有的link把已经使能的link都执行"link_validate"。
media_entity_pipeline_start内部是按照深度优先来操作entity的以下图为例
* 有两条pipelinee0->e1->e2->e3e0->e1->e4->e5
* 先遍历e0->e1->e2->e3这条pipeline调用e3、e2的"link_validate"
* 再遍历e0->e1->e4->e5这条pipeline调用e5、e4的"link_validate"
* 接着处理e1调用它的"link_validate"
* 最后处理e0它没有sink pad无需调用它的"link_validate"
![image-20240228154108145](pic/v853/41_pipeline_start.png)
#### 4.3.3 media子系统和subdev的关系
内核空间v4l2_subdev里含有media_entity两者都很容易找到对方
![image-20240229150632621](pic/v853/43_entity_subdev.png)
从entity找到subdev使用以下代码
```shell
#define media_entity_to_v4l2_subdev(ent) \
container_of(ent, struct v4l2_subdev, entity)
```
用户空间里怎么从entity找到对应的/dev/v4l-subdevX参考`v4l-utils-1.20.0\utils\media-ctl\libmediactl.c`
```c
// 1. open /dev/media0
media->fd = open(media->devnode, O_RDWR);
// 2.循环调用ioctl(MEDIA_IOC_ENUM_ENTITIES), 得到每一个entity的信息
entity = &media->entities[media->entities_count];
memset(entity, 0, sizeof(*entity));
entity->fd = -1;
entity->info.id = id | MEDIA_ENT_ID_FLAG_NEXT;
entity->media = media;
// entity->info类型为: struct media_entity_desc info;
// 里面含有major, minor
ret = ioctl(media->fd, MEDIA_IOC_ENUM_ENTITIES, &entity->info);
// 3. 使用media_get_devname_sysfs函数获得entity对应的设备节点
// 根据主设备号、次设备号在/sys/dev/char目录下找到类似这样的文件: /sys/dev/char/81:2
// 它是一个连接文件,连接到:../../devices/platform/soc/5800800.vind/video4linux/v4l-subdev0
// /dev/v4l-subdev0就是这个entity对应的设备节点
// APP的media_entity.devname[32]里就是"/dev/v4l-subdev0"
static int media_get_devname_sysfs(struct media_entity *entity);
```
### 4.4 subdev的注册与使用
#### 4.4.1 内核注册过程
subdev里含有模块的操作函数谁调用这些函数
* 内核调用subdev完全可以不暴露给用户在摄像头驱动程序内部"偷偷地"调用subdev的函数用户感觉不到subdev的存在。
* APP调用对于比较复杂的硬件驱动程序应该"让用户有办法调节各类参数"比如ISP模块几乎都是闭源的对它的设置只能通过APP进行。这类subdev的函数应该暴露给用户用户可以调用它们。
在内核里subdev的注册过程为分为2步
* v4l2_device_register_subdev: 把subdev放入v4l2_device的链表
```c
int v4l2_device_register_subdev(struct v4l2_device *v4l2_dev,
struct v4l2_subdev *sd);
```
* v4l2_device_register_subdev_nodes遍历v4l2_device链表里各个subdev如果它想暴露给APP就把它注册为普通字符设备
```c
int v4l2_device_register_subdev_nodes(struct v4l2_device *v4l2_dev);
// 调用过程如下
v4l2_device_register_subdev_nodes
struct video_device *vdev;
vdev->fops = &v4l2_subdev_fops;
err = __video_register_device(vdev, VFL_TYPE_SUBDEV, -1, 1,
sd->owner);
name_base = "v4l-subdev";
vdev->cdev->ops = &v4l2_fops;
ret = cdev_add(vdev->cdev, MKDEV(VIDEO_MAJOR, vdev->minor), 1);
```
v4l2_device_register_subdev_nodes的注册过程涉及2个结构体
* file_operations
![image-20240226145649608](pic/v853/25_v4l2_fops.png)
* v4l2_file_operations
![image-20240226145739108](pic/v853/26_subdev_fops.png)
APP对/dev/v4l-subdev*这类的设备进行ioctl操作时内核里流程如下
```shell
App: ioctl
--------------
kernel:
v4l2_fops.unlocked_ioctl, 即v4l2_ioctl
ret = vdev->fops->unlocked_ioctl(filp, cmd, arg);
v4l2_subdev_fops.unlocked_ioctl, 即subdev_ioctl
video_usercopy(file, cmd, arg, subdev_do_ioctl);
```
![image-20240226150254845](pic/v853/27_subdev_do_ioctl.png)
#### 4.4.2 内核态使用subdev
可以直接调用subdev里的操作函数也可以使用下面的宏
```c
#define v4l2_subdev_call(sd, o, f, args...) \
(!(sd) ? -ENODEV : (((sd)->ops->o && (sd)->ops->o->f) ? \
(sd)->ops->o->f((sd), ##args) : -ENOIOCTLCMD))
```
#### 4.4.3 用户态使用subdev
APP可以打开设备文件/dev/v4l-subdevX执行ioctl调用驱动里面的各个ops函数调用关系如下
##### 1. v4l2_subdev_core_ops
* VIDIOC_SUBSCRIBE_EVENTAPP订阅感兴趣的事件导致core->subscribe_event被调用
* VIDIOC_UNSUBSCRIBE_EVENTAPP取消兴趣导致core->unsubscribe_event被调用
* VIDIOC_DBG_G_REGISTER调试作用读寄存器导致core->g_register被调用
* VIDIOC_DBG_S_REGISTER调试作用写寄存器导致core->s_register被调用
* VIDIOC_LOG_STATUS调试作用打印调试信息导致core->log_status被调用
##### 2. v4l2_subdev_video_ops
* VIDIOC_SUBDEV_G_FRAME_INTERVAL获得帧间隔导致video->g_frame_interval被调用
* VIDIOC_SUBDEV_S_FRAME_INTERVAL设置帧间隔导致video->s_frame_interval被调用
* VIDIOC_SUBDEV_QUERY_DV_TIMINGS导致video->query_dv_timings被调用
* VIDIOC_SUBDEV_G_DV_TIMINGS导致video->g_dv_timings被调用
* VIDIOC_SUBDEV_S_DV_TIMINGS导致video->s_dv_timings被调用
##### 3. v4l2_subdev_pad_ops
* VIDIOC_SUBDEV_G_FMT导致pad->get_fmt被调用
* VIDIOC_SUBDEV_S_FMT导致pad->set_fmt被调用
* VIDIOC_SUBDEV_G_CROP/VIDIOC_SUBDEV_G_SELECTION导致pad->get_selection被调用
* VIDIOC_SUBDEV_S_CROP/VIDIOC_SUBDEV_S_SELECTION导致pad->set_selection被调用
* VIDIOC_SUBDEV_ENUM_MBUS_CODE导致pad->enum_mbus_code被调用
* VIDIOC_SUBDEV_ENUM_FRAME_SIZE导致pad->enum_frame_size被调用
* VIDIOC_SUBDEV_ENUM_FRAME_INTERVAL导致pad->enum_frame_interval被调用
* VIDIOC_G_EDID导致pad->get_edid被调用
* VIDIOC_S_EDID导致pad->set_edid被调用
* VIDIOC_SUBDEV_DV_TIMINGS_CAP导致pad->dv_timings_cap被调用
* VIDIOC_SUBDEV_ENUM_DV_TIMINGS导致pad->enum_dv_timings被调用
驱动内部调用:
* v4l2_subdev_link_validate导致pad->link_validate被调用
* v4l2_subdev_alloc_pad_config导致pad->init_cfg被调用
### 4.5 media子系统的注册与使用
#### 4.5.1 内核注册过程
在内核里media子系统的注册过程为
```shell
media_device_register
__media_device_register
struct media_devnode *devnode;
devnode->fops = &media_device_fops;
ret = media_devnode_register(mdev, devnode, owner);
cdev_init(&devnode->cdev, &media_devnode_fops);
ret = cdev_add(&devnode->cdev, MKDEV(MAJOR(media_dev_t), devnode->minor), 1);
```
上述注册过程涉及2个结构体
* file_operations
![image-20240226120253801](pic/v853/17_media_file_ops.png)
* media_file_operations
![image-20240226120400612](pic/v853/18_media_device_fops.png)
APP对/dev/media0这类的设备进行ioctl操作时内核里流程如下
```shell
App: ioctl
--------------
kernel:
media_devnode_fops.unlocked_ioctl, 即media_ioctl
__media_ioctl(filp, cmd, arg, devnode->fops->ioctl);
media_device_ioctl
const struct media_ioctl_info *info;
info = &ioctl_info[_IOC_NR(cmd)];
ret = info->arg_from_user(karg, arg, cmd);
ret = info->fn(dev, karg);
ret = info->arg_to_user(arg, karg, cmd);
```
核心在于ioctl_info
![image-20240226120856997](pic/v853/19_ioctl_info.png)
#### 4.5.2 调用关系
APP使用media子系统时除了open之外就只涉及5个ioctl
* MEDIA_IOC_DEVICE_INFO
* MEDIA_IOC_ENUM_ENTITIES
* MEDIA_IOC_ENUM_LINKS
* MEDIA_IOC_SETUP_LINK
* MEDIA_IOC_G_TOPOLOGY
这5个ioctl将导致内核中如下函数被调用drivers\media\media-device.c
![image-20240227111537846](pic/v853/30_media_ioctl.png)
##### 1.MEDIA_IOC_DEVICE_INFO
这个ioctl被用来获得/dev/mediaX的设备信息设备信息结构体如下
![image-20240226121103122](pic/v853/20_media_device_info.png)
APP代码如下
```c
memset(&media->info, 0, sizeof(media->info)); // struct media_device_info info;
ret = ioctl(media->fd, MEDIA_IOC_DEVICE_INFO, &media->info);
```
驱动中对应核心代码如下:
![image-20240227112019964](pic/v853/31_media_device_get_info.png)
##### 2. MEDIA_IOC_ENUM_ENTITIES
这个ioctl被用来获得指定entity的信息APP参考代码为
![image-20240226142620054](pic/v853/21_enum_entity.png)
驱动中对应核心代码如下:
![image-20240227112316647](pic/v853/32_media_device_enum_entities.png)
##### 3. MEDIA_IOC_ENUM_LINKS
这个ioctl被用来枚举enity的linkAPP参考代码为
![image-20240226142751821](pic/v853/22_enum_link.png)
驱动中对应核心代码如下:
![image-20240227114208829](pic/v853/34_media_device_enum_links.png)
##### 4. MEDIA_IOC_SETUP_LINK
这个ioctl被用来设置link把源pad、目的pad之间的连接激活active或者闲置inactiveAPP示例代码为
![image-20240226142927131](pic/v853/23_setup_link.png)
APP传入的flags的取值有2种
* 0闲置link
* 1激活link
内核里link的flag有如下取值
![image-20240227112910542](pic/v853/33_media_link_flag.png)
如果这个link的flag不是MEDIA_LINK_FL_IMMUTABLE的话就可以去更改它的bit0状态激活或闲置。
驱动中对应核心代码如下:
![image-20240227115855695](pic/v853/35_media_device_setup_link.png)
##### 5. MEDIA_IOC_G_TOPOLOGY
这个ioctl被用来获得整体的拓扑图包括entities、interfaces、pads、links的信息示例代码如下
![image-20240226144452444](pic/v853/24_get_topology.png)
驱动中对应核心代码如下只要APP提供了对应的buffer它就可以复制对应的信息比如entities、interfaces、pads、links的信息
![image-20240227120707559](pic/v853/36_media_device_get_topology.png)
*
### 4.6 v4l2-utils使用详解
v4l2-utils中含有多个APP比如
- [DVBv5_Tools](https://www.linuxtv.org/wiki/index.php/DVBv5_Tools): tools to scan, zap and do other neat things with DVB devices;
- ir-keytable: Dump, Load or Modify ir receiver input tables;
- ir-ctl: A swiss-knife tool to handle raw IR and to set lirc options;
- media-ctl: Tool to handle media controller devices;
- qv4l2: QT v4l2 control panel application;
- v4l2-compliance: Tool to test v4l2 API compliance of drivers;
- v4l2-ctl: tool to control v4l2 controls from the cmdline;
- v4l2-dbg: tool to directly get and set registers of v4l2 devices;
- v4l2-sysfs-path: checks the media devices installed on a machine and the corresponding device nodes;
- xc3028-firmware: Xceive XC2028/3028 tuner module firmware manipulation tool;
- cx18-ctl: tool to handle cx18 based devices (deprecated in favor of v4l2-ctl);
- ivtv-ctl: tool to handle ivtv based devices (deprecated in favor of v4l2-ctl);
- rds-ctl: tool to handle RDS radio devices;
- decode_tm6000: ancillary tool to decodes tm6000 proprietary format streams;
- cec-ctl: tool to control CEC devices from the command line;
- cec-follower: tool used to emulate CEC followers;
- cec-compliance: tool to test CEC API compliance of drivers and remote CEC devices;
media-ctl使用方法为
```shell
media-ctl --help
media-ctl [options]
-d, --device dev Media device name (default: /dev/media0)
If <dev> starts with a digit, then /dev/media<dev> is used.
If <dev> doesn't exist, then find a media device that
reports a bus info string equal to <dev>.
-e, --entity name Print the device name associated with the given entity
-V, --set-v4l2 v4l2 Comma-separated list of formats to setup
--get-v4l2 pad Print the active format on a given pad
--get-dv pad Print detected and current DV timings on a given pad
--set-dv pad Configure DV timings on a given pad
-h, --help Show verbose help and exit
-i, --interactive Modify links interactively
-l, --links links Comma-separated list of link descriptors to setup
--known-mbus-fmts List known media bus formats and their numeric values
-p, --print-topology Print the device topology. If an entity
is specified through the -e option, print
information for that entity only.
--print-dot Print the device topology as a dot graph
-r, --reset Reset all links to inactive
-v, --verbose Be verbose
Links and formats are defined as
links = link { ',' link } ;
link = pad '->' pad '[' flags ']' ;
pad = entity ':' pad-number ;
entity = entity-number | ( '"' entity-name '"' ) ;
v4l2 = pad '[' v4l2-properties ']' ;
v4l2-properties = v4l2-property { ',' v4l2-property } ;
v4l2-property = v4l2-mbusfmt | v4l2-crop | v4l2-interval
| v4l2-compose | v4l2-interval ;
v4l2-mbusfmt = 'fmt:' fcc '/' size ; { 'field:' v4l2-field ; } { 'colorspace:' v4l2-colorspace ; }
{ 'xfer:' v4l2-xfer-func ; } { 'ycbcr-enc:' v4l2-ycbcr-enc-func ; }
{ 'quantization:' v4l2-quant ; }
v4l2-crop = 'crop:' rectangle ;
v4l2-compose = 'compose:' rectangle ;
v4l2-interval = '@' numerator '/' denominator ;
rectangle = '(' left ',' top, ')' '/' size ;
size = width 'x' height ;
where the fields are
entity-number Entity numeric identifier
entity-name Entity name (string)
pad-number Pad numeric identifier
flags Link flags (0: inactive, 1: active)
fcc Format FourCC
width Image width in pixels
height Image height in pixels
numerator Frame interval numerator
denominator Frame interval denominator
v4l2-field One of the following:
any
none
top
bottom
interlaced
seq-tb
seq-bt
alternate
interlaced-tb
interlaced-bt
v4l2-colorspace One of the following:
default
smpte170m
smpte240m
rec709
unknown
470m
470bg
jpeg
srgb
oprgb
bt2020
raw
dcip3
v4l2-xfer-func One of the following:
default
709
srgb
oprgb
smpte240m
none
dcip3
smpte2084
v4l2-quant One of the following:
default
full-range
lim-range
```
v4l2-ctl使用方法如下
```shell
v4l2-ctl --help
General/Common options:
--all display all information available
-C, --get-ctrl <ctrl>[,<ctrl>...]
get the value of the controls [VIDIOC_G_EXT_CTRLS]
-c, --set-ctrl <ctrl>=<val>[,<ctrl>=<val>...]
set the value of the controls [VIDIOC_S_EXT_CTRLS]
-D, --info show driver info [VIDIOC_QUERYCAP]
-d, --device <dev> use device <dev> instead of /dev/video0
if <dev> starts with a digit, then /dev/video<dev> is used
Otherwise if -z was specified earlier, then <dev> is the entity name
or interface ID (if prefixed with 0x) as found in the topology of the
media device with the bus info string as specified by the -z option.
-e, --out-device <dev> use device <dev> for output streams instead of the
default device as set with --device
if <dev> starts with a digit, then /dev/video<dev> is used
Otherwise if -z was specified earlier, then <dev> is the entity name
or interface ID (if prefixed with 0x) as found in the topology of the
media device with the bus info string as specified by the -z option.
-E, --export-device <dev> use device <dev> for exporting DMA buffers
if <dev> starts with a digit, then /dev/video<dev> is used
Otherwise if -z was specified earlier, then <dev> is the entity name
or interface ID (if prefixed with 0x) as found in the topology of the
media device with the bus info string as specified by the -z option.
-z, --media-bus-info <bus-info>
find the media device with the given bus info string. If set, then
-d, -e and -E options can use the entity name or interface ID to refer
to the device nodes.
-h, --help display this help message
--help-all all options
--help-io input/output options
--help-meta metadata format options
--help-misc miscellaneous options
--help-overlay overlay format options
--help-sdr SDR format options
--help-selection crop/selection options
--help-stds standards and other video timings options
--help-streaming streaming options
--help-subdev sub-device options
--help-tuner tuner/modulator options
--help-vbi VBI format options
--help-vidcap video capture format options
--help-vidout vidout output format options
--help-edid edid handling options
-k, --concise be more concise if possible.
-l, --list-ctrls display all controls and their values [VIDIOC_QUERYCTRL]
-L, --list-ctrls-menus
display all controls and their menus [VIDIOC_QUERYMENU]
-r, --subset <ctrl>[,<offset>,<size>]+
the subset of the N-dimensional array to get/set for control <ctrl>,
for every dimension an (<offset>, <size>) tuple is given.
-w, --wrapper use the libv4l2 wrapper library.
--list-devices list all v4l devices. If -z was given, then list just the
devices of the media device with the bus info string as
specified by the -z option.
--log-status log the board status in the kernel log [VIDIOC_LOG_STATUS]
--get-priority query the current access priority [VIDIOC_G_PRIORITY]
--set-priority <prio>
set the new access priority [VIDIOC_S_PRIORITY]
<prio> is 1 (background), 2 (interactive) or 3 (record)
--silent only set the result code, do not print any messages
--sleep <secs> sleep <secs>, call QUERYCAP and close the file handle
--verbose turn on verbose ioctl status reporting
```

Binary file not shown.

Before

Width:  |  Height:  |  Size: 166 KiB

After

Width:  |  Height:  |  Size: 161 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 107 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 129 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 150 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 135 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 172 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 108 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 116 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 126 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 71 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 130 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 255 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 307 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 93 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 92 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 71 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 250 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

View File

@@ -1113,6 +1113,17 @@ vin_md_register_core_entity
设备树里vinc@0,4,8,12的status都是okay但是vinc@4,8里
```shell
vinc4_rear_sensor_sel = <1>;
vinc8_rear_sensor_sel = <1>;
```
并没有sensor 1所以没有创建出对应的subdev没有创建出对应的/dev/video4,8
### 10.8 vin_video0
drivers/media/platform/sunxi-vin/vin-video/vin_video.c
@@ -1120,8 +1131,7 @@ drivers/media/platform/sunxi-vin/vin-video/vin_video.c
![image-20240220185958332](pic/v853/13_vin_cap_internal_ops.png)
```shell
vin_capture_subdev_registered
if (vin_init_video(sd->v4l2_dev, &vinc->vid_cap))
vin_init_video
snprintf(cap->vdev.name, sizeof(cap->vdev.name),
"vin_video%d", cap->vinc->id);
cap->vdev.fops = &vin_fops;
@@ -1156,3 +1166,6 @@ sd->internal_ops何时被调用
## 12. 其他
v4l2-event自定义事件调试 https://blog.csdn.net/qq_34341546/article/details/131329503

View File

@@ -853,6 +853,15 @@ git clone https://e.coding.net/weidongshan/linux/doc_and_source_for_drivers.git
[05-2-3]_搭建V853开发环境_自制单板系统
```
* 2024.03.02 发布"摄像头驱动"
```shell
[05-3-1]_subdev和media子系统的引入
[05-3-2]_subdev概览与数据结构
[05-3-3]_media子系统概览与数据结构
[05-3-4]_subdev的注册
```