【Camera专题】高通Camera功耗优化

一、随便说说

  • 1.最近的好消息是Eric这个月要入职一加了,待遇挺好的,不过加班也挺猛,钱给够就能接受!
    等他先去试试水[奸笑],了解一下实际情况!
  • 2.功耗优化一直是一个令人头大的东西,毕竟单枪匹马,没人指导,真的很难。本来都不打算分享的,
    既然答应了Erci,那就写一篇干货吧。

功耗优化的高通文档:

  • kba-170221213554_7_高通通用功耗温升优化技术期刊
  • 80-P0955-1SC-功耗调试通用指南
    可以参考这两篇文档,获取思路。
    不知道有没有大神通过改Camera框架,进行这种级别的功耗优化!

功耗优化的2个层面:

  • 1.硬件
  • 2.软件

平台:高通8909

二、知识点

2.1 硬件层面的功耗优化

1.CPU(平台)
平台级别的优化,除了硬件上架构不同,软件上框架也是不一样的。
比如8909平台通信的时候,会有一个守护进程进行通信,
高端一点的平台就移除了这一点,功耗就降低了。

目前我们使用新平台,同样的sensor,功耗优化有30mA以上!

2.Camera 供电
DVDD供电这一块,选用高效率的供电,对功耗优化有很大裨益!

  • DCDC电源:效率高,功耗低
  • LDO电源:效率低,功耗高
    来看一组测试数据:

前 摄 小 尺 寸 相 差 13 m A , 全 尺 寸 相 差 31.4 m A \color{red}{前摄小尺寸相差13mA,全尺寸相差31.4mA} 13mA31.4mA
后 摄 小 尺 寸 相 差 42.3 m A , 全 尺 寸 相 差 66.6 m A \color{red}{后摄小尺寸相差42.3mA,全尺寸相差66.6mA} 42.3mA66.6mA

也就是说sensor的分辨率越大,优化得越多。

3.sensor选型
不同的sensor,功耗不一样。目前以我的经验来看,ov的sensor比三星的总体偏优!

相 同 的 条 件 下 测 试 , o v 的 摄 像 头 比 三 星 的 少 了 15 m A \color{red}{相同的条件下测试,ov的摄像头比三星的少了15mA} ov15mA
因此,摄像头的选型也很重要,如果你特别关心功耗这一块的话!

2.2 软件层面的功耗优化

1.采用最低的sensor output resolution

APP请求的尺寸是320x360,Sensor输出尽量选择最小的尺寸:640x480,而不是全尺寸800w的!

相 同 s e n s o r , 底 层 输 出 小 尺 寸 的 比 全 尺 寸 的 小 了 35 m A \color{red}{相同sensor,底层输出小尺寸的比全尺寸的小了35mA} sensor35mA
源码:
vendor/qcom/proprietary/mm-camera/mm-camera2/media-controller/modules/sensors/sensors/sensor.c

static int32_t sensor_pick_resolution(void *sctrl,
  sensor_set_res_cfg_t *res_cfg, enum msm_sensor_resolution_t *pick_res)
{
    
    
···
  width = res_cfg->width;//app请求的宽
  height = res_cfg->height;app请求的高

  SHIGH("app : Height %d Width %d", height, width);
···
}

这个函数就是用了匹配app请求的宽高和底层输出的!
代码主要逻辑就是:
app:宽/高=绝对值,假设这个值为A
遍历底层所有的尺寸:
底层:宽/高=绝对值,假设这个值为B1,B2,B3,B4
A和所有的B1,B2,B3,B4相比较,谁最小,谁就最匹配!
但是工作中,我发现这个代码逻辑好像有点问题,就是无法完美匹配最接近的尺寸!
那么可以强制选择你觉得合适的尺寸:

static int32_t sensor_pick_resolution(void *sctrl,
  sensor_set_res_cfg_t *res_cfg, enum msm_sensor_resolution_t *pick_res)
{
    
    
···
  width = res_cfg->width;//app请求的宽
  height = res_cfg->height;app请求的高

  SHIGH("app : Height %d Width %d", height, width);
···
++  if((height==320 && width==360)) {
    
    //app请求的尺寸
++    if (ctrl->lib_params->sensor_lib_ptr->sensor_slave_info->sensor_id_info.sensor_id == 0x5675) {
    
    
        //判断是那颗sensor
++        SHIGH("it is ov5675,make pick_res =1");
++        *pick_res =1;//选择尺寸1
++    }
++  }


}

