完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
扫一扫,分享给好友
media_device主要有下面几个部件构成:
这里先分析media的注册 media的注册参考rkcif_mipi的代码进行分析 int rkcif_plat_init(struct rkcif_device *cif_dev, struct device_node *node, int inf_id) { ... cif_dev->media_dev.dev = dev; v4l2_dev = &cif_dev->v4l2_dev; v4l2_dev->mdev = &cif_dev->media_dev; strlcpy(v4l2_dev->name, dev_name(dev), sizeof(v4l2_dev->name)); media_device_init(&cif_dev->media_dev); ret = media_device_register(&cif_dev->media_dev); if (ret < 0) { v4l2_err(v4l2_dev, "Failed to register media device: %dn",ret); goto err_unreg_v4l2_dev; } ... } 主要分2部分,一部分是media设备初始化,一部分是media设备的注册 rkcif_plat_init()-> media_device_init() void media_device_init(struct media_device *mdev) { INIT_LIST_HEAD(&mdev->entities); INIT_LIST_HEAD(&mdev->interfaces); INIT_LIST_HEAD(&mdev->pads); INIT_LIST_HEAD(&mdev->links); INIT_LIST_HEAD(&mdev->entity_notify); mutex_init(&mdev->graph_mutex); ida_init(&mdev->entity_internal_idx); dev_dbg(mdev->dev, "Media device initializedn"); } 可以看到media_device的entities,interfaces,pads,links等链表都被初始化,可以知道后面这里东西都要链接到这里 其中entity_internal_idx是用于图遍历算法的 rkcif_plat_init()-> media_device_register() #define media_device_register(mdev) __media_device_register(mdev, THIS_MODULE) rkcif_plat_init()-> __media_device_register() int __must_check __media_device_register(struct media_device *mdev, struct module *owner) { struct media_devnode *devnode; int ret; devnode = kzalloc(sizeof(*devnode), GFP_KERNEL); if (!devnode) return -ENOMEM; /* Register the device node. */ mdev->devnode = devnode; devnode->fops = &media_device_fops; devnode->parent = mdev->dev; devnode->release = media_device_release; /* Set version 0 to indicate user-space that the graph is static */ mdev->topology_version = 0; ret = media_devnode_register(mdev, devnode, owner); if (ret < 0) { /* devnode free is handled in media_devnode_*() */ mdev->devnode = NULL; return ret; } 这里出现了media_devnode结构体,填充devnode的相关成员变量,然后注册devnode rkcif_plat_init()-> __media_device_register()-> media_devnode_register() int __must_check media_devnode_register(struct media_device *mdev, struct media_devnode *devnode, struct module *owner) { int minor; int ret; /* Part 1: Find a free minor number */ mutex_lock(&media_devnode_lock); minor = find_next_zero_bit(media_devnode_nums, MEDIA_NUM_DEVICES, 0); if (minor == MEDIA_NUM_DEVICES) { mutex_unlock(&media_devnode_lock); pr_err("could not get a free minorn"); kfree(devnode); return -ENFILE; } set_bit(minor, media_devnode_nums); mutex_unlock(&media_devnode_lock); devnode->minor = minor; devnode->media_dev = mdev; /* Part 1: Initialize dev now to use dev.kobj for cdev.kobj.parent */ devnode->dev.bus = &media_bus_type; devnode->dev.devt = MKDEV(MAJOR(media_dev_t), devnode->minor); devnode->dev.release = media_devnode_release; if (devnode->parent) devnode->dev.parent = devnode->parent; dev_set_name(&devnode->dev, "media%d", devnode->minor); device_initialize(&devnode->dev); /* Part 2: Initialize the character device */ cdev_init(&devnode->cdev, &media_devnode_fops); devnode->cdev.owner = owner; /* Part 3: Add the media and char device */ ret = cdev_device_add(&devnode->cdev, &devnode->dev); if (ret < 0) { pr_err("%s: cdev_device_add failedn", __func__); goto cdev_add_error; } /* Part 4: Activate this minor. The char device can now be used. */ set_bit(MEDIA_FLAG_REGISTERED, &devnode->flags); return 0; cdev_add_error: mutex_lock(&media_devnode_lock); clear_bit(devnode->minor, media_devnode_nums); devnode->media_dev = NULL; mutex_unlock(&media_devnode_lock); put_device(&devnode->dev); return ret; } 上面的代码主要作用就是注册/dev/mediax,没有什么需要特别注意的 |
|
|
|
你正在撰写答案
如果你是对答案或其他答案精选点评或询问,请使用“评论”功能。
1941 浏览 3 评论
rk1126实现BT601输入,输入不带IIC接口的驱动程序
3691 浏览 0 评论
2327 浏览 1 评论
3549 浏览 3 评论
RK3568 Android11让系统ntp校准时间生效,需要设置些什么
3813 浏览 1 评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-9-27 12:07 , Processed in 0.737323 second(s), Total 75, Slave 56 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号