锐单电子商城 , 一站式电子元器件采购平台!
  • 电话:400-990-0325

[sdm660 android9.0]补光灯代码分析

时间:2023-05-30 18:37:00 mtp系列传感器3vled适合多大电阻

高通相关dtsi解析

驱动程序 v2 用于在背景光昏暗时为相机传感器提供照明,以捕捉良好的图像。它也可用于手电筒/手电筒应用。 它是 Qualcomm Technologies Inc. 参考平台上 PMIC 的一部分。 主节点: 所需属性: - 兼容:应该是兼容qcom,qpnp-flash-led-v2” - reg : 闪光灯 LED 模块的基址和大小 - qcom,pmic-revid : PMIC revid 模块模型。用于识别 PMIC 子类型。 可选属性: - 中断:指定与闪光灯相关的中断。 - 中断名称:指定与中断相关的中断名称。 - qcom,hdrm-auto-mode : 选择是否使用布尔类型的净空自动模式 - qcom,isc-delay-us : 指定短路延迟的整数类型。有效值为 3264128192。单位为 uS。 - qcom,warmup-delay-us : 指定预热延迟的整数类型。有效值为 3264128192。单位为 uS。 - qcom,short-circuit-det :使用布尔属性进行短路故障检测。 - qcom,open-circuit-det :启用开路故障检测的布尔属性。 - qcom,vph-droop-det :启用 VPH 布尔属性下垂检测。 - qcom,vph-droop-hys-mv : 指定 VPH 下垂滞后的整数属性。 qcom,vph-droop-det 使用时间。有效值为 0255075。 单位为毫伏。 - qcom,vph-droop-thresh-mv : 指定 VPH 下降阈值的整数属性。 qcom,vph-droop-det 使用时间。有效值为 25003200,步长为 100。单位为 mV。 - qcom,vph-droop-debounce-us : 指定 VPH 下垂抖动时间的整数属性。 qcom,vph-droop-det 使用时间。有效值为 081626。单位为 uS。 - qcom,led1n2-iclamp-low-ma :用于缓解指定电流钳低电平的整数属性。 mA。允许 值与 qcom,max-current 下相同。 - qcom,led1n2-iclamp-mid
      
       -ma :整数属性,用于指定电流钳位中间电平以进行缓解。单位为 mA。允许 值与 qcom
       ,max
       -current 下相同。 
       - qcom
       ,led3
       -iclamp
       -low
       -ma :整数属性,用于指定电流钳低电平以进行缓解。单位为 mA。允许 值与 qcom
       ,max
       -current 下相同。 
       - qcom
       ,led3
       -iclamp
       -mid
       -ma :整数属性,用于指定电流钳位中间电平以进行缓解。单位为 mA。允许 值与 qcom
       ,max
       -current 下相同。 
       - qcom
       ,vled
       -max
       -uv :闪电流预测缓解的整数属性。默认值为 
       3500000 uV。 
       - qcom
       ,ibatt
       -ocp
       -threshold
       -ua :闪电流预测缓解的整数属性。默认值为 
       4500000 uA。 
       - qcom
       ,rparasitic
       -uohm:用于指示电池电阻寄生分量的闪光电流预测缓解的整数属性。默认值为 
       0 uOhm。 
       - qcom
       ,lmh
       -ocv
       -threshold
       -uv :闪存电流抢占式 LMH 缓解所需的属性。默认值为 
       3700000 uV。 
       - qcom
       ,lmh
       -rbatt
       -threshold
       -uohm :闪存电流抢占式 LMH 缓解所需的属性。默认值为 
       400000 uOhm。 
       - qcom
       ,lmh
       -mitigation
       -sel :配置闪存电流抢占式 LMH 缓解的可选属性。接受的值为:
       0:MITIGATION_DISABLED 
       1:MITIGATION_BY_ILED_THRESHOLD 
       2:MITIGATION_BY_SW 默认值为 
       2- qcom
       ,chgr
       -mitigation
       -sel :可选属性,用于配置闪光电流抢占式充电器缓解。 接受的值为:
       0:MITIGATION_DISABLED 
       1:MITIGATION_BY_ILED_THRESHOLD 
       2:MITIGATION_BY_SW 默认值为 
       2- qcom
       ,lmh
       -level :配置闪存电流抢占式 LMH 缓解的可选属性。接受的值为 
       013。默认值为 
       0- qcom
       ,iled
       -thrsh
       -ma:可选属性,用于配置触发硬件抢占式缓解的 LED 电流阈值。单位为 mA。默认值为 
       1000。可接受的值在 
       0 
       - 
       3100 范围内,步长为 
       1000 禁用自主硬件缓解。 
       - qcom
       ,thermal
       -derate
       -en :启用闪电流热缓解的布尔属性。 
       - qcom
       ,thermal
       -derate
       -current :用于散热的一系列电流限制。如果指定了 qcom
       ,thermal
       -derate
       -en,则为必需。单位为 mA。格式是qcom,热降额电流 
       = 
       <OTST1_LIMIT
       , OTST2_LIMIT
       , OTST3_LIMIT
       >- qcom
       ,otst
       -ramp
       -back
       -up
       -dis 
       : 在热降额触发后禁用电流斜坡备份的布尔属性 
       - qcom
       ,thermal
       -derate
       -slow :整数属性来指定缓慢降低热速率。单位在美国。允许 值为:
       1282565121024204840968192314592- qcom
       ,thermal
       -derate
       -fast :整数属性,用于指定快速降低热速率。单位在美国。允许 值为:
       326496128256384512. 
       - qcom
       ,thermal
       -debounce 
       : 指定热去抖动时间的整数属性。仅当 qcom
       ,thermal
       -derate
       -en 时使用被指定。 子节点内的必需属性。智利节点包含每个单独 LED 的设置。每个 LED 硬件都需要一个自己的节点和一个开关节点来控制亮度。为了打开
       /关闭LED和更好的调节器控制,引入了“led
       :
       switch”节点。 “led
       :
       switch”从其他节点获取几个现有属性以简化操作。为了向后兼容,切换节点可以是可选的: 
       - 标签:将使用的 LED 类型,“闪光灯”或“手电筒”。 
       - qcom
       ,led
       -name 
       : LED 的名称。可接受的值为“led
       :flash_0”、“led
       :flash_1”、“led
       :torch_0”、“led
       :torch_1” 
       - qcom
       ,
       default
       -led
       -trigger:触发相机闪光灯和手电筒。可接受的值为“flash0_trigger”、“flash1_trigger”、“torch0_trigger”、torch1_trigger” 
       - qcom
       ,id 
       : 每个物理 LED 的枚举 ID。可接受的值为“
       0”、“
       1”等。 
       - qcom
       ,max
       -current 
       : 此 LED 允许的最大电流。有效值应该是 
       01000 之间的整数,表示 
       01000 mA。 
       - qcom
       ,pmic
       -revid 
       : PMIC 修订 ID 源。 PMI8996 修订检查需要此属性。 子节点内的可选属性: 
       - qcom
       ,current 
       : LED 的默认电流强度。可接受的值应该是 
       0 t 
       1000 之间的整数,表示 
       01000 mA。 
       - qcom
       ,duration 
       : 闪光灯 LED 的持续时间。当持续时间到期时,硬件将关闭闪光灯 LED。值应为 
       10 ms 到 
       1280 ms,增量步长为 
       10 ms。不适用于手电筒。 LED
       :SWITCH 节点需要处理用作闪光灯的 LED。 
       - reg
       <n
       > 
       : 
       reg<n> 
       (
       <n
       > 代表数字。例如 
       0
       ,
       1
       ,
       2
       ,
       .
       .
       ) 属性是添加对多个电源的支持。它包括两个属性调节器名称和最大电压。调节器节点内的必需属性: 
       - max
       -voltage:这指定调节器的最大电压。某些开关或升压调节器不需要此属性。 
      

