msm 8953 camera 流程

 camera的流程研究
 
  rn6864m_csi0   probe succeeded  ---- probe 是否成功
  rn6864m        probe succeeded  ---- 
  
  // msm_sensor_i2c_option: sensor_name=rn6864m_csi0,   camera_id=0
  // msm_sensor_i2c_option: sensor_name=rn6864m,        camera_id=1
 
./sys/devices/virtual/cam_i2c_dev/rn6864m
./sys/devices/virtual/cam_i2c_dev/rn6864m_csi0
./sys/class/cam_i2c_dev/rn6864m
./sys/class/cam_i2c_dev/rn6864m_csi0

msm8953-camera-sensor-mtp.dtsi --- 配置信息
msm_sensor_driver.c -------- 
msm_sensor_ctrl_t *s_ctrl
.compatible = "qcom,camera" --- 匹配

msm_sensor_platform_remove
msm_sensor_driver_create_i2c_v4l_subdev  --- i2c设备 
msm_sensor_driver_create_v4l_subdev      ---- v4l2设备

msm_sensor_fill_slave_info_init_params  --- 初始化参数
 
 msm_sensor_get_power_down_settings  --- 关闭camera的参数集
 
 msm_sensor_get_power_up_settings  ---- 上电camera的参数集
 .ioctl = msm_sensor_init_subdev_ioctl,
 .core = &msm_sensor_init_subdev_core_ops,
 
 public.libraries.android.txt  --- 让函数暴露出来
 vendor-->qcom-->proprietary-->common-->config--> device-vendor.mk  MM_CAMERA += libmmcamera_rn6864m
 
 modules-->sensors--> msm8953_camera.xml
 CameraId   整个系统的camera编号
 SensorName  sensor也就是camera的名称,与驱动要匹配
 CSIDCore  --- 连接到哪一路物理上的CSI       qcom,csiphy-sd-index = <0>;  与这个同步 (qcom,csid-sd-index = <1>;)
 
 <CSIDCore>0</CSIDCore>
 
qcom,csiphy-sd-index = <2>;  <CameraId>2</CameraId>  --- 软件上的CSI0 还是 1  
qcom,csid-sd-index = <1>; <CSIDCore>1</CSIDCore>     --- 物理上的CSI0 还是一
.h 中的配置 #define SENSOR_MODEL "rn6864m"  驱动模型的 名称 name 

HAL 层的调用 sensor 的调用流程  ---> --->

[   20.209720] rn6864m_csi0 probe succeeded
[   20.212426] msm_sensor_i2c_option: sensor_name=rn6864m_csi0,camera_id=0
[   20.232313] ------------[ cut here ]------------
[   20.235925] WARNING: CPU: 4 PID: 704 at /mnt/data/ailiving/Workfolder/carl/aili/d/d-5/sc60/kernel/msm-3.18/drivers/gpio/gpiolib.c:68 gpio_to_desc+0x2c/0x50()
[   20.262078] Call trace:
[   20.263624] ---[ end trace 6938045f0ff21e83 ]---
[   20.268484] ------------[ cut here ]------------
[   20.272704] WARNING: CPU: 5 PID: 704 at /mnt/data/ailiving/Workfolder/carl/aili/d/d-5/sc60/kernel/msm-3.18/drivers/gpio/gpiolib.c:68 gpio_to_desc+0x2c/0x50()
[   20.286944] Call trace:
[   20.289426] ---[ end trace 6938045f0ff21e84 ]---
[   20.409467] rn6864m probe succeeded

msm8953_64:/dev # ls vi* -l -l
crw-rw---- 1 system camera 81,   2 2000-01-12 08:12 video0
crw-rw---- 1 system camera 81,  17 2000-01-12 08:12 video1
crw-rw---- 1 system camera 81,  19 2000-01-12 08:12 video2
crw-rw---- 1 system camera 81,   0 2000-01-12 08:12 video32
crw-rw---- 1 system camera 81,   1 2000-01-12 08:12 video33
msm8953_64:/dev #


HAL发送命令,根据xml文件中的camera的名字,加载不同的camera驱动
vendor 


在SensorDevice构造方法里调用HAL架构的hw_get_module来获得Sensor设备模块,
之后调用sensors_open这个工具函数,打开Sensor设备模块(调用其methods->open函数指针),返回Sensor设备的操作接口(这些接口在HAL层实现),保存在mSensorDevice中,调用Sensor模块的get_sensors_list方法获得传感器列表,然后依次激活这些设备并且添加到mActivationCount设备信息向量中。
Sensor HAL模块代码及打开模块工具函数sensors_open:
@hardware/libhardware/include/hardware/sensors.h
./qcom/proprietary/mm-camera/mm-camera2/media-controller/modules/sensors/module/sensor_init.c


