本讲是Camera KMD ISP子系统专题的第16讲,我们讲解Camera KMD ISP子系统CRM之Session和Link。
更多资源:
资源 | 描述 |
---|---|
在线课程 | 极客笔记在线课程 |
知识星球 | 星球名称:深入浅出Android Camera 星球ID: 17296815 |
极客笔记圈 |
Session
session之间关系
crm session与umd关系
- 一个crm session对应一个camx session
- 一个crm session对应一个虚拟session, 例如eeprom在camx session创建之前就需要读取eeprom数据,这时会创建一个virtual session对应底层一个crm session
crm session在umd代理
CSLHwsession g_CSLHwInstance.sessionList[256]
crm session在kmd存在形式
struct cam_req_mgr_core_session {
int32_t session_hdl;//crm session句柄
uint32_t num_links;//有多少个crm link
struct cam_req_mgr_core_link *links[MAXIMUM_LINKS_PER_SESSION];//crm link数组
struct list_head entry;//链表节点串联多个crm session
struct mutex lock;
int32_t force_err_recovery;//标志是否需要强制error恢复
int32_t sync_mode;//多摄时同步模式
};
list_add(&cam_session->entry, &g_crm_core_dev->session_head);
Virtual session创建过程
Camx session创建过程
Crm session创建过程KMD部分
static long cam_private_ioctl(struct file *file, void *fh, bool valid_prio, unsigned int cmd, void *arg)
{
switch (k_ioctl->op_code) {
case CAM_REQ_MGR_CREATE_SESSION: {
cam_req_mgr_create_session(&ses_info);
}
break;
}
int cam_req_mgr_create_session(struct cam_req_mgr_session_info *ses_info)
{
//在kmd分配一个crm session
struct cam_req_mgr_core_session *cam_session = kzalloc(sizeof(*cam_session), GFP_KERNEL);
session_hdl = cam_create_session_hdl((void *)cam_session);//为crm session创建一个handle
ses_info->session_hdl = session_hdl;//session handle返回到umd
cam_session->session_hdl = session_hdl;//session handle保存到kmd
list_add(&cam_session->entry, &g_crm_core_dev->session_head);//保存创建的crm session到全局链表session_head中
}
Link
Link 是什么
- Link是crm用于精准控制实时设备的重要数据结构,里面维护了所有的实时设备句柄
- Link与umd的pipeline不是一一对应关系,上层realtime pipeline会在crm创建一个link与之对应
Link 结构体
struct cam_req_mgr_core_link {
int32_t link_hdl;//link句柄
int32_t num_devs;//有多少个rt设备
struct cam_req_mgr_core_workq *workq;//用于异步任务的工作队列
int32_t pd_mask;//标志有哪些pipeline delay的设备
struct cam_req_mgr_connected_device *l_dev;//保存所有的rt设备
struct cam_req_mgr_req_data req;//request data管理,例如in_q
struct cam_req_mgr_timer *watchdog;//监控sof freeze的看门狗
void *parent;//属于哪个crm session
}
Link 创建流程UMD部分
Link 创建流程KMD部分
static long cam_private_ioctl(struct file *file, void *fh, bool valid_prio, unsigned int cmd, void *arg)
{
switch (k_ioctl->op_code) {
case CAM_REQ_MGR_LINK_V2: {
cam_req_mgr_link_v2(&ver_info);
}
break;
}
int cam_req_mgr_link_v2(struct cam_req_mgr_ver_info *link_info)
{
1. 为session预留一个link
link = __cam_req_mgr_reserve_link(cam_session);
2. 为link创建唯一的句柄
link->link_hdl = cam_create_device_hdl(&root_dev);
3. 为所有的rt devices分配内存,由link->l_dev记录
__cam_req_mgr_create_subdevs(&link->l_dev, link_info->u.link_info_v2.num_devices);
4. 使用各个device ops 查询所有的rt device获得设备信息,初始化in_q和request tables等
__cam_req_mgr_setup_link_info(link, link_info)
}
__cam_req_mgr_reserve_link(cam_session)
{
link = &g_links[i];//从全局g_links数组中取出一个未占用的Link
//为link->req.in_q分配一个in_q
in_q = kzalloc(sizeof(struct cam_req_mgr_req_queue),GFP_KERNEL);
link->req.in_q = in_q;
//关联crm session和link
link->parent = (void *)session;
session->num_links++;
}
__cam_req_mgr_setup_link_info(link, link_info)
{
//初始化link->req.in_q
__cam_req_mgr_setup_in_q(&link->req);
//获取rt device的设备信息,例如pipeline delay
for (i=0; i<num_devices; i++)
{
dev->ops->get_dev_info(&dev->dev_info);
}
//为不同pipeline delay创建request table,并通知设备link_setup
for (i=0; i<num_devices; i++)
{
pd_tbl = __cam_req_mgr_create_pd_tbl(dev->dev_info.p_delay);
__cam_req_mgr_add_tbl_to_link(&link->req.l_tbl, pd_tbl);
}
//刚启动时,pd 1的 table不需要遍历,会忽略一次。这里需要手动设置一下
__cam_req_mgr_tbl_set_all_skip_cnt(&link->req.l_tbl);
}