补光灯有两种工作模式:
Camera flash led分flash和torch两种模式。
Flash: 拍照时闪光灯瞬间亮一下的情况,电流比较大,目前是1000mA,最大电流不能超过led的最大承受能力。
Torch: 只用于录video或者拿led当手电筒的情况,电流不能太大,例如现在用的是200mA。
Flash的开启需要先从torch过渡,也就是电流慢慢增大,减小冲击。

1.库文件:
从sdm660_camera.xml中,pmic,
其代码位于:vendor/qcom/proprietary/mm-camera/mm-camera2/media-controller/modules/sensors/flash/libs/pmic/pmic_flash.h,最终编译生成 libflash_pmic.so 库
定义 使用闪光灯和手电筒时 跳过的帧数

static flash_lib_t flash_lib_ptr = { 
       
  .flash_name = "pmic",
  .flash_driver_type = FLASH_DRIVER_TYPE_DEFAULT,
  .main_flash_on_frame_skip = 3,
  .main_flash_off_frame_skip = 3,
  .torch_on_frame_skip = 2,
  .torch_off_frame_skip = 2,
};
头文件中主要是定义了在闪光灯打开时,摄像头需要跳过的帧数,及在手机筒打开时需要跳过的帧数。
还是一个比较重要的就是 flash_driver_type,
当 .flash_driver_type = FLASH_DRIVER_TYPE_DEFAULT, 时,闪光灯的相关配置是由kernel 来定义的。
当 .flash_driver_type = FLASH_DRIVER_PMIC, 和其他值时,闪光灯的相关配置需要由本lib 库来定义。

