v4l2_device 结构体
每个设备实例都通过 v4l2_device (v4l2-device.h)结构体来表示。简单设备可以仅分配这个结构体,但在大多数情况下,都会将这个结构体嵌入到一个更大的结构体中。驱动中,将会通过v4l2_device_register(struct device *dev, struct v4l2_device *v4l2_dev)注册设备示例。
v4l2_subdev结构体
很多camera驱动需要与子设备通信,控制这些子设备完成各种任务,V4L2为了给驱动提供调用子设备的统一接口,创建了v4l2_subdev结构体。每个 v4l2_subdev 都包含子设备驱动需要实现的函数指针(如果对此设备不适用,可为NULL)。由于子设备可完成许多不同的工作,而在一个庞大的函数指针结构体中通常仅有少数有用的函数实现其功能肯定不合适。所以,函数指针根据其实现的功能被分类,每一类都有自己的函数指针结构体
进行dts信息解析,dts中将配置sensor的硬件信息以及csi pipeline的连续顺序:
1. parse_modules_from_device_tree(vind);
申请gpio硬件资源:
vin_gpio_request(vind);
2. 通过v4l2_device_register()注册v4l2_device:
v4l2_dev = &vind->v4l2_dev;
v4l2_dev->mdev = &vind->media_dev;
strlcpy(v4l2_dev->name, "sunxi-vin", sizeof(v4l2_dev->name));
ret = v4l2_device_register(dev, &vind->v4l2_dev);
3. 通过media_device_register()注册media_device:
ret = media_device_register(&vind->media_dev);
4.获取时钟信息:
ret = vin_md_get_clocks(vind);
5.注册各个media entity设备:
ret = vin_md_register_entities(vind, dev->of_node);
/************************ sensor ***************************/
for (j = 0; j < sensors->detect_num; j++) {
if (sensors->use_sensor_list == 1)
__vin_handle_sensor_info(&sensors->inst[j]);
__vin_verify_sensor_info(&sensors->inst[j]);
/* 通过v4l2_device_register_subdev或v4l2_i2c_new_subdev向系统注册v4l2_subdev */
if (__vin_register_module(vind, module, j)) {
sensors->valid_idx = j;
break;
}
}
/************************ video device ***************************/
/* 通过v4l2_device_register_subdev向系统注册v4l2_subdev */
vin_md_register_core_entity(vind, vind->vinc[i]);
/******************** csi、mipi、isp、vipp *************************/
/* 通过v4l2_device_register_subdev向系统注册v4l2_subdev */
ret = v4l2_device_register_subdev(&vind->v4l2_dev, vind->csi[i].sd);
ret = v4l2_device_register_subdev(&vind->v4l2_dev, vind->mipi[i].sd);
ret = v4l2_device_register_subdev(&vind->v4l2_dev, vind->isp[i].sd);
ret = v4l2_device_register_subdev(&vind->v4l2_dev, vind->scaler[i].sd);
6.建立csi pipeline默认连接:
ret = vin_setup_default_links(vind);
/* 此时csi与isp、isp与vipp建立默认连接,同时根据dts中的配置,初始化好csi pipeline中的subdev */
注册v4l2_subdev节点(/dev/v4l-subdevX):
int v4l2_device_register_subdev_nodes(struct v4l2_device *v4l2_dev)
{
strlcpy(vdev->name, sd->name, sizeof(vdev->name));
vdev->v4l2_dev = v4l2_dev;
vdev->fops = &v4l2_subdev_fops;
vdev->release = v4l2_device_release_subdev_node;
vdev->ctrl_handler = sd->ctrl_handler;
err = __video_register_device(vdev, VFL_TYPE_SUBDEV, -1, 1,
sd->owner);
}
到这里,基本各个设备都已经完成加载注册,硬件与dts都正确的情况,应该存在/dev/videoX节点。但是可能存在疑惑,这个节点到底是什么时候,哪里进行注册的呢,下面介绍。
原文链接:https://blog.csdn.net/weixin_41944449/article/details/133197607
标签:subdev,register,vind,dev,camera,linux,device,驱动,v4l2 From: https://www.cnblogs.com/ycjstudy/p/18282291