这里*pick_res = 1代表的就是驱动代码里配置的res1,如下:640x480这一组参数!

static struct sensor_lib_out_info_t sensor_out_info[] = {
    
     
  //res0
  {
    
    
    .x_output = 2592,
    .y_output = 1944,
    .line_length_pclk = 750,
    .frame_length_lines = 2000,
    .vt_pixel_clk = 45000000,
    .op_pixel_clk = 180000000,//180000000,//168000000,//220800000,
    .binning_factor = 1,
    .max_fps = 30,//90.0,
    .min_fps = 10,//90.0,
    .mode = SENSOR_DEFAULT_MODE,
  },  
  //res1
   {
    
       
    .x_output = 640,
    .y_output = 480,
    .line_length_pclk = 1500,
    .frame_length_lines = 3000,
    .vt_pixel_clk = 45000000,
    .op_pixel_clk = 90000000,
    .binning_factor = 1,
    .max_fps = 10,//90.0,
    .min_fps = 7.5,//90.0,
    .mode = SENSOR_DEFAULT_MODE,
  },  
};
2.采用合适的帧率(fps)

帧率越低,对应的功耗也就越低!

相 同 条 件 下 , 10 f p s 和 30 f p s 相 差 了 56 m A \color{red}{相同条件下,10fps和30fps相差了56mA} 10fps30fps56mA
因此,选择合适的fps很重要!

源码:
以ov5675为例
vendor/qcom/proprietary/mm-camera/mm-camera2/media-controller/modules/sensors/sensor_libs/ov5675/
ov5675_lib.c

static struct msm_camera_i2c_reg_array res1_reg_array[] = {
    
    
···
    //0x7d0=2000(十进制)
    {
    
    0x380e, 0x07, 0x00},//frame_length_lines 
    {
    
    0x380f, 0xd0, 0x00},
···
}
static struct msm_sensor_output_reg_addr_t output_reg_addr = {
    
     
  .x_output = 0x3808,
  .y_output = 0x380a,
  .line_length_pclk = 0x380c,//相关寄存器
  .frame_length_lines = 0x380e,//相关寄存器
};

static struct sensor_lib_out_info_t sensor_out_info[] = {
    
    
  {
    
    
    .x_output = 2592,
    .y_output = 1944,
    .line_length_pclk = 750,
    .frame_length_lines = 2000,
    .vt_pixel_clk = 45000000,
    .op_pixel_clk = 180000000,//180000000,//168000000,//220800000,
    .binning_factor = 1,
    .max_fps = 30,//90.0,
    .min_fps = 10,//90.0,
    .mode = SENSOR_DEFAULT_MODE,
  },
···省略其他尺寸
}

帧率的计算公式
fps = vt_pixel_clk /(frame_length_lines * line_length_pclk )

这里带入公式:
fps=45000000 ÷(2000x750)=30fps
因此max_fps配置成30fps
min_fps 的修改和效果文件有关。

参数含义

一般来说,我们只需要改frame_length_lines 这个值就可了,其他值保持不变!

帧率的修改
假设我们想改成20fps,怎么修改呢!
1.改寄存器
2.改配置
frame_length_lines = 45000000 ÷ 750 ÷ 20fps = 3000
修改如下:

static struct msm_camera_i2c_reg_array res1_reg_array[] = {
    
    
···
    {
    
    0x380e, 0x0b, 0x00},//这里寄存器改成0XBB8=3000(十进制)
    {
    
    0x380f, 0xb8, 0x00},
···
}
static struct msm_sensor_output_reg_addr_t output_reg_addr = {
    
     
  .x_output = 0x3808,
  .y_output = 0x380a,
  .line_length_pclk = 0x380c,//相关寄存器
  .frame_length_lines = 0x380e,//相关寄存器
};

static struct sensor_lib_out_info_t sensor_out_info[] = {
    
    
  {
    
    
    .x_output = 2592,
    .y_output = 1944,
    .line_length_pclk = 750,
/* .frame_length_lines = 2000,*/
++  .frame_length_lines = 3000,
    .vt_pixel_clk = 45000000,
    .op_pixel_clk = 180000000,//180000000,//168000000,//220800000,
    .binning_factor = 1,
++  .max_fps = 20,//90.0,
    .min_fps = 10,//90.0,
    .mode = SENSOR_DEFAULT_MODE,
  },
···省略其他尺寸
}

