【高通SDM660平臺 Android 10.0】(18) --- Actuator 與 Kernel Actuator代碼分析


【高通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) — Actuator 與 Kernel Actuator代碼分析》

《【高通SDM660平臺】Camera Capture 流程》
《【高通SDM660平臺】Camera mm-qcamera-app 代碼分析》
《【高通SDM660平臺 Android 10.0】 — 高通馬達、eeprom、flash 等外設代碼分析》


本文以 mm-camera/mm-camera2/media-controller/modules/sensors/configs/sdm660_camera.xml 中的第一顆Camera 馬達 lc898217xc 爲例,
藉由他來分析下,馬達庫中相關的邏輯,及kernel 驅動中馬達相關的


一、[vendor] 庫文件 libactuator_lc898217xc.so

代碼路徑位於: mm-camera/mm-camera2/media-controller/modules/sensors/actuator/libs/lc898217xc

1.1 Android.mk

# mm-camera/mm-camera2/media-controller/modules/sensors/actuator/libs/lc898217xc/Android.mk
LOCAL_C_INCLUDES := lc898217xc_actuator.h
LOCAL_SRC_FILES:= lc898217xc_actuator.c

LOCAL_MODULE     ##      := lc898217xc_actuator.c
LOCAL_SHARED_LIBRARIES := libcutils

include $(BUILD_SHARED_LIBRARY)

Android.mk 可以看出,最終將lc898217xc_actuator.c 編譯成 lc898217xc_actuator.so

1.2 lc898217xc_actuator.c

代碼比較簡單,返回actuator_lib_ptr 結構體。

#include "actuator_driver.h"

static actuator_driver_ctrl_t actuator_lib_ptr = {
#include "lc898217xc_actuator.h"
};

void *actuator_driver_open_lib(void)
{
  return &actuator_lib_ptr;
}


1.3 lc898217xc_actuator.h

{
    .actuator_params =
    {
      .module_name = "onsemi",
      .actuator_name = "lc898217xc",
      .i2c_addr = 0xE4,							// 馬達的七位地址
      .i2c_freq_mode = SENSOR_I2C_MODE_FAST,
      .i2c_data_type = CAMERA_I2C_WORD_DATA,
      .i2c_addr_type = CAMERA_I2C_BYTE_ADDR,
      .act_type = ACTUATOR_TYPE_BIVCM,
      .data_size = 12,
      .reg_tbl =
      {
        .reg_tbl_size = 1,
        .reg_params =
        {
          {
            .reg_write_type = ACTUATOR_WRITE_DAC,
            .hw_mask = 0x0000,
            .reg_addr = 0x84,
            .hw_shift = 0,
            .data_shift = 0,
          },
        },
      },
      .init_setting_size = 1,
      .init_settings =				// 馬達初始化數組
      {
        { 0xB3, CAMERA_I2C_BYTE_ADDR,
          0x00, CAMERA_I2C_BYTE_DATA, ACTUATOR_I2C_OP_POLL, 10 },
      },
    }, /* actuator_params */

    .actuator_tuned_params =
    {
      .scenario_size =
      {
        1, /* MOVE_NEAR */
        1, /* MOVE_FAR */
      },
      .ringing_scenario =
      {
        /* MOVE_NEAR */
        {
          400,
        },
        /* MOVE_FAR */
        {
          400,
        },
      },
      .initial_code = 400,
      .region_size = 1,
      .region_params =
      {
        {
          .step_bound =
          {
            400, /* Macro step boundary*/
            0, /* Infinity step boundary*/
          },
          .code_per_step = 1,
          .qvalue = 128,
        },
      },
      /* damping used as direction value */
      .damping =
      {
        /* damping[MOVE_NEAR] */
        {
          /* Scenario 0 */
          {
            .ringing_params =
            {
              /* Region 0 */
              {
                .damping_step = 0xFFF,
                .damping_delay = 1000,
                .hw_params = 0x0000180,
              },
            },
          },
        },
        /* damping[MOVE_FAR] */
        {
          /* Scenario 0 */
          {
            .ringing_params =
            {
              /* Region 0 */
              {
                .damping_step = 0xFFF,
                .damping_delay = 1000,
                .hw_params = 0x0000FE80,
              },
            },
          },
        },
      },
    }, /* actuator_tuned_params */
  },


二、[vendor] 馬達通用驅動

vendor 中馬達通用驅動代碼位於:mm-camera/mm-camera2/media-controller/modules/sensors/actuator/module/actuator.c
馬達驅動的主要入口在於 actuator_sub_module_init() 函數中,用於獲取馬達open, process,close 等方法。

# mm-camera/mm-camera2/media-controller/modules/sensors/actuator/module/actuator.c

int32_t actuator_sub_module_init(sensor_func_tbl_t *func_tbl)
{
  SDBG("Enter");
  func_tbl->open = actuator_open;
  func_tbl->process = actuator_process;
  func_tbl->close = actuator_close;
  return 0;
}

2.1 actuator 操作方法初始化