2.通用代码vendor/qcom/proprietary/mm-camera/mm-camera2/media-controller/modules/sensors/flash/module/flash.c
vendor/qcom/proprietary/mm-camera/mm-camera2/media-controller/modules/sensors/module/module_sensor_offload.c
flash open动作是在 module_sensor_offload_open()中调用打开 闪光灯节点的。
flash 初始化是由 module_sensor_offload_init_config() 中来调用的

void module_sensor_offload_init_config( void* param1,  void* param2,  void* param3 __attribute__((unused)),
                      void* param4 __attribute__((unused)))
{ 
       
  // 初始化闪光灯 ,调用 flash_init(),打开闪光灯 lib 库
  SLOW("flash subdev id = %d",
  status = module_sensor_flash_init(s_bundle);
  
  // 获取使用闪光灯时,跳过的帧数,如果没设置,默认过滤 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;
  }
}

2.1 初始化:flash_init()
vendor/qcom/proprietary/mm-camera/mm-camera2/media-controller/modules/sensors/module/module_sensor.c
module_sensor_flash_init()

vendor/qcom/proprietary/mm-camera/mm-camera2/media-controller/modules/sensors/module/module_sensor.c
boolean module_sensor_flash_init(module_sensor_bundle_info_t *s_bundle)
{ 
       
  /* Get flash name from camera config read from daemon init */
  a_name = s_bundle->sensor_common_info.camera_config.flash_name;

  SENSOR_SUB_MODULE_PROCESS_EVENT(s_bundle, SUB_MODULE_LED_FLASH, LED_FLASH_INIT, a_name, rc);
  return TRUE;
}

可以看出,在 module_sensor_flash_init() 中主要是调用 flash_init() 来做初始化的。—LED_FLASH_INIT
flash_init()

根据传递的name ,拼凑lib 库的字符串,此处为 libflash_pmic.so,同步将 pmic_flash.h中的结构体内容保存在 flash_ptr->driver_lib_data 中。
解析 pmic 参数信息,及 flash_driver_type 信息。
配置 I2C 地址信息
解析上下电信息,准备下发到 Kernel 中
下发 CFG_FLASH_INIT 命令到 Kernel 中,相关信息保存在 .flash_init_info 中

