vin驱动入口
vin驱动代码主要在drivers\media\platform\sunxi-vin\vin.c,该文件里面的所有函数几乎用static修饰,即只能被本驱动模块内部使用。分析vin驱动的代码,总结它是个用于管理V4l2设备的,包括主设备和子设备,在驱动启动过程中它是一个引导者,驱动启动后,它退隐了,应用程序对Camera的操作与它无关。
vin驱动入口函数是vin_init():
static int __init vin_init(void)
{
ret = sunxi_csi_platform_register();
ret = sunxi_isp_platform_register();
ret = sunxi_mipi_platform_register();
ret = sunxi_flash_platform_register();
ret = sunxi_scaler_platform_register();
ret = sunxi_vin_core_register_driver();
ret = sunxi_vin_debug_register_driver();
ret = platform_driver_register(&vin_driver);
}
vin_init()做了四件事:
- 分别向系统注册了csi、isp、mipi、flash和scaler驱动程序。根据DST里面的配置,如果有相应的device,则将运行驱动程序的probe,暂不去分析它们。
- 注册vin_core驱动程序。对应DST里面的vinc节点的设备,总共有8个可配置的设备。参考《v4l2_core驱动.docx》
- 注册用于调试的vin_debug驱动程序
- 最后注册vin.c定义的vin驱动程序。对应DST里面的vind节点。本文档重点分析该节点对应的驱动。
对于vin驱动程序,与vind设备匹配后将执行vin_probe(),这里的代码只保留主要的:
static int vin_probe(struct platform_device *pdev)
{
//从DST中分析sensor和vinc0~vinc8子节点
parse_modules_from_device_tree(vind);
strlcpy(vind->media_dev.model, "Allwinner Vin",
sizeof(vind->media_dev.model));
/*entity注册成功的回调vin_md_link_notify*/
vind->media_dev.link_notify = vin_md_link_notify;
vind->media_dev.dev = dev;//将media_dev的dev变量直线本驱动的device
v4l2_dev = &vind->v4l2_dev;
v4l2_dev->mdev = &vind->media_dev;
strlcpy(v4l2_dev->name, "sunxi-vin", sizeof(v4l2_dev->name));
//1、注册一个名字为"sunxi-vin"的v4l2设备实例
ret = v4l2_device_register(dev, &vind->v4l2_dev);
//2、注册多媒体设备实例
ret = media_device_register(&vind->media_dev);
//3、注册entity和v4l2_subdev
ret = vin_md_register_entities(vind, dev->of_node);
//4、为vinc0~vinc8创建media_links
//例如vinc0:sensor0(NCSI0)-->CSI2-->ISP0-->VIPP0(包括stat0-->scaler0)-->vid_cap.subdev-->vid_cap.vdev.entity
ret = vin_create_media_links(vind);
//5、启动默认的多媒体links
ret = vin_setup_default_links(vind);
//6、为v4l2_dev->subdev注册v4l2子设备节点
//这里可能没有注册到,因为v4l2_dev->subdev还没被赋值
//需要等cci/isp/mipi等设备驱动运行起来后才有值
ret = v4l2_device_register_subdev_nodes(&vind->v4l2_dev);
}
vind是结构体vin_md变量,vin_md全称是Video input_media device,是驱动中自定义的一个总的结构体,用于驱动中各个函数的调用。
vin_probe函数的一开始通过扫描DST为vin_md的csi、mipi、cci、isp、stat和scaler这些物理设备的信息并保存下来,但实际项目用到哪些物理设备还是不知道的,这里仅仅是保存信息。
1、v4l2_device_register
在一切子设备被串联起来之前首先要初始化注册 v4l2_device 这个总的设备。调用v4l2_device_register()注册一个名字为“sunxi-vin”的v4l2总设备,此时这个总设备还没有任何子设备(v4l2_subdev)。驱动程序设置了 v4l2_device 的 mdev 成员,那么子设备与 video 节点都会被自动当作 media framework 里的 entitiy 抽象。
前面几句代码语句最终让vind成为下图:
2、media_device_register
一个多媒体设备用一个 media_device 结构体来表示,类似v4l2_device,通常情况下该结构体要嵌入到一个更大的设备自定义的结构体里面,并且大多数时候 media_device 与 v4l2_device 是处于并列的级别,例如本驱动的vin_md结构体里面就有v4l2_device和media_device两个结构体变量。
使用以下函数进行 meida 设备的注册:media_device_register(struct media_device *mdev);
函数的调用者需要在注册之前设置以下结构体成员(提前初始化该结构体是调用者的责任):
- dev:必须指向一个父设备,通常是平台设备的device成员。
- model:模型名字。
3、vin_md_register_entities
该函数主要是注册vinc、csi、isp、mipi和scaler等各种子设备。内部调用了v4l2_device_register_subdev(),而它由调用了media_device_register_entity()分别创建了media entity,每个entity类型(以ISP0为例):
在vin驱动的入口函数vin_init()中,向系统注册了vinc、csi、isp、mipi和scaler等各种子设备的驱动程序,而这里注册了他们的相应的设备,这样,设备与驱动匹配成功,将会调用这些子设备驱动程序的probe函数。
4、vin_create_media_links
下面是打印信息,可见该函数把所有Media Entity可能的组合都创建了link:
[ 5.041439] [VIN_LOG_MD]created link [nvp6134] -> [sunxi_csi.2]
[ 5.048009] [VIN_LOG_MD]created link [sunxi_scaler.0] => [vin_cap.0]
[ 5.055075] [VIN_LOG_MD]created link [vin_cap.0] => [vin_video0]
[ 5.061736] [VIN_LOG_MD]created link [nvp6134] -> [sunxi_csi.2]
[ 5.068283] [VIN_LOG_MD]created link [sunxi_scaler.1] => [vin_cap.1]
[ 5.075332] [VIN_LOG_MD]created link [vin_cap.1] => [vin_video1]
[ 5.082003] [VIN_LOG_MD]created link [nvp6134] -> [sunxi_csi.2]
[ 5.088553] [VIN_LOG_MD]created link [sunxi_scaler.2] => [vin_cap.2]
[ 5.095599] [VIN_LOG_MD]created link [vin_cap.2] => [vin_video2]
[ 5.102273] [VIN_LOG_MD]created link [nvp6134] -> [sunxi_csi.2]
[ 5.108814] [VIN_LOG_MD]created link [sunxi_scaler.3] => [vin_cap.3]
[ 5.115865] [VIN_LOG_MD]created link [vin_cap.3] => [vin_video3]
[ 5.122527] [VIN_LOG_MD]created link [sunxi_csi.0] -> [sunxi_isp.0]
[ 5.129453] [VIN_LOG_MD]created link [sunxi_csi.0] -> [sunxi_isp.1]
[ 5.136415] [VIN_LOG_MD]created link [sunxi_csi.0] -> [sunxi_isp.2]
[ 5.143359] [VIN_LOG_MD]created link [sunxi_csi.0] -> [sunxi_isp.3]
[ 5.150325] [VIN_LOG_MD]created link [sunxi_csi.1] -> [sunxi_isp.0]
[ 5.157251] [VIN_LOG_MD]created link [sunxi_csi.1] -> [sunxi_isp.1]
[ 5.164199] [VIN_LOG_MD]created link [sunxi_csi.1] -> [sunxi_isp.2]
[ 5.171149] [VIN_LOG_MD]created link [sunxi_csi.1] -> [sunxi_isp.3]
[ 5.178075] [VIN_LOG_MD]created link [sunxi_csi.2] -> [sunxi_isp.0]
[ 5.185037] [VIN_LOG_MD]created link [sunxi_csi.2] -> [sunxi_isp.1]
[ 5.191980] [VIN_LOG_MD]created link [sunxi_csi.2] -> [sunxi_isp.2]
[ 5.198925] [VIN_LOG_MD]created link [sunxi_csi.2] -> [sunxi_isp.3]
[ 5.205881] [VIN_LOG_MD]created link [sunxi_csi.3] -> [sunxi_isp.0]
[ 5.212867] [VIN_LOG_MD]created link [sunxi_csi.3] -> [sunxi_isp.1]
[ 5.219809] [VIN_LOG_MD]created link [sunxi_csi.3] -> [sunxi_isp.2]
[ 5.226746] [VIN_LOG_MD]created link [sunxi_csi.3] -> [sunxi_isp.3]
[ 5.233703] [VIN_LOG_MD]created link [sunxi_isp.0] => [sunxi_h3a.0]
[ 5.240656] [VIN_LOG_MD]created link [sunxi_isp.0] -> [sunxi_scaler.0]
[ 5.247900] [VIN_LOG_MD]created link [sunxi_isp.0] -> [sunxi_scaler.1]
[ 5.255128] [VIN_LOG_MD]created link [sunxi_isp.0] -> [sunxi_scaler.2]
[ 5.262388] [VIN_LOG_MD]created link [sunxi_isp.0] -> [sunxi_scaler.3]
[ 5.269635] [VIN_LOG_MD]created link [sunxi_isp.0] -> [sunxi_scaler.4]
[ 5.276860] [VIN_LOG_MD]created link [sunxi_isp.0] -> [sunxi_scaler.5]
[ 5.284105] [VIN_LOG_MD]created link [sunxi_isp.0] -> [sunxi_scaler.6]
[ 5.291347] [VIN_LOG_MD]created link [sunxi_isp.0] -> [sunxi_scaler.7]
[ 5.298598] [VIN_LOG_MD]created link [sunxi_isp.1] => [sunxi_h3a.1]
[ 5.305531] [VIN_LOG_MD]created link [sunxi_isp.1] -> [sunxi_scaler.0]
[ 5.312771] [VIN_LOG_MD]created link [sunxi_isp.1] -> [sunxi_scaler.1]
[ 5.320024] [VIN_LOG_MD]created link [sunxi_isp.1] -> [sunxi_scaler.2]
[ 5.327267] [VIN_LOG_MD]created link [sunxi_isp.1] -> [sunxi_scaler.3]
[ 5.334500] [VIN_LOG_MD]created link [sunxi_isp.1] -> [sunxi_scaler.4]
[ 5.341727] [VIN_LOG_MD]created link [sunxi_isp.1] -> [sunxi_scaler.5]
[ 5.348981] [VIN_LOG_MD]created link [sunxi_isp.1] -> [sunxi_scaler.6]
[ 5.356194] [VIN_LOG_MD]created link [sunxi_isp.1] -> [sunxi_scaler.7]
[ 5.363440] [VIN_LOG_MD]created link [sunxi_isp.2] => [sunxi_h3a.2]
[ 5.370397] [VIN_LOG_MD]created link [sunxi_isp.2] -> [sunxi_scaler.0]
[ 5.377645] [VIN_LOG_MD]created link [sunxi_isp.2] -> [sunxi_scaler.1]
[ 5.384856] [VIN_LOG_MD]created link [sunxi_isp.2] -> [sunxi_scaler.2]
[ 5.392098] [VIN_LOG_MD]created link [sunxi_isp.2] -> [sunxi_scaler.3]
[ 5.399349] [VIN_LOG_MD]created link [sunxi_isp.2] -> [sunxi_scaler.4]
[ 5.406592] [VIN_LOG_MD]created link [sunxi_isp.2] -> [sunxi_scaler.5]
[ 5.413835] [VIN_LOG_MD]created link [sunxi_isp.2] -> [sunxi_scaler.6]
[ 5.421078] [VIN_LOG_MD]created link [sunxi_isp.2] -> [sunxi_scaler.7]
[ 5.428313] [VIN_LOG_MD]created link [sunxi_isp.3] => [sunxi_h3a.3]
[ 5.435252] [VIN_LOG_MD]created link [sunxi_isp.3] -> [sunxi_scaler.0]
[ 5.442509] [VIN_LOG_MD]created link [sunxi_isp.3] -> [sunxi_scaler.1]
[ 5.449739] [VIN_LOG_MD]created link [sunxi_isp.3] -> [sunxi_scaler.2]
[ 5.456983] [VIN_LOG_MD]created link [sunxi_isp.3] -> [sunxi_scaler.3]
[ 5.464228] [VIN_LOG_MD]created link [sunxi_isp.3] -> [sunxi_scaler.4]
[ 5.471462] [VIN_LOG_MD]created link [sunxi_isp.3] -> [sunxi_scaler.5]
[ 5.478711] [VIN_LOG_MD]created link [sunxi_isp.3] -> [sunxi_scaler.6]
[ 5.485947] [VIN_LOG_MD]created link [sunxi_isp.3] -> [sunxi_scaler.7]
从打印信息发现,v4l2子设备包括有nvp6134、sunxi_csi.03、vin_cap.03、sunxi_isp.07、sunxi_scaler.07、sunxi_h3a.0~3。
5、vin_setup_default_links
vin_setup_default_links ()根据DST的配置和上面创建的entity来构建默认的media_links,也就是pipeline,打印信息如下(nvp6314):
[ 5.493174] [VIN_LOG_MD]link: source sunxi_csi.2 sink sunxi_isp.0
[ 5.499937] [VIN]vin_md_link_notify: source sunxi_csi.2, sink sunxi_isp.0, flag 1
[ 5.508246] [VIN_LOG_MD]link: source sunxi_isp.0 sink sunxi_scaler.0
[ 5.515294] [VIN]vin_md_link_notify: source sunxi_isp.0, sink sunxi_scaler.0, flag 1
[ 5.523862] [VIN_LOG_MD]vin_md_prepare_pipeline entity is vin_cap.0, group id is 0x2000
[ 5.532741] [VIN_LOG_MD]vin_md_prepare_pipeline entity is sunxi_scaler.0, group id is 0x1000
[ 5.542093] [VIN_LOG_MD]vin_md_prepare_pipeline entity is sunxi_isp.0, group id is 0x800
[ 5.551047] [VIN_LOG_MD]vin_md_prepare_pipeline entity is sunxi_csi.2, group id is 0x400
[ 5.560010] [VIN_LOG_MD]link: source sunxi_csi.2 sink sunxi_isp.0
[ 5.566763] [VIN_LOG_MD]link: source sunxi_isp.0 sink sunxi_scaler.1
[ 5.573830] [VIN]vin_md_link_notify: source sunxi_isp.0, sink sunxi_scaler.1, flag 1
[ 5.582408] [VIN_LOG_MD]vin_md_prepare_pipeline entity is vin_cap.1, group id is 0x2000
[ 5.591285] [VIN_LOG_MD]vin_md_prepare_pipeline entity is sunxi_scaler.1, group id is 0x1000
[ 5.600636] [VIN_LOG_MD]vin_md_prepare_pipeline entity is sunxi_isp.0, group id is 0x800
[ 5.609613] [VIN_LOG_MD]vin_md_prepare_pipeline entity is sunxi_csi.2, group id is 0x400
[ 5.618586] [VIN_LOG_MD]link: source sunxi_csi.2 sink sunxi_isp.0
[ 5.625358] [VIN_LOG_MD]link: source sunxi_isp.0 sink sunxi_scaler.2
[ 5.632407] [VIN]vin_md_link_notify: source sunxi_isp.0, sink sunxi_scaler.2, flag 1
[ 5.640973] [VIN_LOG_MD]vin_md_prepare_pipeline entity is vin_cap.2, group id is 0x2000
[ 5.649837] [VIN_LOG_MD]vin_md_prepare_pipeline entity is sunxi_scaler.2, group id is 0x1000
[ 5.659196] [VIN_LOG_MD]vin_md_prepare_pipeline entity is sunxi_isp.0, group id is 0x800
[ 5.668153] [VIN_LOG_MD]vin_md_prepare_pipeline entity is sunxi_csi.2, group id is 0x400
[ 5.677129] [VIN_LOG_MD]link: source sunxi_csi.2 sink sunxi_isp.0
[ 5.683885] [VIN_LOG_MD]link: source sunxi_isp.0 sink sunxi_scaler.3
[ 5.690935] [VIN]vin_md_link_notify: source sunxi_isp.0, sink sunxi_scaler.3, flag 1
[ 5.699506] [VIN_LOG_MD]vin_md_prepare_pipeline entity is vin_cap.3, group id is 0x2000
[ 5.708371] [VIN_LOG_MD]vin_md_prepare_pipeline entity is sunxi_scaler.3, group id is 0x1000
[ 5.717715] [VIN_LOG_MD]vin_md_prepare_pipeline entity is sunxi_isp.0, group id is 0x800
[ 5.726689] [VIN_LOG_MD]vin_md_prepare_pipeline entity is sunxi_csi.2, group id is 0x400
上面红色的路径pipeline是vinc0的,为:
sensor0(NCSI0)–>CSI2–>ISP0–>VIPP0(包括stat0–>scaler0)–>vin_cap.0
对于vinc1,则有:
sensor0(NCSI0)–>CSI2–>ISP0–>VIPP1(包括stat1–>scaler1) -->vin_cap.1
根media_links信息,如果应用程序使用vinc0路径,则我们仅关心这个pipeline相关的CSIC子模块的配置。
对于Nvp6324有:
6)v4l2_device_register_subdev_nodes
遍历主设备v4l2_device下的所有subdev,并为它们创建供应用程序操作的文件节点——/dev/v4l_subdevXX。v4l2框架中除了要求驱动提供主设备的文件节点,也可以合理的提供子设备的文件节点,并提供一些ioctl方法。
其他:
vin.c文件里面的所有函数,除了驱动模型里面的init和probe等,其他函数都是在本文档使用的。运行probe之后,vin驱动还有和作用呢?这时我们注意到vin_pipe_ops结构体变量:
struct vin_core里面也包含了vin_pipeline_ops结构体指针,vin_probe()–>vin_md_register_entities() -->vin_md_register_core_entity()–> v4l2_set_subdev_hostdata():
这部分在《vin core驱动.docx》说明。