基于RV1126平台imx291分析 --- media部件注册 rkcif_mipi
Linux v4l2架构学习总链接
rv1126 架构如下
前面分析subdev的时候,是从imx291开始的,这里分析media部件,换个方向,从rkcif_mipi开始
这里有一部分内容需要去看subdev的分析
rkcif_mipi对于media的操作有2个地方
第一处就是注册video的时候
video_register_device()-> video_register_media_controller()
static int video_register_media_controller(struct video_device *vdev)
{
#if defined(CONFIG_MEDIA_CONTROLLER)u32 intf_type;int ret;/* Memory-to-memory devices are more complex and use* their own function to register its mc entities.*/if (!vdev->v4l2_dev->mdev || vdev->vfl_dir == VFL_DIR_M2M)return 0;/** vdev->entity 可以认为就是rkcif_mipi的entity* obj_type表示当前entity的类型* 对于video 就是 MEDIA_ENTITY_TYPE_VIDEO_DEVICE* 对于subdev 则是 MEDIA_ENTITY_TYPE_V4L2_SUBDEV* function的值* 对于video - VFL_TYPE_GRABBER* 值为 MEDIA_ENT_F_IO_V4L* 对于subdev,就需要看情况而定,驱动自己设置* 比如subdev是个sensor,则值为MEDIA_ENT_F_CAM_SENSOR* 比如subdev是个flash,则值为MEDIA_ENT_F_FLASH* 比如subdev是个连接部件,则值为MEDA_ENT_F_VID_IF_BRIDGE* 比如...*/vdev->entity.obj_type = MEDIA_ENTITY_TYPE_VIDEO_DEVICE;vdev->entity.function = MEDIA_ENT_F_UNKNOWN;switch (vdev->vfl_type) {case VFL_TYPE_GRABBER:intf_type = MEDIA_INTF_T_V4L_VIDEO;vdev->entity.function = MEDIA_ENT_F_IO_V4L;break;case VFL_TYPE_VBI:intf_type = MEDIA_INTF_T_V4L_VBI;vdev->entity.function = MEDIA_ENT_F_IO_VBI;break;case VFL_TYPE_SDR:intf_type = MEDIA_INTF_T_V4L_SWRADIO;vdev->entity.function = MEDIA_ENT_F_IO_SWRADIO;break;case VFL_TYPE_TOUCH:intf_type = MEDIA_INTF_T_V4L_TOUCH;vdev->entity.function = MEDIA_ENT_F_IO_V4L;break;case VFL_TYPE_RADIO:intf_type = MEDIA_INTF_T_V4L_RADIO;/** Radio doesn't have an entity at the V4L2 side to represent* radio input or output. Instead, the audio input/output goes* via either physical wires or ALSA.*/break;case VFL_TYPE_SUBDEV:intf_type = MEDIA_INTF_T_V4L_SUBDEV;/* Entity will be created via v4l2_device_register_subdev() */break;default:return 0;}if (vdev->entity.function != MEDIA_ENT_F_UNKNOWN) {/** entity.name 赋值*/vdev->entity.name = vdev->name;/* Needed just for backward compatibility with legacy MC API *//** 这2句没看明白具体要做什么,后面遇到再说吧*/vdev->entity.info.dev.major = VIDEO_MAJOR;vdev->entity.info.dev.minor = vdev->minor;/** 可不可以认为这个函数的作用就是就entity注册到media中* 或者说entity关联到media中* 具体分析在下面*/ret = media_device_register_entity(vdev->v4l2_dev->mdev,&vdev->entity);if (ret < 0) {pr_warn("%s: media_device_register_entity failed\n",__func__);return ret;}}....
#endifreturn 0;
}
video_register_device()-> video_register_media_controller() -> media_device_register_entity()
int __must_check media_device_register_entity(struct media_device *mdev,struct media_entity *entity)
{struct media_entity_notify *notify, *next;unsigned int i;int ret;if (entity->function == MEDIA_ENT_F_V4L2_SUBDEV_UNKNOWN ||entity->function == MEDIA_ENT_F_UNKNOWN)dev_warn(mdev->dev,"Entity type for entity %s was not initialized!\n",entity->name);/* Warn if we apparently re-register an entity */WARN_ON(entity->graph_obj.mdev != NULL);/** entity通过graph_obj.medv关联到media* 初始化links个数为0* 其中links是所有的link数量包括前向和反向已经使能是失能的* backlinks记录的是反向的links数量* 那么正向的就是 links - backlinks ?*/entity->graph_obj.mdev = mdev;INIT_LIST_HEAD(&entity->links);entity->num_links = 0;entity->num_backlinks = 0;/** 这里是得到一个编号* internal_idx是entity内部唯一编号,这个编号*/ret = ida_alloc_min(&mdev->entity_internal_idx, 1, GFP_KERNEL);if (ret < 0)return ret;entity->internal_idx = ret;mutex_lock(&mdev->graph_mutex);/** media中记录已分配的最大编号*/mdev->entity_internal_idx_max =max(mdev->entity_internal_idx_max, entity->internal_idx);/* Initialize media_gobj embedded at the entity *//** 将media通过graph_obj挂载到medv->entities链表上* 详细看下面的分析*/media_gobj_create(mdev, MEDIA_GRAPH_ENTITY, &entity->graph_obj);/* Initialize objects at the pads *//** 根据当前这个情景分析,num_pads为0* 这里先不分析*/for (i = 0; i < entity->num_pads; i++)media_gobj_create(mdev, MEDIA_GRAPH_PAD,&entity->pads[i].graph_obj);/** 根据当前这个情景分析,medv->entity_notifier链表上为空* 这里先不分析*//* invoke entity_notify callbacks */list_for_each_entry_safe(notify, next, &mdev->entity_notify, list)notify->notify(entity, notify->notify_data);/** pm是电源相关的* 详细分析在下面*/if (mdev->entity_internal_idx_max>= mdev->pm_count_walk.ent_enum.idx_max) {struct media_graph new = { .top = 0 };/** Initialise the new graph walk before cleaning up* the old one in order not to spoil the graph walk* object of the media device if graph walk init fails.*/ret = media_graph_walk_init(&new, mdev);if (ret) {mutex_unlock(&mdev->graph_mutex);return ret;}/** 在media_graph_walk_init重新分配了一个空间,地址记录在new中* media_graph_walk_cleanup将之前申请的内存空间释放* 释放的原因是,之前的不够用了*/media_graph_walk_cleanup(&mdev->pm_count_walk);/** 更新新的pm_count_walk* 具体的用法后面遇到在分析*/mdev->pm_count_walk = new;}mutex_unlock(&mdev->graph_mutex);return 0;
}
video_register_device()-> video_register_media_controller() -> media_device_register_entity() -> media_gobj_create()
void media_gobj_create(struct media_device *mdev,enum media_gobj_type type,struct media_gobj *gobj)
{BUG_ON(!mdev);/** gobj是&entity->graph_obj* 对于gobj,都有一个自己的ID*/gobj->mdev = mdev;/* Create a per-type unique object ID */gobj->id = media_gobj_gen_id(type, ++mdev->id);/** 对于entity* 挂载到medv->entities链表上* 对于pad* 挂载到medv->pads链表上* 对于link* 挂载到medv->links链表上* 对于interface* 挂载到medv->interface链表上* * 对于整个media来说,应该会有很多的entity,pad,link* 都会被挂载到media的相关链表上*/switch (type) {case MEDIA_GRAPH_ENTITY:list_add_tail(&gobj->list, &mdev->entities);break;case MEDIA_GRAPH_PAD:list_add_tail(&gobj->list, &mdev->pads);break;case MEDIA_GRAPH_LINK:list_add_tail(&gobj->list, &mdev->links);break;case MEDIA_GRAPH_INTF_DEVNODE:list_add_tail(&gobj->list, &mdev->interfaces);break;}/** 用于存储图拓扑版本的单调计数器* 每次拓扑更改时都应增加* 拓扑到底是个什么东西呢?增加一个link也算改变拓扑???*/mdev->topology_version++;dev_dbg_obj(__func__, gobj);
}
video_register_device()-> video_register_media_controller() -> media_device_register_entity() -> media_gobj_walk_init()
__must_check int media_graph_walk_init(struct media_graph *graph, struct media_device *mdev)
{return media_entity_enum_init(&graph->ent_enum, mdev);
}static inline __must_check int media_entity_enum_init(struct media_entity_enum *ent_enum, struct media_device *mdev)
{return __media_entity_enum_init(ent_enum,mdev->entity_internal_idx_max + 1);
}__must_check int __media_entity_enum_init(struct media_entity_enum *ent_enum,int idx_max)
{/** 加设idx_max值是1 * 64位系统的话,BITS_PER_LONG 为64* 那么ALIGN后 idx_max值就是64*/idx_max = ALIGN(idx_max, BITS_PER_LONG);/** idx_max/ BITS_PER_LONG 计算出有几个long的大小* ent_enum->bmap作用是什么???*/ent_enum->bmap = kcalloc(idx_max / BITS_PER_LONG, sizeof(long),GFP_KERNEL);if (!ent_enum->bmap)return -ENOMEM;bitmap_zero(ent_enum->bmap, idx_max);/** 记录idx_max的值*/ent_enum->idx_max = idx_max;return 0;
}
可以看到注册video节点的时候,调用了media_device_register_entity,会将对于的entity链接到media的entities链表,同时会初始化media的pm_count_walk,电源相关的东西
所以后面如果其他地方调用了media_device_register_entity,同样会做上面的事情。
第二部分对entity添加pad等部件
rkcif_register_stream_vdev()
static int rkcif_register_stream_vdev(struct rkcif_stream *stream,bool is_multi_input)
{...node->pad.flags = MEDIA_PAD_FL_SINK;ret = media_entity_pads_init(&vdev->entity, 1, &node->pad);if (ret < 0)goto unreg;...
}
可以看到只有1个pad,且是一个sink pad
rkcif_register_stream_vdev() -> media_entity_pads_init()
int media_entity_pads_init(struct media_entity *entity, u16 num_pads,struct media_pad *pads)
{struct media_device *mdev = entity->graph_obj.mdev;unsigned int i;if (num_pads >= MEDIA_ENTITY_MAX_PADS)return -E2BIG;/** entity中记录pad个数及pad地址*/entity->num_pads = num_pads;entity->pads = pads;/** rkcif_mipi是有mdev的* 这也是为什么要从rkcif_mipi开始分析* 因为imx291 mipi-csi等是没有mdev的* 下面的部分代码就会执行不了*/if (mdev)mutex_lock(&mdev->graph_mutex);for (i = 0; i < num_pads; i++) {/** 初始化每个pad* 记录所属的entity,这样entity与pad就是你中有我我中有你了*/pads[i].entity = entity;pads[i].index = i;if (mdev)/** media_gobj_create之前分析过了* 主要做4件事* 1. pad通过graph_obj记录medv* 2. pad通过graph_obj获取自己的id* 3. pad链接到mdev->pads链表上* 4. medv->topology_version++*/media_gobj_create(mdev, MEDIA_GRAPH_PAD,&entity->pads[i].graph_obj);}if (mdev)mutex_unlock(&mdev->graph_mutex);return 0;
}
可以看到第二部分操作就是给entity添加一个pad,并将pad链接到media pads链表上。
当前的media相关操作就这些
看到这里会疑惑,这就完了?rkcif_mipi的entity和mipi csi的entity怎么连接的?
这里之所以不分析,是因为现在分析的会很突兀,有些不容易理解,后面会再次通过subdev注册的过程找到相关的代码。
画了一个示意图,主意rkcif_mipi会注册4个video节点,之前的分析只是分析一个。
基于RV1126平台imx291分析 --- media部件注册 rkcif_mipi相关推荐
- Android 基于bmob平台的手机登录验证码注册 等功能实现
首先是基于Bmob 平台,采用MVP 开发模式.效果见图: 下面一 一给出源码: MVP 目录结构: 登录/注册的Activity: package com.example.yangzi.mvp_de ...
- 产品分享:Qt+Arm基于RV1126平台的内窥镜软硬整套解决方案(实时影像、冻结、拍照、录像、背光调整、硬件光源调整,其他产品也可使用该平台,如视频监控,物联网产品等等)
若该文为原创文章,转载请注明原文出处 本文章博客地址:[https://hpzwl.blog.csdn.net/article/details/118887440 长期持续带来更多项目与技术分享,咨 ...
- linux内核usb驱动框架,基于S3C2440平台的linux2.6.22内核版本的USB驱动框架分析
基于S3C2440平台的linux2.6.22内核版本的USB驱动框架分析 发布时间:2014-07-18 16:47:31来源:红联作者:linux08071151 driver/usb/host/ ...
- 基于边缘计算平台的分析与研究
摘 要:边缘计算作为万物互联时代的关键技术,具有广泛的应用场景.文章首先分析了边缘计算平台在推广中面临的问题:随后从架构出发分析了典型边缘计算平台,并列举了边缘计算应用场景的需求参数,最后提出了一种边 ...
- android手机舆情分析,基于Android平台的环境公共舆情监督系统研究
摘要: 近年来,随着我国社会经济的持续发展和人民生活水平的不断提高,人们的环境保护意识也在不断增长,其中城市环境质量问题逐渐成为了人们普遍关注的焦点,也成为环保部门和环保从业人员的重点研究方向.环境监 ...
- 基于 Thingsboard 平台自定义 RPC 控制类小部件示例
基于 Thingsboard 平台自定义 RPC 控制类小部件示例 1. 小部件介绍 2. 创建小部件 3. 部件编辑器 3.1 简介 3.2 资源 / HTML / CSS 3.3 JavaScri ...
- 浅谈基于物联网技术的地下综合管廊智慧管控平台建设分析
摘要:本文以物联网.GIS等技术为基础,采用文献研究等方法,在探究我国地下综合管廊管廊现状及相关技术飾基础上,对其智慧管控平台的建设展开了研究,希望能为相关研究及建设提供有价值的参考. 关键词:物联网 ...
- 基于SOA的区域卫生信息平台案例分析(转)
这篇文章是在学习过程中baidud到得,觉得在学习阶段可以看看,用的是ESB做的系统集成. 以下是原文: 一.政策与现状 国务院在<关于深化医药卫生体制改革意见>中明确提出要大力推进医药卫 ...
- P2构型并联混合动力汽车Cruise整车仿真模型 基于Cruise平台搭建整车部件等动力学模型,基于MATLAB/Simulink平台完成整车控制策略的建模
P2构型并联混合动力汽车Cruise整车仿真模型. 1.基于Cruise平台搭建整车部件等动力学模型,基于MATLAB/Simulink平台完成整车控制策略的建模,策略模型具备再生制动,最优制动力分配 ...
- 基于ALS的音乐分析及离线推荐系统的设计与实现报告
文章目录 摘要 数据说明 相关技术介绍 Sqoop概述 Spark概述 协同过滤推荐算法概述 系统设计与实现 数据分析 热门推荐 个性化推荐 前台交互展示 总结 摘要 在互联网时代,各类的音乐网站提供 ...
最新文章
- 未来,机器人帮你盖房子
- oracle package lock,Oracle 11g下重现library cache lock等待事件
- LeetCode 1057. 校园自行车分配(map有序+贪心)
- 企业要想迅速壮大,不仅需要大量的人才
- C++ Error C2664:无法将参数 1 从“const char [9]”转换为“LPCWSTR”解决方案
- OCP考点实战演练02-日常维护篇
- html+css 登录界面
- win10本机计算机策略,[本地策略组怎么打开]win10本地组策略打开方法
- 2022-2028年中国氧化铝陶瓷基板行业竞争现状及投资决策建议报告
- NShape(开源矢量图形编辑器) 入门(一)
- 文字转化为二维码(数据加密)
- What do you think about this itinerary?
- AWS之Glue使用方法
- 正确写出doublecheck的单例模式
- 方向包围盒OBB(oriented bounding box)
- 题解 CF133A 【HQ9+】
- 对ResNet的理解
- NLG评估指标chrF、chrF++介绍
- 51单片机最小系统板制作过程
- 美通企业周刊 | 中国平安将深度参与深圳公共住房建设;北京环球度假区将引入IMAX影院...
热门文章
- Python代码缩进
- 7 个优秀 WordPress LMS 在线教育系统插件比较(优点和缺点)
- 谭浩强 c语言 swap,C语言谭浩强完整教案.ppt
- linux 执行sql loader,sql loader使用例子
- 小米蓝牙耳机驱动_硬核拆解——小米蓝牙耳机
- 火山软件开发访问网页查找电话号和读写文件应用
- kodi pvr 不能安装_Kodi看电视直播教程 安装PVR IPTV Simple Client播放m3u8直播源
- matlab怎么画矩形世界地图,matlab绘制世界地图
- overleaf换模板
- matlab自适应遗传算法代码,matlab自适应遗传算法