tatic int32_t flash_init(void *ptr, void *data)
{ 
       
  sensor_flash_data_t *flash_ctrl = (sensor_flash_data_t*)ptr;
  struct msm_flash_init_info_t flash_init_info;
  struct msm_flash_cfg_data_t flash_cfg;
  struct msm_camera_i2c_reg_setting_array *flash_init_settings = NULL;
  struct msm_sensor_power_setting_array *power_setting_array = NULL;

  SDBG("Enter");

  /* memset flash init info */
  memset(&flash_init_info, 0, sizeof(flash_init_info));

  // 1. 根据传递的name ,拼凑lib 库的字符串,此处为 libflash_pmic.so,同步将 pmic_flash.h中的结构体内容保存在 flash_ptr->driver_lib_data 中
  /* Load flash library */
  rc = flash_load_lib(ptr, name);
  // 2. 解析 pmic 参数信息。
  flash_update_settings_size(flash_ctrl->driver_lib_data);
  // 3. 解析 flash_driver_type 信息
  switch (flash_ctrl->driver_lib_data->flash_driver_type) { 
       
    case FLASH_DRIVER_TYPE_PMIC:
        flash_init_info.flash_driver_type = FLASH_DRIVER_PMIC;
        break;
    case FLASH_DRIVER_TYPE_I2C:
        flash_init_info.flash_driver_type = FLASH_DRIVER_I2C;
        break;
    case FLASH_DRIVER_TYPE_GPIO:
        flash_init_info.flash_driver_type = FLASH_DRIVER_GPIO;
        break;
    case FLASH_DRIVER_TYPE_DEFAULT:
        flash_init_info.flash_driver_type = FLASH_DRIVER_DEFAULT;
        break;
  }
  // 4. 配置I2C 地址
  flash_init_info.slave_addr = flash_ctrl->driver_lib_data->i2c_flash_info.slave_addr;
  flash_init_info.i2c_freq_mode = sensor_sdk_util_get_i2c_freq_mode(
                flash_ctrl->driver_lib_data->i2c_flash_info.i2c_freq_mode);
                
  // 5. 解析上下电信息,准备下发到 Kernel 中
  /* Translate power settings from uspace structure to kernel struct */
  power_setting_array = (struct msm_sensor_power_setting_array *)malloc(sizeof(*power_setting_array));
  translate_camera_power_setting(power_setting_array,&(flash_ctrl->driver_lib_data->power_setting_array));

  /* Translate reg array settings from uspace structure to kernel struct */
  flash_init_settings = (struct msm_camera_i2c_reg_setting_array *)malloc(sizeof(*flash_init_settings));

  translate_sensor_reg_setting_array(flash_init_settings,
                &(flash_ctrl->driver_lib_data->i2c_flash_info.flash_init_settings));

  flash_init_info.power_setting_array = power_setting_array;
  flash_init_info.settings = flash_init_settings;


  for (i = 0; i < MAX_LED_TRIGGERS; i++) { 
       
    flash_cfg.flash_current[i] = flash_ctrl->driver_lib_data->max_flash_current[i];
    flash_cfg.flash_duration[i] = flash_ctrl->driver_lib_data->max_flash_duration[i];
    SLOW("i = %d flash_current = %d flash_duration = %d", i, flash_cfg.flash_current[i], flash_cfg.flash_duration[i]);
  }


  // 6. 下发 CFG_FLASH_INIT 命令到 Kernel 中,相关信息保存在 .flash_init_info 中
  flash_cfg.cfg_type = CFG_FLASH_INIT;
  flash_cfg.cfg.flash_init_info = &flash_init_info;


  rc = ioctl(flash_ctrl->fd, VIDIOC_MSM_FLASH_CFG, &flash_cfg);


  for (i = 0; i < MAX_LED_TRIGGERS; i++) { 
       
    flash_ctrl->flash_max_current[i] = flash_cfg.flash_current[i];
    flash_ctrl->flash_max_duration[i] = flash_cfg.flash_duration[i];
    SLOW("i = %d flash_max_current = %d flash_max_duration = %d",
                  i, flash_ctrl->flash_max_current[i], flash_ctrl->flash_max_duration[i]);
  }


  SDBG("Exit");
  free(power_setting_array);
  free(flash_init_settings);
  return SENSOR_SUCCESS;
}

2.2核心函数:flash_process()
操作闪光灯,都是操作 flash_process() 函数,最终都是通过 ioctl 来下发指令和参数的

