【高通SDM660平臺 Android 10.0】18 --- Actuator 與 Kernel Actuator代碼分析 及 Camera start_session過程分析
《【高通SDM660平臺】(1) — Camera 驅動 Bringup Guide》
《【高通SDM660平臺】(2) — Camera Kernel 驅動層代碼邏輯分析》
《【高通SDM660平臺】(3) — Camera V4L2 驅動層分析 》
《【高通SDM660平臺】(4) — Camera Init 初始化流程 》
《【高通SDM660平臺】(5) — Camera Open 流程》
《【高通SDM660平臺】(6) — Camera getParameters 及 setParameters 流程》
《【高通SDM660平臺】(7) — Camera onPreview 代碼流程》
《【高通SDM660平臺】(8) — Camera MetaData介紹》
《【高通SDM660平臺 Android 10.0】(9) — Qcom Camera Daemon 代碼分析》
《【高通SDM660平臺 Android 10.0】(10) — Camera Sensor lib 與 Kernel Camera Probe 代碼分析》
《【高通SDM660平臺 Android 10.0】(11) — Eeprom lib 與 Kernel eeprom代碼分析》
《【高通SDM660平臺 Android 10.0】(12) — Camera Chromatix 代碼分析》
《【高通SDM660平臺 Android 10.0】(18) — Camera start_session() 過程分析》
《【高通SDM660平臺 Android 10.0】(19) — Camera_focus、Camera_snapshot、volume_up 按鍵工作原理分析》
《【高通SDM660平臺 Android 10.0】(20) — Actuator 與 Kernel Actuator代碼分析》
本來打算分析 flash 、Actuator 等 碼流程,但它位的初始化,都是在 start_session()中,所以,我們今天先來看下 start_session()的流程
1. module_sensor_init( )
在 module_sensor_init()
方法中,將 module_sensor_start_session
函數保存在結構體 s_module->start_session
中,
我們今天就要從它談起。
mct_module_t *module_sensor_init(const char *name)
{`
s_module->start_session = module_sensor_start_session;
s_module->stop_session = module_sensor_stop_session;
/* module_sensor_probe_sensors */
ret = sensor_init_probmodus */
ret = mct_list_traverse(module_ctrl->sensor_bundle, module_sensors_subinit, NULL);
/* Create ports based on CID info */
ret = mct_list_traverse(module_ctrl->sensor_bundle, port_sensor_create, s_module);
ret = mct_list_traverse(module_ctrl->sensor_bundle, module_sensor_init_eeprom, module_ctrl->eebin_hdl);
ret = mct_list_traverse(module_ctrl->sensor_bundle, module_sensor_init_chromatix, module_ctrl->eebin_hdl);
}
1.1 module_sensor_start_session( )
在module_sensor_start_session
中主要工作如下:
- 獲取
module_ctrl
結構體 - 通過
session id
獲取 對應的s_bundle
結構體 - 默認關閉 手電筒,紅外線
- 創建名爲
CAM_sensor
的pthread 線程,用於監聽拍照過程中的SET_AUTOFOCUS
,OFFLOAD_FUNC
事件 - 加載sensor lib,對sensor 進行上電,打開所有外設,初始化
# mm-camera/mm-camera2/media-controller/modules/sensors/module/module_sensor.c
static boolean module_sensor_start_session( mct_module_t *module, uint32_t sessionid)
{
// 1. 獲取 module_ctrl 結構體
SHIGH("sessionid %d", sessionid);
module_ctrl = (module_sensor_ctrl_t *)module->module_private;
ATRACE_CAMSCOPE_BEGIN(CAMSCOPE_SENSOR_START_SESSION);
// 2. 通過 session id 獲取 對應的 s_bundle 結構體
/* get the s_bundle from session id */
s_list = mct_list_find_custom(module_ctrl->sensor_bundle, &sessionid, sensor_util_find_bundle);
s_bundle = (module_sensor_bundle_info_t *)s_list->data;
// 3. 默認關閉 手電筒,紅外線
/* initialize the "torch on" flag to 0 */
s_bundle->torch_on = 0;
s_bundle->longshot = 0;
s_bundle->ir_mode = SENSOR_IR_MODE_OFF;
// 4. 創建名爲 CAM_sensor 的pthread 線程,用於監聽拍照過程中的 SET_AUTOFOCUS(自動對焦),OFFLOAD_FUNC(轉移函數運行) 事件
/* create sensor thread */
ret = sensor_thread_create(s_bundle);
===========>
+ ret = pthread_create(&thread.td, &attr, sensor_thread_func, &thread );
+ pthread_setname_np(thread.td, "CAM_sensor");
+ ------------>
+ // mm-camera/mm-camera2/media-controller/modules/sensors/sensor/module/sensor_thread.c
+ while(!thread_exit){
+ ready = poll(&pollfds, (nfds_t)num_of_fds, -1);
+ nread = read(pollfds.fd, &msg, sizeof(sensor_thread_msg_t));
+ sensor_process_thread_message(&msg);
+ }
+ <------------
<===========
/* Reset phase correction parameters when session starts */
module_sensor_dualcamera_reset_pc_params(s_bundle);
// 5. 加載sensor lib,對sensor 進行上電,打開所有外設,初始化
/* this init session includes
power up sensor, config init setting */
ret = module_sensor_init_session(s_bundle, module_ctrl->eebin_hdl);
/* Power up peer sensor if in stereo mode. */
if (TRUE == s_bundle->is_stereo_configuration && s_bundle->stereo_peer_s_bundle != NULL) {
SERR("Powering up peer stereo sensor. ");
ret = module_sensor_init_session(s_bundle->stereo_peer_s_bundle, module_ctrl->eebin_hdl);
}
SHIGH("SUCCESS");
ATRACE_CAMSCOPE_END(CAMSCOPE_SENSOR_START_SESSION);
return TRUE;
}
1.2 module_sensor_init_session()
主要工作如下:
- session 相關標誌位初始化
- 初始化幀緩存隊列,默認
FRAME_CTRL_SIZE = 7
- 獲取該 camera 對應所有外設的信息。
- 獲取 eeprom 結構體數據
- 打開所有外設節點,將sensor open 方法轉移到 sensor thread 中,運行函數爲
module_sensor_offload_open()
(thead 也就是我們前面CAM_sensor
的pthread
線程,名爲sensor_thread_func
) - 打開所有外設節點,相關信息,以
actuator_data_t *
結構體信息返回在s_bundle->module_sensor_params[i]->sub_module_private
中 - 等待
module_sensor_offload_open()
函數,打開外設成功後,發送的pthread_cond_signal(&s_bundle->cond);
此時置位標誌位open_done = TRUE
- 註冊 Chromatix mamnager
- 如果使能了
camera.eztune.enable
,則重新加載初始化 chromatix - 如果定義了其他的lib 庫,則在此處加載功
- 將
sensor init config
方法轉移到 sensor thread 中,運行函數爲module_sensor_offload_init_config()
。 - 調用 camera sensor 方法,處理
SENSOR_SET_FORMATTED_CAL_DATA
,也就是調用sensor_set_formatted_cal_data(sctrl, data);
設置s_bundle->formatted_data
爲camera otp
數據
formatted_data
是在初始化 eeprom 時向kernel 下發命令EEPROM_GET_FORMATTED_DATA
獲取的 - 如果支持 LASER 的話,此時對鐳射初始化
# mm-camera/mm-camera2/media-controller/modules/sensors/module/module_sensor.c
/** module_sensor_init_session: init session function for sensor
*
* @s_bundle: sensor bundle pointer pointing to the sensor for which stream is added
* @eebin_hdl: pointing to eeprom bin data
*
* Return: 0 for success and negative error for failure
*
* When called first time, this function
* 1) opens all sub modules to open subdev node
* 2) loads sensor library
* 3) calls init on sensor, csiphy and csid. Has ref count to ensure that actual add stream sequence is executed only once
***/
static boolean module_sensor_init_session( module_sensor_bundle_info_t *s_bundle, void *eebin_hdl)
{
int32_t rc = SENSOR_SUCCESS, i = 0, j = 0, k = 0;
module_sensor_params_t *module_sensor_params = NULL;
module_sensor_params_t *actuator_module_params = NULL;
module_sensor_params_t *csiphy_module_params = NULL;
module_sensor_params_t *csid_module_params = NULL;
module_sensor_params_t *eeprom_module_params = NULL;
module_sensor_params_t *flash_module_params = NULL;
enum sensor_sub_module_t s_module;
af_algo_tune_parms_t *af_algo_cam_ptr = NULL;
af_algo_tune_parms_t *af_algo_camcorder_ptr = NULL;
actuator_driver_params_t *af_driver_ptr = NULL;
// 1. session 相關標誌位初始化
/* Initialize max width, height and stream on count */
s_bundle->peer_identity = 0;
s_bundle->max_width = 0;
s_bundle->max_height = 0;
s_bundle->stream_on_count = 0;
s_bundle->stream_mask = 0;
s_bundle->last_idx = 0;
s_bundle->delay_frame_idx = 0;
s_bundle->num_skip = 4; // 跳過的幀數
s_bundle->state = 0;
s_bundle->block_parm = 0;
s_bundle->regular_led_trigger = 0;
s_bundle->main_flash_on_frame_skip = 0;
s_bundle->main_flash_off_frame_skip = 0;
s_bundle->torch_on_frame_skip = 0;
s_bundle->torch_off_frame_skip = 0;
s_bundle->last_flash_request = CAM_FLASH_MODE_OFF;
s_bundle->flash_params.flash_mode = CAM_FLASH_MODE_OFF;
s_bundle->flash_params.flash_state = CAM_FLASH_STATE_READY;
s_bundle->torch_on = 0;
s_bundle->longshot = 0;
s_bundle->led_off_count = -1;
s_bundle->flash_rer_enable = 0;
s_bundle->ois_cmd_queue_mask = 0x0000;
s_bundle->ois_enabled = 0;
s_bundle->ois_mode = OIS_DISABLE;
s_bundle->hal_params.test_pattern_mode = CAM_TEST_PATTERN_OFF;
s_bundle->stream_thread_wait_time = 5;
s_bundle->actuator_sensitivity = 0;
s_bundle->ir_mode = SENSOR_IR_MODE_OFF;
s_bundle->retry_frame_skip = 0;
s_bundle->init_config_done = 0;
s_bundle->open_done = 0;
s_bundle->is_plain16 = 0;
s_bundle->close_done = 0;
s_bundle->delay_frame_cnt = 0;
s_bundle->cur_scene_mode = -1;
memset(prop, 0, sizeof(prop));
property_get("persist.vendor.partial.skip", prop, "1");
s_bundle->partial_flash_frame_skip = atoi(prop);
s_bundle->sensor_params.flash_mode = CAM_FLASH_MODE_OFF;
s_bundle->is_first_stream_on = 1;
s_bundle->is_camera_closing = 0;
memset(s_bundle->isp_frameskip, 0, sizeof(s_bundle->isp_frameskip));
memset(s_bundle->identity, 0, sizeof(s_bundle->identity));
memset(&s_bundle->cap_control, 0, sizeof(sensor_capture_control_t));
memset(&s_bundle->hal_frame_batch, 0, sizeof(cam_capture_frame_config_t));
memset(&s_bundle->dualc_info, 0, sizeof(sensor_dualc_info));
/* initialize condition variable */
pthread_condattr_init(&s_bundle->fast_aec_condattr);
pthread_condattr_setclock(&s_bundle->fast_aec_condattr, CLOCK_MONOTONIC);
pthread_cond_init(&s_bundle->fast_aec_cond, &s_bundle->fast_aec_condattr);
/* initialize mutex */
pthread_mutex_init(&s_bundle->fast_aec_mutex, NULL);
/* initialize flash control mutex */
pthread_mutex_init(&s_bundle->capture_control_mutex, NULL);
// 2. 初始化幀緩存隊列,默認 FRAME_CTRL_SIZE = 7
/* Initialize frame control queues*/
for (j = 0; j < FRAME_CTRL_SIZE; j++) {
s_bundle->frame_ctrl.frame_ctrl_q[j] = (mct_queue_t*)CAM_CALLOC(1, sizeof(mct_queue_t));
JUMP_ON_NULL(s_bundle->frame_ctrl.frame_ctrl_q[j], ERROR0);
mct_queue_init(s_bundle->frame_ctrl.frame_ctrl_q[j]);
/* Initialize frame control mutex */
pthread_mutex_init(&s_bundle->frame_ctrl.frame_ctrl_mutex[j], NULL);
}
// 3. 獲取該 camera 對應所有外設的信息。
for (i = 0; i < SUB_MODULE_MAX; i++) {
intf_info = &s_bundle->subdev_info[i].intf_info[SUBDEV_INTF_PRIMARY];
SLOW("primary sd index = %d, id = %d subdev name %s,",i, intf_info->subdev_id, intf_info->sensor_sd_name);
intf_info = &s_bundle->subdev_info[i].intf_info[SUBDEV_INTF_SECONDARY];
SLOW("secondary sd index %d subdev name %s, secondary id = %d", i, intf_info->sensor_sd_name, s_bundle->sensor_info->subdev_intf[i]);
}
// 4. 獲取 eeprom 結構體數據
/* eeprom control is already created at cam daemon init */
s_bundle->module_sensor_params[SUB_MODULE_EEPROM]->sub_module_private =
s_bundle->eeprom_data;
// 5. 打開所有外設節點,
// 將sensor open 方法轉移到 sensor thread 中,運行函數爲 `module_sensor_offload_open()`。
//(thead 也就是我們前面CAM_sensor 的pthread線程,名爲sensor_thread_func)
/* offload open to sensor thread */
msg.msgtype = OFFLOAD_FUNC;
msg.offload_func = module_sensor_offload_open;
msg.param1 = s_bundle;
msg.param2 = NULL;
msg.param3 = NULL;
msg.param4 = NULL;
msg.stop_thread = FALSE;
nwrite = write(s_bundle->pfd[1], &msg, sizeof(sensor_thread_msg_t));
if (nwrite < 0) {
SERR("%s: offload open: Writing into fd failed:", __func__);
module_sensor_offload_open(s_bundle, eebin_hdl, NULL, NULL);
if (s_bundle->open_done < 0)
goto ERROR1;
}
// 6. 打開所有外設節點,相關信息,以 `actuator_data_t *` 結構體信息返回在 `s_bundle->module_sensor_params[i]->sub_module_private` 中
ATRACE_CAMSCOPE_BEGIN(CAMSCOPE_SENSOR_SD_OPEN);
for (i = 0; i < SUB_MODULE_MAX; i++) {
if (s_bundle->module_sensor_params[i]->func_tbl.open && !s_bundle->subdev_info[i].sub_mod_open_flag) {
rc = s_bundle->module_sensor_params[i]->func_tbl.open( &s_bundle->module_sensor_params[i]->sub_module_private,
&s_bundle->subdev_info[i]);
}
}
ATRACE_CAMSCOPE_END(CAMSCOPE_SENSOR_SD_OPEN);
// 7. 等待module_sensor_offload_open() 函數,打開外設成功後,發送的pthread_cond_signal(&s_bundle->cond);
// 此時置位標誌位 open_done = TRUE
TIMED_WAIT_ON_EVENT(s_bundle->mutex, s_bundle->cond,
ts, OPEN_TIMEOUT, s_bundle->open_done,
TRUE, "open_done");
// 8. 註冊 Chromatix mamnager
// 調用 func_tbl.process ,處理事件 CHROMATIX_SET_CM,將 chromatix_ctrl ctrl->cm = s_bundle->chromatix_manager
/* register chromatix manager to chromatix sub module */
SENSOR_SUB_MODULE_PROCESS_EVENT(s_bundle, SUB_MODULE_CHROMATIX,
CHROMATIX_SET_CM, &s_bundle->chromatix_manager, rc);
for (k = 0; k < (int32_t)ARRAY_SIZE(eebin_load); k++) {
s_module = eebin_load[k].s_module;
if (s_bundle->module_sensor_params[s_module]->func_tbl.process) {
rc = s_bundle->module_sensor_params[s_module]->func_tbl.process(
s_bundle->module_sensor_params[s_module]->sub_module_private,eebin_load[k].p_event, eebin_hdl);
}
}
// 9. 如果使能了 camera.eztune.enable,則重新加載初始化 chromatix
/* reload all chromatix for each session only for eztune */
property_get("persist.vendor.camera.eztune.enable", prop, "0");
eztune_enable = atoi(prop);
SLOW("eztune enabled %d", eztune_enable);
if (eztune_enable) {
/* clear all the present chromatix before */
cm_destroy(&s_bundle->chromatix_manager);
/* reload chromatix files */
status = module_sensor_init_chromatix(s_bundle,eebin_hdl);
}
// 10. 如果定義了其他的lib 庫,則在此處加載功
/* Load external libraries */
if (s_bundle->sensor_lib_params->sensor_lib_ptr->external_library) {
status = module_sensor_load_external_libs(s_bundle);
if (status == FALSE) {
SERR("failed: module_sensor_load_external_libs");
goto ERROR1;
}
}
// 11. 將sensor init config 方法轉移到 sensor thread 中,運行函數爲 `module_sensor_offload_init_config()`。
/* offload init config to sensor thread */
msg.msgtype = OFFLOAD_FUNC;
msg.offload_func = module_sensor_offload_init_config;
msg.param1 = s_bundle;
msg.param2 = eebin_hdl;
msg.param3 = NULL;
msg.param4 = NULL;
msg.stop_thread = FALSE;
nwrite = write(s_bundle->pfd[1], &msg, sizeof(sensor_thread_msg_t));
if (nwrite < 0) {
SERR("%s: offload init config: Writing into fd failed:",__func__);
module_sensor_offload_init_config(s_bundle, eebin_hdl, NULL, NULL);
}
// 12. 調用 camera sensor 方法,處理 SENSOR_SET_FORMATTED_CAL_DATA ,也就是調用 sensor_set_formatted_cal_data(sctrl, data);
// 設置 s_bundle->formatted_data 爲 camera otp 數據
// formatted_data 是在初始化 eeprom 時 下發命令 EEPROM_GET_FORMATTED_DATA 獲取的
SENSOR_SUB_MODULE_PROCESS_EVENT(s_bundle, SUB_MODULE_SENSOR,
SENSOR_SET_FORMATTED_CAL_DATA, s_bundle->formatted_data, rc);
// 13. 如果支持 LASER 的話,此時對鐳射初始化
if (s_bundle->sensor_lib_params->sensor_lib_ptr->sensor_output.is_depth_sensor) {
SENSOR_SUB_MODULE_PROCESS_EVENT(s_bundle, SUB_MODULE_LASER_LED,
LASER_LED_INIT, NULL, rc);
}
SHIGH("Success : sensor_name:%s",
s_bundle->sensor_lib_params->sensor_lib_ptr->sensor_slave_info.sensor_name);
return TRUE;
}
1.3 module_sensor_offload_init_config( )
- 解析
sdm660_camera.xml
中的旋轉角度<MountAngle>
- 析像頭的位置,如
CAM_POSITION_BACK(0)
,CAM_POSITION_FRONT(1)
,CAM_POSITION_BACK_AUX(4)
- 解析
sdm660_camera.xml
中的<ModesSupported>
- 獲取
sensor_property
, 其定義在sensor lib.h
中,
如mm-camera/mm-camera2/media-controller/modules/sensors/sensor/libs/s5k3l8/s5k3l8_lib.h
下的.sensor_property
屬性 - 解析
sdm660_camera.xml
中的 lens 信息<LensInfo>
- Camera sensor 初始化,停止senosr 數據流,VDDIO上電,下發初始化參數
- 如果需要修改 i2c ,此開始重寫 i2c 寄存器
- 獲取並設置senoor 的otp 數據
獲取Camera otp 數據是在否sensor 內部做 isp,還是在平臺端 中做isp , is_insensor
獲取otp數據,並且把 otp 數據寫入sensor 中。
// 注,有些sensor 是在sensor 內部做isp, 所以會用到 這些數據。
// 絕大多數的 sensor isp 是在平臺端做的。 - 初始化閃光燈 ,調用
flash_init()
,打開閃光燈 lib 庫 -----> 後面分析閃光燈代碼流程時,就直接從這裏跳入了 - 獲取使用閃光燈時,跳過的幀數,如果沒設置,默認過濾 2 幀
- 初始化馬達
- 如果定義了其他的庫,則直接加載
- 解析快速 AEC 時,跳過的幀數
- 解析 ext_pipeline_delay
void module_sensor_offload_init_config( void* param1, void* param2, void* param3 __attribute__((unused)),
void* param4 __attribute__((unused)))
{
module_sensor_bundle_info_t *s_bundle = (module_sensor_bundle_info_t *)param1;
void *eebin_hdl = param2;
int32_t rc = SENSOR_SUCCESS, i = 0, j = 0, k = 0;
module_sensor_params_t *module_sensor_params = NULL;
module_sensor_params_t *eeprom_module_params = NULL;
sensor_get_t sensor_get;
sensor_property_t sensor_property;
eebin_ctl_t bin_ctl;
enum sensor_sub_module_t s_module;
af_algo_tune_parms_t *af_algo_cam_ptr = NULL;
af_algo_tune_parms_t *af_algo_camcorder_ptr = NULL;
actuator_driver_params_t *af_driver_ptr = NULL;
boolean status = TRUE;
boolean live_connect_enabled = FALSE;
char prop[PROPERTY_VALUE_MAX];
module_sensor_params = s_bundle->module_sensor_params[SUB_MODULE_SENSOR];
// 1. 解析 sdm660_camera.xml 中的旋轉角度 <MountAngle>
/* set mount angle, position and modes_supported */
if (s_bundle->sensor_info->is_mount_angle_valid == 1)
if (s_bundle->sensor_common_info.camera_config.sensor_mount_angle >= SENSOR_MOUNTANGLE_360)
s_bundle->sensor_common_info.camera_config.sensor_mount_angle =s_bundle->sensor_info->sensor_mount_angle;
// 2. 解析像頭的位置,如 CAM_POSITION_BACK(0),CAM_POSITION_FRONT(1), CAM_POSITION_BACK_AUX(4)
switch(s_bundle->sensor_info->position) {
case BACK_CAMERA_B: // 0 後報
s_bundle->sensor_common_info.camera_config.position = CAM_POSITION_BACK; break;
case FRONT_CAMERA_B: // 1 前攝
s_bundle->sensor_common_info.camera_config.position = CAM_POSITION_FRONT; break;
case AUX_CAMERA_B: // 4 後二攝
s_bundle->sensor_common_info.camera_config.position = CAM_POSITION_BACK_AUX; break;
}
// 3. 解析 sdm660_camera.xml 中的 <ModesSupported>
if (s_bundle->sensor_info->modes_supported != CAMERA_MODE_INVALID)
s_bundle->sensor_common_info.camera_config.modes_supported = s_bundle->sensor_info->modes_supported;
s_bundle->sensor_params.aperture_value = 0;
memset(&sensor_property, 0, sizeof(sensor_property));
// 4. 獲取 sensor_property, 其定義在 sensor lib.h 中,
// 如mm-camera/mm-camera2/media-controller/modules/sensors/sensor/libs/s5k3l8/s5k3l8_lib.h
// 下的 .sensor_property 屬性
/* get lens info to sensor sub module */
rc = module_sensor_params->func_tbl.process(
module_sensor_params->sub_module_private, SENSOR_GET_PROPERTY, &sensor_property);
// 5. 解析 sdm660_camera.xml 中的lens 信息 <LensInfo>
{
/* Fill aperture */
s_bundle->sensor_params.aperture_value = s_bundle->sensor_common_info.camera_config.lens_info.f_number;
s_bundle->sensor_params.f_number =_bundle->sensor_common_info.camera_config.lens_info.f_number;
s_bundle->sensor_params.focal_length = s_bundle->sensor_common_info.camera_config.lens_info.focal_length;
s_bundle->sensor_params.sensing_method = sensor_property.sensing_method;
s_bundle->sensor_params.crop_factor = sensor_property.crop_factor;
SLOW("aperture %f", s_bundle->sensor_params.aperture_value);
}
// 6. Camera sensor 初始化
/* af_actuator_init */
/* get actuator header */
/* sensor init */
rc = module_sensor_params->func_tbl.process( module_sensor_params->sub_module_private,SENSOR_INIT, NULL);
====================>
static int32_t sensor_init(void *sctrl)
{
// 停止senosr 數據流
rc = sensor_set_stop_stream_settings(ctrl);
// VDDIO 上電
rc = sensor_power_up(ctrl);
=========>
+ cfg.cfgtype = CFG_POWER_UP;
+ LOG_IOCTL(ctrl->s_data->fd, VIDIOC_MSM_SENSOR_CFG, &cfg, "power_up");
<=========
// 下發 Camera 初始化參數
rc = sensor_write_init_settings(sctrl);
}
<====================
// 7. 如果需要修改 i2c ,此開始重寫 i2c 寄存器
/* Set alternative slave address if needed */
rc = module_sensor_params->func_tbl.process( module_sensor_params->sub_module_private,
SENSOR_SET_ALTERNATIVE_SLAVE, &s_bundle->sensor_common_info.camera_config.sensor_slave_addr);
/*Disabling fast aec by default. Will be enabled only based on HAL input */
s_bundle->fast_aec_required = FALSE;
// 8. 獲取並設置senoor 的otp 數據
if (s_bundle->sensor_info->subdev_id[SUB_MODULE_EEPROM] != -1) {
struct msm_camera_i2c_reg_setting cal_setting;
int32_t is_insensor = 0;
// 8.1 獲取Camera otp 數據是在否sensor 內部做 isp,還是在平臺端 中做isp , is_insensor
/* Check if eeprom has cal data for sensor module. */
SENSOR_SUB_MODULE_PROCESS_EVENT(s_bundle, SUB_MODULE_EEPROM, EEPROM_GET_ISINSENSOR_CALIB, &is_insensor, rc);
// 8.2 獲取otp數據,並且把 otp 數據寫入sensor 中。
// 注,有些sensor 是在sensor 內部做isp, 所以會用到 這些數據。
// 絕大多數的 sensor isp 是在平臺端做的。
/* If yes, apply cal data to the sensor module. */
if (is_insensor) {
SENSOR_SUB_MODULE_PROCESS_EVENT(s_bundle, SUB_MODULE_EEPROM, EEPROM_GET_RAW_DATA, &cal_setting, rc);
SENSOR_SUB_MODULE_PROCESS_EVENT(s_bundle, SUB_MODULE_SENSOR, SENSOR_SET_CALIBRATION_DATA, &cal_setting, rc);
}
}
// 9. 初始化閃光燈 ,調用 flash_init(),打開閃光燈 lib 庫
SLOW("flash subdev id = %d",
status = module_sensor_flash_init(s_bundle);
// 10. 獲取使用閃光燈時,跳過的幀數,如果沒設置,默認過濾 2 幀
/* Get led frame skip timing parameters */
SENSOR_SUB_MODULE_PROCESS_EVENT(s_bundle, SUB_MODULE_LED_FLASH, LED_FLASH_GET_FRAME_SKIP_TIME_PARAMS, s_bundle, rc);
if (rc < 0) {
SERR("failed to get led off frame skip time");
s_bundle->main_flash_on_frame_skip = 2;
s_bundle->main_flash_off_frame_skip = 2;
s_bundle->torch_on_frame_skip = 2;
s_bundle->torch_off_frame_skip = 2;
}
// 11. 初始化馬達
status = module_sensor_actuator_init_calibrate(s_bundle);
// 12. 如果定義了其他的庫,則直接加載
/* Load external libraries */
if (s_bundle->sensor_lib_params->sensor_lib_ptr->external_library) {
status = module_sensor_load_external_libs(s_bundle);
}
// 13. 解析快速 AEC 時,跳過的幀數
/* Get fast AEC capabilities */
rc = module_sensor_params->func_tbl.process(
module_sensor_params->sub_module_private,
SENSOR_GET_FAST_AEC_WAIT_FRAMES, &s_bundle->sensor_num_fast_aec_frame_skip);
// 14. 解析 ext_pipeline_delay
if (s_bundle->sensor_info->subdev_id[SUB_MODULE_EXT] != -1) {
SENSOR_SUB_MODULE_PROCESS_EVENT(s_bundle, SUB_MODULE_EXT,
EXT_GET_INFO, &s_bundle->ext_pipeline_delay, rc);
}
// 15. 如果支持 Camera 調試,則創建 liveconnect 線程
/* Start live connect thread if property is set */
memset(prop, 0, sizeof(prop));
property_get("persist.vendor.camera.liveconnect", prop, "0");
live_connect_enabled = atoi(prop);
if (live_connect_enabled > 0 ) {
/* Create sensor live connect thread */
status = sensor_live_connect_thread_create(s_bundle);
s_bundle->live_connect_thread_started = TRUE;
}
SHIGH("Success");
/*end*/
PTHREAD_MUTEX_LOCK(&s_bundle->mutex);
s_bundle->init_config_done = 1;
pthread_cond_signal(&s_bundle->cond);
PTHREAD_MUTEX_UNLOCK(&s_bundle->mutex);
return;
}
至此 start_session 結束