# mm-camera/mm-camera2/media-controller/modules/sensors/module/module_sensor.c
/** Initialization table **/
static int32_t (*sub_module_init[SUB_MODULE_MAX])(sensor_func_tbl_t *) = {
  [SUB_MODULE_SENSOR]       = sensor_sub_module_init,
  [SUB_MODULE_CHROMATIX]    = chromatix_sub_module_init,
  [SUB_MODULE_ACTUATOR]     = actuator_sub_module_init,
  [SUB_MODULE_EEPROM]       = eeprom_sub_module_init,
  [SUB_MODULE_LED_FLASH]    = led_flash_sub_module_init,
};

mct_module_t *module_sensor_init(const char *name)
{
	ret = sensor_init_probe(module_ctrl);
	ret = module_sensor_find_other_subdev(module_ctrl);
  	/* Init sensor modules */
  	ret = mct_list_traverse(module_ctrl->sensor_bundle, module_sensors_subinit, NULL);
}

static boolean module_sensors_subinit(void *data, void *user_data __attribute__((unused)))
{
	module_sensor_bundle_info_t *s_
	bundle = (module_sensor_bundle_info_t *)data;
	
	for (i = 0; i < SUB_MODULE_MAX; i++) 
	{
    	s_bundle->module_sensor_params[i] = malloc(sizeof(module_sensor_params_t));
		memset(s_bundle->module_sensor_params[i], 0, sizeof(module_sensor_params_t));
		
		rc = sub_module_init[i](&s_bundle->module_sensor_params[i]->func_tbl);
		if (rc < 0 || !s_bundle->module_sensor_params[i]->func_tbl.open ||
            !s_bundle->module_sensor_params[i]->func_tbl.process ||
            !s_bundle->module_sensor_params[i]->func_tbl.close) {
          	SERR("failed");
          	goto ERROR;
        }
        switch(i) {
        	case SUB_MODULE_SENSOR:
		        s_bundle->subdev_info[i].data = &(s_bundle->sensor_common_info);
		        s_bundle->subdev_info[i].sub_mod_open_flag = 0;
		        break;
        	case SUB_MODULE_CHROMATIX:
		        s_bundle->subdev_info[i].sub_mod_open_flag = 0;
		        break;
        	case SUB_MODULE_ACTUATOR:
	          	s_bundle->subdev_info[i].sub_mod_open_flag = 0;
	          	break;
	   	}
	}

從上面log, 可以看出,在 mm-qcamera-daemon 啓動過程中,將actuator 相關的操作方法,
保存在 module_ctrl->sensor_bundle->module_sensor_params[SUB_MODULE_ACTUATOR]->func_tbl中,
調用方法爲: module_ctrl->sensor_bundle->module_sensor_params[SUB_MODULE_ACTUATOR]->func_tbl.process()


2.2 actuator 的調用

前面代碼中,我們已將 actuator 的操作函數初始化在了 module_ctrl->sensor_bundle->module_sensor_params[SUB_MODULE_ACTUATOR]->func_tbl中,那它又是什麼時候被調用的呢?

2.2.1 module_sensor_start_session()

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);
}

module_sensor_start_session 中主要工作如下:

  1. 獲取 module_ctrl 結構體
  2. 通過 session id 獲取 對應的 s_bundle 結構體
  3. 默認關閉 手電筒,紅外線
  4. 創建名爲 CAM_sensor 的pthread 線程,用於監聽拍照過程中的 SET_AUTOFOCUSOFFLOAD_FUNC 事件
  5. 加載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;
}

2.2.2 module_sensor_init_session()

主要工作如下:

  1. session 相關標誌位初始化
  2. 初始化幀緩存隊列,默認 FRAME_CTRL_SIZE = 7
  3. 獲取該 camera 對應所有外設的信息。
  4. 獲取 eeprom 結構體數據
  5. 將sensor open 方法轉移到 sensor thread 中,運行函數爲 module_sensor_offload_open()
    (thead 也就是我們前面CAM_sensorpthread線程,名爲sensor_thread_func
# 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);

  TIMED_WAIT_ON_EVENT(s_bundle->mutex, s_bundle->cond,
              ts, OPEN_TIMEOUT, s_bundle->open_done,
              TRUE, "open_done");

  /* 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);
      if (rc < 0) {
        SERR("failed rc %d", rc);
        goto ERROR1;
      }
    }
  }

  /* 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);
    if (status == FALSE) {
      SERR("module_sensor_init_chromatix failed for eztune.");
      goto ERROR1;
    }
  }

  /* 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;
    }
  }

  /* 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);
    if (s_bundle->init_config_done < 0)
      goto ERROR1;
  }

  SENSOR_SUB_MODULE_PROCESS_EVENT(s_bundle, SUB_MODULE_SENSOR,
    SENSOR_SET_FORMATTED_CAL_DATA, s_bundle->formatted_data, rc);

  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;

ERROR1:
  for (i = SUB_MODULE_MAX-1; i >= 0; i--) {
    if (s_bundle->module_sensor_params[i]->func_tbl.close &&
      s_bundle->module_sensor_params[i]->sub_module_private) {
        s_bundle->module_sensor_params[i]->func_tbl.close(
          s_bundle->module_sensor_params[i]->sub_module_private);
      s_bundle->module_sensor_params[i]->sub_module_private = NULL;
    }
  }
ERROR0:
  s_bundle->ref_count--;
  for (j--; j >= 0; j--) {
    /* Free the frame control queue*/
    mct_queue_free(s_bundle->frame_ctrl.frame_ctrl_q[j]);
    s_bundle->frame_ctrl.frame_ctrl_q[j] = NULL;
    /* Destroy frame control mutex */
    pthread_mutex_destroy(&s_bundle->frame_ctrl.frame_ctrl_mutex[j]);
  }
  SERR("failed");
  return FALSE;
}