小 技 巧 : s e n s o r 尺 寸 可 以 配 多 组 分 辨 率 相 同 , 但 是 帧 率 不 同 的 , 客 制 化 使 用 \color{red}{小技巧:sensor尺寸可以配多组分辨率相同,但是帧率不同的,客制化使用} sensor使

3.VFE时钟的修改

op_pixel_clk就是vfe时钟,实际上就是需要通过 MIPI 通道从摄像头获取的数据量!
概念如下:

VFE时钟越小,功耗越低!如图

图中的MIPI速率和我们这里说的VFE是对应起来的!

相 同 条 件 下 , M I P I 速 率 越 低 , 功 耗 优 化 了 将 近 25 m A \color{red}{相同条件下,MIPI速率越低,功耗优化了将近25mA} MIPI25mA

当然,这个MIPI速率不能随便改小,一定要改一个合适的值!
以上图的数据为例子:

sensor:s5k4h7
分辨率:1280x720
帧率:15
数据类型:bayer(一个像素10bit)
MIPI通道:4 lane

总数据量 = 1280x720x15x10 x 4 lane = 138,240,000 x4
op_pixel_clk = 138,240,000x4 /10=138.24 x4 MHZ(4 lane的数据)
这里最小要配置成138.24 x4 MHZ

不过一般来说我们要配置大一下,否正有可能会数据溢出!导致预览黑屏!
而且还要考虑到op_pixel_clk对天线的干扰!

考虑到天线干扰数据溢出问题,这里我们配置这224MHZ!

如何修改s5k4h7的VFE时钟: 224MHZ=448Mbps

计算公式:
MIPI_output_clk=ExtClk(MCLK=24MHz)/0x030D*0x030F/(2^0x3C17)

0x030D = 0x06(默认值 不要动)
0x030F = 0x70(可以修改这个值)十进制:112
0x3C17 = 0x00 (默认值 不要动)
带入公式得:

MIPI_output_clk=24/6*112/1=448Mbps
op_pixel_clk = 448 Mbps x 4 lane / 10bit = 179200000

改完之后把MIPI_output_clk化成16进制填入0x0820、0x0821寄存器
448Mbps = 0x01C0

源码:
vendor/qcom/proprietary/mm-camera/mm-camera2/media-controller/modules/sensors/sensor_libs/s5k4h7/
s5k4h7_lib.c

//1632x1224@30fps
#define RES2_REG_ARRAY \
{
      
       \
···
  {
    
    0x030D, 0x06, 0x00}, \
···
  {
    
    0x030F, 0x70, 0x00}, \
···
  {
    
    0x0820, 0x01, 0x00}, \
  {
    
    0x0821, 0xC0, 0x00}, \
···
}

static struct sensor_lib_out_info_t sensor_out_info[] = {
    
    
      /* Res 2 */
      {
    
        
        .x_output = 1632,
        .y_output = 1224,
        .line_length_pclk = 3688,
        .frame_length_lines = 5062,
        .vt_pixel_clk = 280000000,
        .op_pixel_clk = 179200000,
        .binning_factor = 1, 
        .min_fps = 7.50,
        .max_fps = 15.0,
        .mode = SENSOR_DEFAULT_MODE,
      },
}
4. 关闭过多的log


打开摄像头时,有很多数据流的log。可以关闭这样的log,达到节省功耗的目的!
但是在我看来,好像优化不大!

5.关闭ZSL模式

如果你开启了ZSL模式,预览的时候,会有ZSL通道,预览流会以全尺寸在跑!
造成导致功耗增大10mA左右!

6.APP端的优化

App端的优化,我也不太熟悉,大概说一下思路吧!
如果是你自己写的APP,你可以拿骁龙相机做对比功耗!
如果你的APP功耗比骁龙相机大了,就要找出原因,看是否可以优化!

  • 1.TextureView代替surfaceView
  • 2.网络请求
  • 3.动画、加载其他资源
  • 4.其他

到此,功耗优化的干货就这些了!

继续当一名咸鱼(* ̄︶ ̄)!

Stay hungry,Stay foolish!

猜你喜欢

转载自blog.csdn.net/justXiaoSha/article/details/101048786