1 Linux為什么要引入Component框架?
為了讓subsystem按照一定順序初始化設備才提出來的。
subsystem中由很多設備模塊,內核加載這些模塊的時間不確定。子系統內有些模塊是需要依賴其它模塊先初始化才能進行自己初始化工作(例如v4l2 subdev和v4l2 video device),這時就要用到component框架。
例如v4l2 subdev和v4l2 video device中,誰依賴誰先創建?
v4l2 video device依賴V4l2 subdev,它要等subdev創建后再創建,同時將subdev綁定到v4l2 video device上。
1.1 高通camera kmd中component的使用
入口:camera_init是入口。
submodule_table[i].component[j].init()
對submodule table中定義的每個component做init。
相關定義:
static const struct camera_submodule_component camera_base[] = {{&cam_req_mgr_init, &cam_req_mgr_exit},{&cam_sync_init, &cam_sync_exit},{&cam_smmu_init_module, &cam_smmu_exit_module},{&cam_cpas_dev_init_module, &cam_cpas_dev_exit_module},{&cam_cdm_intf_init_module, &cam_cdm_intf_exit_module},{&cam_hw_cdm_init_module, &cam_hw_cdm_exit_module},
};
static const struct camera_submodule_component camera_isp[] = {{&cam_ife_csid_init_module, &cam_ife_csid_exit_module},{&cam_ife_csid_lite_init_module, &cam_ife_csid_lite_exit_module},{&cam_vfe_init_module, &cam_vfe_exit_module},{&cam_sfe_init_module, &cam_sfe_exit_module},{&cam_isp_dev_init_module, &cam_isp_dev_exit_module},
};
...
static const struct camera_submodule submodule_table[] = {{.name = "Camera BASE",.num_component = ARRAY_SIZE(camera_base),.component = camera_base,},{.name = "Camera TFE",.num_component = ARRAY_SIZE(camera_tfe),.component = camera_tfe,},{.name = "Camera ISP",.num_component = ARRAY_SIZE(camera_isp),.component = camera_isp,},{.name = "Camera SENSOR",.num_component = ARRAY_SIZE(camera_sensor),.component = camera_sensor},...
};
1.2 重要數據結構
- master
表示要構建的系統
struct master {struct list_head node; //用于鏈接到全局masters中bool bound; //標記當前master是否bind了const struct component_master_ops *ops; //master設備的回調接口struct device *dev;struct component_match *match; //安裝順序保存了當前master的所有component匹配條件
};
- Component
表示系統組件
struct component {struct list_head node;//用于鏈接到全局的component_list中struct master *master;//保存本組件屬于哪個master devicebool bound;//本component是否bind過const struct component_ops *ops;//本component的回調接口struct device *dev; //本組件屬于哪個設備
};
- component_match
用來匹配系統需要的組件,并規定了組件的初始化順序
struct component_match_array {void *data;//比較數據int (*compare)(struct device *, void *);//比較接口void (*release)(struct device *, void *);struct component *component;//當前比較匹配規則屬于哪個componentbool duplicate;//標記是否做移除
};struct component_match {size_t alloc;//分配了多少個比較條件對象component_match_array size_t num;//保存了多少個component匹配條件struct component_match_array *compare;//匹配條件數組地址
};
- 全局變量masters和component_list
保存整個linux系統中所有主設備的數據結構。
保存整個linux系統中所有添加到component框架里的component數據結構。
static LIST_HEAD(component_list);
static LIST_HEAD(masters);
1.3 CRM和其他component如何聯系起來?
在高通KMD框架中,CRM屬于主設備(master設備),其他cam_sync、cam_smmu、cam_cap、cam_tfe、cam_sensor等屬于組件component。
他們是通過配置cam_component_platform_drivers時聯系起來。
static struct platform_driver *const cam_component_platform_drivers[] = {
/* BASE */&cam_sync_driver,&cam_smmu_driver,&cam_cpas_driver,&cam_cdm_intf_driver,&cam_hw_cdm_driver,
#ifdef CONFIG_SPECTRA_TFE&cam_csid_ppi100_driver,&cam_tfe_driver,&cam_tfe_csid_driver,
#endif
#ifdef CONFIG_SPECTRA_ISP&cam_ife_csid_driver,&cam_ife_csid_lite_driver,&cam_vfe_driver,&cam_sfe_driver,&isp_driver,
#endif...
}
1.4 camera kmd中component如何bind
camera_submodule_component 的camera base數組中,會依次執行cam_req_mgr_init和cam_sync_init以及其他component的init函數實現。
1.4.1 crm init
cam_req_mgr_init就是crm的init,也是master設備的init。
它主要做了什么?
- 向linux系統注冊crm的platform_driver驅動
- cam_req_mgr_probe
crm的platform_driver驅動中定義了probe函數,當驅動名稱和設備名稱匹配時,調用驅動的probe函數。
這里cam_req_mgr_probe主要做了兩件事:
1)遍歷cam_component_platform_drivers按順序添加到match_list
2)添加match_list到master設備,并遍歷是否所有的component都添加完成。
如果所有的component都添加完成,嘗試初始化master_device。
嘗試初始化master_device通過調用try_to_bring_up_aggregate_device(adev,NULL),它主要做兩件事,一是查看是不是所有component_match列表里的component都已經添加到全局鏈表component_list中,二是如果所有component_match列表里的component都ready,就調用master設備的bind接口進行初始化。master的bind會順序執行各component的bind()。
(通過調用component_bind_all())
1.4.2 cam_sync init
它主要做了什么?
- 向linux系統注冊cam_sync的platform_driver驅動
- cam_sync_probe
cam_sync_probe做了什么?
為cam_sync創建一個component,并添加到component框架。
它會調用component_add()進行添加,進一步調用try_to_bring_up_masters(component),
try_to_bring_up_masters會遍歷全局鏈表master_devices中所有的master設備,嘗試bringup每一個遍歷出來的aggregate device。