2.2.3 module_sensor_offload_open()


2.2.4 module_sensor_offload_init_config()

# mm-camera/mm-camera2/media-controller/modules/sensors/module/module_sensor_offload.c
void module_sensor_offload_init_config(
  void* param1,
  void* param2,
  void* param3 __attribute__((unused)),
  void* param4 __attribute__((unused)))
{

2.2.5 module_sensor_actuator_init_calibrate()

# mm-camera/mm-camera2/media-controller/modules/sensors/module/module_sensor.c
boolean module_sensor_actuator_init_calibrate(module_sensor_bundle_info_t *s_bundle)
{
    int32_t                  rc = 0;
    char                     *a_name = NULL;
    sensor_get_af_algo_ptr_t af_algo;
    eeprom_set_chroma_af_t   eeprom_set;
    af_algo_tune_parms_t     *af_algo_cam_ptr = NULL;
    actuator_driver_params_t *af_driver_ptr = NULL;

    /* Get the actuator name from camera config read during daemon init */
    a_name = s_bundle->sensor_common_info.camera_config.actuator_name;
    SLOW("Actuator init and calibrate for %s", a_name);

    /* Initialize the actuator */
    SENSOR_SUB_MODULE_PROCESS_EVENT(s_bundle, SUB_MODULE_ACTUATOR,
        ACTUATOR_INIT, a_name, rc);
    if (rc < 0) {
        SERR("sensor_failure : ACTUATOR_INIT failed");
        return FALSE;
    }

    /* Get diver param from actuator */
    SENSOR_SUB_MODULE_PROCESS_EVENT(s_bundle, SUB_MODULE_ACTUATOR,
        ACTUATOR_GET_AF_DRIVER_PARAM_PTR, &af_driver_ptr, rc);
    if (rc < 0 || af_driver_ptr == NULL) {
        SERR("sensor_failure : ACTUATOR_GET_AF_DRIVER_PARAM_PTR failed");
        return FALSE;
    }

    /* Set driver param to eeprom */
    eeprom_set.af_driver_ptr = af_driver_ptr;

    /* Perform calibration if eeprom is present */
    if (s_bundle->sensor_info->subdev_id[SUB_MODULE_EEPROM] != -1)
    {
        SENSOR_SUB_MODULE_PROCESS_EVENT(s_bundle, SUB_MODULE_EEPROM,
            EEPROM_CALIBRATE_FOCUS_DATA, &eeprom_set, rc);
        if (rc < 0) {
            SERR("sensor_failure : EEPROM_SET_CALIBRATE_FOCUS failed");
            return FALSE;
        }
        /* calcualte actuator sensitivity
           assuming total_steps is tuned to number of um */
        s_bundle->actuator_sensitivity =
          (float)af_driver_ptr->actuator_tuned_params.region_params[0].qvalue /
          af_driver_ptr->actuator_tuned_params.region_params[0].code_per_step;
    }
    /* protect the qvalue */
    else {
      af_driver_ptr->actuator_tuned_params.region_params[0].qvalue = 1;
    }

    SENSOR_SUB_MODULE_PROCESS_EVENT(s_bundle, SUB_MODULE_ACTUATOR,
      ACTUATOR_SET_PARAMETERS, NULL, rc);
    if (rc < 0) {
      SERR("sensor_failure : ACTUATOR_SET_PARAMETERS failed");
      return FALSE;
    }

    return TRUE;
}


三、[kernel] 馬達驅動

vendor 中馬達通用驅動代碼位於:msm-4.14/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.c


# mm-camera/mm-camera2/media-controller/modules/sensors/module/sensor_common.h

// This macro will call the process event function of submodule with event and puts the returned value in rc
#define SENSOR_SUB_MODULE_PROCESS_EVENT(s_bundle, submodule, event, data, rc)      \
    if (s_bundle->module_sensor_params[(submodule)]->func_tbl.process != NULL){    \
        rc = s_bundle->module_sensor_params[(submodule)]->func_tbl.process(        \
        s_bundle->module_sensor_params[(submodule)]->sub_module_private,           \
        (event), (data));                                                          \
    } else {                                                                       \
        SERR("func_tbl for submodule %d is NULL", submodule);                      \
        rc = SENSOR_FAILURE;                                                       \
    }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章