# mm-camera/mm-camera2/media-controller/modules/sensors/flash/module/flash.c
static int32_t flash_process(void *ctrl, sensor_submodule_event_type_t event, void *data)
{ 
       
  flash_ctrl = (sensor_flash_data_t *)ctrl;
  rer = flash_ctrl->rer;
  dual_led_setting = &flash_ctrl->dual_led_setting;


  /* Initilize to invalid value * Kernel uses default values if not updated */
  cfg.flash_current[0] = default_current;
  cfg.flash_current[1] = default_current;


  /* Translate reg array settings from uspace structure to kernel struct */
  flash_settings = (struct msm_camera_i2c_reg_setting_array *)malloc( sizeof(*flash_settings));
  SLOW("event %d", event);

switch (event) { 
       
  case LED_FLASH_GET_MAX_CURRENT: { 
                       // 1. 获得闪光灯的最大电流
    int32_t ** flash_current = (int32_t **)data;
    *flash_current = &(flash_ctrl->flash_max_current[0]);
    goto flash_process_Exit;
  }
  case LED_FLASH_GET_MAX_DURATION: { 
                   // 2. 获得双闪的最大电流
    uint32_t* flash_duration = (uint32_t*)data;
    *flash_duration = flash_ctrl->flash_max_duration[0];
    goto flash_process_Exit;
  }
  case LED_FLASH_SET_CURRENT: { 
                           // 3. 设置闪光灯的最大电流
    /* Get currents for dual LED */
    rc = flash_set_current(data, dual_led_setting);
    goto flash_process_Exit;
  }
  case LED_FLASH_INIT:                            // 4. 闪光灯初始化
    rc = flash_init(flash_ctrl, data);
    goto flash_process_Exit;
  case LED_FLASH_SET_RER_CHROMATIX: { 
                   // 5. 设置 红眼 chromatix 参数
    rer_chromatix = (red_eye_reduction_type *)data;
    /* Get (RER) data from chromatix */
    rc = flash_rer_set_chromatix(rer, rer_chromatix);
    goto flash_process_Exit;
  }
  case LED_FLASH_GET_RER_PARAMS: { 
                       // 6. 获取 红眼 参数
    *(int32_t *) data = rer->cfg->red_eye_reduction_led_flash_enable;
    goto flash_process_Exit;
  }
  case LED_FLASH_SET_RER_PARAMS: { 
                       // 7. 设置 红眼 参数
    mode = (int32_t *)data;
    rc = flash_rer_set_parm(rer, *mode);
    goto flash_process_Exit;
  }
  case LED_FLASH_SET_FIRING_POWER:{ 
                       // 8. 设置电流
    flashPower = *(uint8_t *)data;
    goto flash_process_Exit;
  }
  case LED_FLASH_SET_RER_PROCESS: { 
                       // 9. 配置红眼处理函数
    led_module_params = (module_sensor_params_t *)data;
    rc = flash_rer_sequence_process(rer, led_module_params);
    goto flash_process_Exit;
  }
  case LED_FLASH_SET_OFF:                        // 10. 关闭闪光灯
    SHIGH("Turning off flash");
    translate_sensor_reg_setting_array(flash_settings,
      &(flash_ctrl->driver_lib_data->i2c_flash_info.flash_off_settings));
    cfg.cfg_type = CFG_FLASH_OFF;
    cfg.cfg.settings = flash_settings;
    break;
  case LED_FLASH_SET_TORCH:
  case LED_FLASH_SET_PRE_FLASH: { 
                       // 11. 开启 手电筒 或 开启预闪,下发参数 CFG_FLASH_LOW
    SHIGH("Turning on torch/pre flash");
    /* Pre flash mode */
    translate_sensor_reg_setting_array(flash_settings,
              &(flash_ctrl->driver_lib_data->i2c_flash_info.flash_low_settings));
    cfg.cfg_type = CFG_FLASH_LOW;
    cfg.cfg.settings = flash_settings;


    if (dual_led_setting->low_setting[0] == 0 && dual_led_setting->low_setting[1] == 0) { 
       
      cfg.flash_current[0] = data ? *(int32_t *)data : default_current;
      cfg.flash_current[1] = data ? *(int32_t *)data : default_current;
    } else { 
       
      cfg.flash_current[0] = dual_led_setting->low_setting[0];
      cfg.flash_current[1] = dual_led_setting->low_setting[1];
    }
    break;
  }
  case LED_FLASH_SET_RER_PULSE_FLASH: { 
                   // 12. 设置红眼 脉冲 电平
    /* RER flash pulses */
    translate_sensor_reg_setting_array(flash_settings,
      &(flash_ctrl->driver_lib_data->i2c_flash_info.flash_high_settings));
    cfg.cfg_type = CFG_FLASH_HIGH;


    /* Use chromatix current if exist (set in RER_PROCESS)*/
    cfg.flash_current[0] = data ? *(int32_t *)data : default_current;
    cfg.flash_current[1] = data ? *(int32_t *)data : default_current;
    cfg.cfg.settings = flash_settings;


    temp = (dual_led_setting->high_setting[0] + dual_led_setting->high_setting[1]);
    if (temp > 0) { 
       
      /* Update with Dual LED current */
      cfg.flash_current[0] = (cfg.flash_current[0] * dual_led_setting->high_setting[0]) / temp;
      cfg.flash_current[1] = (cfg.
锐单商城拥有海量元器件数据手册IC替代型号,打造电子元器件IC百科大全!

相关文章