a. 总线初始化
media目录下有media_device, media_devnode和media_entity。唯一的subsys_initcall出现在media_devnode,subsys_initcall(media_devnode_init),那就从这里入手。
313 static int __init media_devnode_init(void)
314 {
315 int ret;
316
317 pr_info("Linux media interface: v0.10\n");
318 ret = alloc_chrdev_region(&media_dev_t, 0, MEDIA_NUM_DEVICES,
319 MEDIA_NAME);
320 if (ret < 0) {
321 pr_warn("unable to allocate major\n");
322 return ret;
323 }
324
325 ret = bus_register(&media_bus_type);
326 if (ret < 0) {
327 unregister_chrdev_region(media_dev_t, MEDIA_NUM_DEVICES);
328 pr_warn("bus_register failed\n");
329 return -EIO;
330 }
331
332 return 0;
333 }
根据318行,media本身是注册成为一个字符设备,alloc_chrdev_region会自动为media设备分配一个主设备号,次设备号从0~255,并在chrdevs数组中预留一个slot出来,做一些初始化的工作。
325行是注册一个名字为"media"的bus总线,总线上包含创建devices和drivers两个集合以及列表?。
b. 注册媒体节点 /dev/mediaX
通常在isp或者usbCam的驱动probe的时候会调用media_device_register。
371 int __must_check media_device_register(struct media_device *mdev)
372 {
373 int ret;
374
375 if (WARN_ON(mdev->dev == NULL || mdev->model[0] == 0))
376 return -EINVAL;
377
378 mdev->entity_id = 1;
379 INIT_LIST_HEAD(&mdev->entities);
380 spin_lock_init(&mdev->lock);
381 mutex_init(&mdev->graph_mutex);
382
383 /* Register the device node. */
384 mdev->devnode.fops = &media_device_fops;
385 mdev->devnode.parent = mdev->dev;
386 mdev->devnode.release = media_device_release;
387 ret = media_devnode_register(&mdev->devnode);
388 if (ret < 0)
389 return ret;
390
391 ret = device_create_file(&mdev->devnode.dev, &dev_attr_model);
392 if (ret < 0) {
393 media_devnode_unregister(&mdev->devnode);
394 return ret;
395 }
396
397 return 0;
398 }
设置调用者的entity_id为1,初始化了fops,主要是给用户层提供了MEDIA_IOC_DEVICE_INFO,MEDIA_IOC_ENUM_ENTITIES,MEDIA_IOC_ENUM_LINKS和MEDIA_IOC_SETUP_LINK的操作,不过Android上较多使用
的只有MEDIA_IOC_ENUM_ENTITIES。
media_devnode_register做了几个工作:
1.找到一个次设备号,
2.初始化ops为media_devnode_fops(ioctl最终指向media_device的ioctl)并注册一个字符设备,
3.注册一个媒体设备(挂载在mediabus总线上),在系统中生成了/dev/mediaX节点,
4.标明该设备已被注册。
c. Media子系统的拓扑结构
为了解决多媒体设备的复杂性和数据流动性,Media使用了一个树状结构,可以认为是一个pipeline filter架构。由三个基本元素(Entity, Pad, Link)构成, Entity代表一个实体,可以使CMOSsensor或者isp;pad隶属于Entity,用于对外的连接,可分为sink或者source两种;link表示Entity之间的链接。下图就是一个典型的双pipeline isp的拓扑结构,蓝色方框代表Entity,绿色方框代表pad,In/Out分别对应Sink/Source,pad之间的连线就是Link。
media-entity中提供了media_entity_graph_walk_start和media_entity_graph_walk_next这两个接口来遍历所有已连接并enable的Entity,采用了深度优先搜索的方式。