主要是从vendor下sensor_init.c中probe到kernel层上电probe检测的流程。
module_sensor_init()                                            //module_sensor.c    |
 //创建mct, camera引擎
        ---> s_module = mct_module_create(name) 
 //初始化sensor module control structure               
        ---> module_sensor_ctrl_t        *module_ctrl
//probe sensor
        ---> sensor_init_probe(module_ctrl)      
//其他的subdev,比如actuator, eeprom, flash, cis, ois
        --->module_sensor_find_other_subdev(module_ctrl);
//然后是执行mct_list_traverse,分别初始化

然后看一下sensor_init_probe:


static boolean sensor_probe(module_sensor_ctrl_t *module_ctrl, int32_t fd,
  const char *sensor_name, char *path, struct xmlCameraConfigInfo *xmlConfig)
{
  boolean                              ret = TRUE;
  int32_t                              rc = 0, i;
  sensor_lib_params_t                  *sensor_lib_params;
  struct sensor_init_cfg_data          cfg;
  struct msm_camera_sensor_slave_info *slave_info = NULL;
  struct msm_sensor_power_setting *power_up_setting = NULL;
  struct msm_sensor_power_setting *power_down_setting = NULL;
  struct camera_power_setting_array *power_setting_array;

  /* Validate input parameters */
  if ((fd < 0) || !sensor_name || (xmlConfig == NULL)) {
    SERR("failed: invalid params fd %d sensor_name %s xmlConfig %p ",
      fd, sensor_name, xmlConfig);
    return FALSE;
  }
  
  
  
  
  
  static boolean sensor_init_xml_probe(module_sensor_ctrl_t *module_ctrl,
  int32_t sd_fd)
{
  int32_t         rc = 0;
  boolean         ret = FALSE;
  uint32_t        i = 0;
  char            config_xml_name[BUFF_SIZE_255];
  xmlDocPtr       docPtr = NULL;
  xmlNodePtr      rootPtr = NULL;
  xmlNodePtr      nodePtr = NULL;
  uint32_t        num_cam_config = 0;
  uint8_t         slot_probed[MAX_SENSOR_SLOT_NUMBER] = {0};
  camera_module_config_t camera_cfg;
  struct xmlCameraConfigInfo xmlConfig;
  char prop[PROPERTY_VALUE_MAX];
  uint32_t csidtg_enable = 0;

  property_get("persist.camera.csidtg.enable", prop, "0");
  csidtg_enable = atoi(prop);

  /* Create the xml path from data partition */
  snprintf(config_xml_name, BUFF_SIZE_255, "%s%s",
    CONFIG_XML_PATH, CONFIG_XML);

  if (access(config_xml_name, R_OK)) {
    SHIGH(" read fail (non-fatal) %s. Trying from system partition",
      config_xml_name);

    if (csidtg_enable) {
      /* Create the CSIDTG xml path from system partition */
      snprintf(config_xml_name, BUFF_SIZE_255, "%s%s",
        CONFIG_XML_SYSTEM_PATH, CSIDTG_CONFIG_XML);
    } else {
      /* Create the xml path from system partition */
      snprintf(config_xml_name, BUFF_SIZE_255, "%s%s",
        CONFIG_XML_SYSTEM_PATH, CONFIG_XML);
    }

    if (access(config_xml_name, R_OK)) {
      SERR("Cannot read file from %s. read failed", config_xml_name);
      return FALSE;
    }
  }

  SHIGH("reading from file %s", config_xml_name);

  /* Get the Root pointer and Document pointer of XMl file */
  ret = sensor_xml_util_load_file(config_xml_name, &docPtr, &rootPtr,
    "CameraConfigurationRoot");
  if (ret == FALSE) {
    SERR(" sensor_xml_util_load_file failed");
    return FALSE;
  }

  /* Get number of camera module configurations */
  num_cam_config = sensor_xml_util_get_num_nodes(rootPtr, "CameraModuleConfig");
  SLOW("num_cam_config = %d", num_cam_config);
  if (!num_cam_config || num_cam_config > MAX_CAMERA_CONFIG) {
    SERR(" invalid num_cam_config = %d", num_cam_config);
    ret = FALSE;
    goto XML_PROBE_EXIT;
  }


这个函数用来解析vendor下msm8953_camera.xml, 然后进行sensor probe:
步骤:
    1.获得xml路径
    2.检查根节点CameraModuleConfig个数,判断有几个camera
    3.for循环判断是否已经probe,没有就进行sensor_probe()
 
-----------
其中第一步中:
    先检查路径 CONFIG_XML_PATH + CONFIG_XML = “/data/misc/camera/camera_config.xml”
    然后判断系统属性persist.camera.csidtg.enable是否设置,为1就检查
    CONFIG_XML_SYSTEM_PATH + CONFIG_XML = "/system/etc/camera/camera_config.xml"
 
这个是out下最终生成的xml


boolean sensor_init_probe(module_sensor_ctrl_t *module_ctrl)
{
  int32_t                     rc = 0, dev_fd = 0, sd_fd = 0;
  uint32_t                    i = 0;
  struct media_device_info    mdev_info;
  int32_t                     num_media_devices = 0;
  char                        dev_name[32];
  char                        subdev_name[32];
  struct sensor_init_cfg_data cfg;
  boolean                     ret = TRUE;

  while (1) {
    uint32_t num_entities = 1;
    snprintf(dev_name, sizeof(dev_name), "/dev/media%d", num_media_devices);
    dev_fd = open(dev_name, O_RDWR | O_NONBLOCK);
    if (dev_fd < 0) {
      SLOW("Done enumerating media devices");
      break;
    }


    
    mct_module_t *module_sensor_init(const char *name)
{
  boolean                      ret = TRUE;
  int32_t                      rc = 0;
  mct_module_t                *s_module = NULL;
  module_sensor_ctrl_t        *module_ctrl = NULL;
  eebin_ctl_t bin_ctl;

  SHIGH("Sensor driver Version: %s", SENSOR_DRIVER_VERSION);
  SHIGH("Sensor SDK capabilities: %s", SENSOR_SDK_CAPABILITIES);

  SHIGH("Actuator driver Version: %s", ACTUATOR_DRIVER_VERSION);
  SHIGH("Actuator SDK capabilities: %s", ACTUATOR_SDK_CAPABILITIES);

  SHIGH("EEPROM driver Version: %s", EEPROM_DRIVER_VERSION);
  SHIGH("EEPROM SDK capabilities: %s", EEPROM_SDK_CAPABILITIES);

  SHIGH("Flash driver Version: %s", FLASH_DRIVER_VERSION);
  SHIGH("Flash SDK capabilities: %s", FLASH_SDK_CAPABILITIES);

  SHIGH("OIS driver Version: %s", OIS_DRIVER_VERSION);
  SHIGH("OIS SDK capabilities: %s", OIS_SDK_CAPABILITIES);

  SHIGH("PDAF driver Version: %s", PDAF_DRIVER_VERSION);
  SHIGH("PDAF SDK capabilities: %s", PDAF_SDK_CAPABILITIES);


  /* Create MCT module for sensor */
  s_module = mct_module_create(name);
  if (!s_module) {
    SERR("failed");
    return NULL;
  }

  /* Fill function table in MCT module */
  s_module->set_mod = module_sensor_set_mod;
  s_module->query_mod = module_sensor_query_mod;
  s_module->start_session = module_sensor_start_session;
  s_module->stop_session = module_sensor_stop_session;
  s_module->set_session_data = module_sensor_set_session_data;
  s_module->get_session_data = module_sensor_get_session_data;
  /* Create sensor module control structure that consists of bundle
     information */
  module_ctrl = malloc(sizeof(module_sensor_ctrl_t));
  if (!module_ctrl) {
    SERR("failed");
    goto ERROR1;
  }
  memset(module_ctrl, 0, sizeof(module_sensor_ctrl_t));

  s_module->module_private = (void *)module_ctrl;

  /* sensor module doesn't have sink port */
  s_module->numsinkports = 0;

  rc = eebin_interface_init(&module_ctrl->eebin_hdl);
  if (rc < 0) {
    SERR("failed");
  }

  bin_ctl.cmd = EEPROM_BIN_GET_BIN_DATA;
  rc = eebin_interface_control(module_ctrl->eebin_hdl, &bin_ctl);
  if (rc < 0) {
    SERR("failed");
  }

  /* module_sensor_probe_sensors */
  ret = sensor_init_probe(module_ctrl);
  if (ret == FALSE) {
    SERR("failed");
    goto ERROR1;
  }
  
  
1.枚举/dev/media*, 然后用ioctl打开,获得mdev_info, 比较是不是msm_config,不是就结束
2.sd_fd = open(subdev_name, O_RDWR);                          //获得文件描述符

1.调用sensor_load_libbrary()            //加载libmmcamera_ov7251.so这类库文件
                                   //这个函数调用的dlsy打开库,返回符号地址,通过地址调用方法
 
2.从返回的地址获得上电时序power_setting_array
 
3.然后是malloc申请空间这些,主要目的是把xml里的信息,复制到变量slave_info中
                        //struct msm_camera_sensor_slave_info slave_info
 
4.把slave_info传到kernel层,通过ioctl(fd, VIDIOC_MSM_SENSOR_INIT_CFG, &cfg)的方式
                        //这里slave_info是cfg的成员
                        //对应kernel:
                        //传入的命令码是VIDIOC_MSM_SENSOR_INIT_CFG
                        //cfg.cfgtype = CFG_SINIT_PROBE;
 
5.执行完ioctl, 通过返回的cfg.probed_info.session_id在这一层判断是否probe成功


对应的是:
        driver/media/platform/msm/camera_v2/sensor/msm_sensor_init.c +117
                case VIDIOC_MSM_SENSOR_INIT_CFG:
 
//上面cfg传到这里成了arg
//
static int32_t msm_sensor_driver_cmd(struct msm_sensor_init_t *s_init,void *arg)
 
这个函数中判断了上面的cfg->cfgtype, 然后就执行了kernel底层的硬件probe
 
 72     switch (cfg->cfgtype) {
 73     case CFG_SINIT_PROBE:
 74         mutex_lock(&s_init->imutex);
 75         s_init->module_init_status = 0;
 76         rc = msm_sensor_driver_probe(cfg->cfg.setting,
 77                                             &cfg->probed_info,
 78                                                     cfg->entity_name);
 
 
最后执行到msm_sensor_driver_probe()
这个函数里面static int __init msm_sensor_driver_init(void)
{
    int32_t rc = 0;

    CDBG("%s Enter\n", __func__);
    rc = platform_driver_register(&msm_sensor_platform_driver);
    if (rc)
        pr_err("%s platform_driver_register failed rc = %d",
            __func__, rc);
    rc = i2c_add_driver(&msm_sensor_driver_i2c);
    if (rc)
        pr_err("%s i2c_add_driver failed rc = %d",  __func__, rc);

    return rc;
}
做的一些事情,主要是把user层的camera信息复制到kerner层的结构体中
 
比如把上下电时序复制到msm_sensor_ctrl_t->sensordata->power_info中,
然后执行真正的上电检测
           rc = s_ctrl->func_tbl->sensor_power_up(s_ctrl);
 
然后Create /dev/videoX node;
 
然后下电    s_ctrl->func_tbl->sensor_power_down(s_ctrl);

static int __init msm_sensor_driver_init(void)
{
    int32_t rc = 0;

    CDBG("%s Enter\n", __func__);
    rc = platform_driver_register(&msm_sensor_platform_driver);
    if (rc)
        pr_err("%s platform_driver_register failed rc = %d",
            __func__, rc);
    rc = i2c_add_driver(&msm_sensor_driver_i2c);
    if (rc)
        pr_err("%s i2c_add_driver failed rc = %d",  __func__, rc);

    return rc;
}


static int32_t msm_sensor_driver_platform_probe(struct platform_device *pdev)
{
    int32_t rc = 0;
    struct msm_sensor_ctrl_t *s_ctrl = NULL;

    /* Create sensor control structure */
    s_ctrl = kzalloc(sizeof(*s_ctrl), GFP_KERNEL);
    if (!s_ctrl)
        return -ENOMEM;

    platform_set_drvdata(pdev, s_ctrl);

    /* Initialize sensor device type */
    s_ctrl->sensor_device_type = MSM_CAMERA_PLATFORM_DEVICE;
    s_ctrl->of_node = pdev->dev.of_node;

    /*fill in platform device*/
    s_ctrl->pdev = pdev;

    rc = msm_sensor_driver_parse(s_ctrl);
    if (rc < 0) {
        pr_err("failed: msm_sensor_driver_parse rc %d", rc);
        goto FREE_S_CTRL;
    }

    /* Get clocks information */
    rc = msm_camera_get_clk_info(s_ctrl->pdev,
        &s_ctrl->sensordata->power_info.clk_info,
        &s_ctrl->sensordata->power_info.clk_ptr,
        &s_ctrl->sensordata->power_info.clk_info_size);
    if (rc < 0) {
        pr_err("failed: msm_camera_get_clk_info rc %d", rc);
        goto FREE_S_CTRL;
    }

    /* Fill platform device id*/
    pdev->id = s_ctrl->id;

    /* Fill device in power info */
    s_ctrl->sensordata->power_info.dev = &pdev->dev;
    return rc;
FREE_S_CTRL:
    kfree(s_ctrl);
    return rc;


int32_t msm_sensor_driver_probe(void *setting,
    struct msm_sensor_info_t *probed_info, char *entity_name)
{
    int32_t                              rc = 0;
    struct msm_sensor_ctrl_t            *s_ctrl = NULL;
    struct msm_camera_cci_client        *cci_client = NULL;
    struct msm_camera_sensor_slave_info *slave_info = NULL;
    struct msm_camera_slave_info        *camera_info = NULL;

    unsigned long                        mount_pos = 0;
    uint32_t                             is_yuv;

    /* Validate input parameters */
    if (!setting) {
        pr_err("failed: slave_info %pK", setting);
        return -EINVAL;
    }

猜你喜欢

转载自blog.csdn.net/u010689853/article/details/108315672