欢迎光临散文网 会员登陆 & 注册

高通Camera驱动--调试技术大全(看完悟了)

2022-05-08 13:58 作者:补给站Linux内核  | 我要投稿

本文主要介绍QCOM camera调试的重要参数;

(1)Lane_assign 和lane_mask

  • 现在摄像头基本都是mipi接口类型,因为前后摄都对应到平台这边不同的mipi接口,相应的数据lane需要一一对应;

  • lane assign:


  • lane_mask:


比如:

101       <LaneMask>0x1F</LaneMask>                                                                               102       <LaneAssign>0x4320</LaneAssign>

  • 0x1F:只有0~4表示有效,对应bit位置为1表示该位的lane或者clock有效,0x1F即表示该mipi接口上的4条data线和clk线都有效;

  • 0x4320:表示sensor这边几条data线对应到平台这边mipi接口的第几路接口端口映射;bit0~3表示lane0对应平台这边mipi的第0接口,bit12~15表示lane 3对应平台这边mipi的第4接口,那第1个接口就是为时钟clk对接的;

(2)combo_mode

  • 如该平台这边只有一个mipi phy设备,有时候就需要前后摄共用这个phy,此时combo_mode就要设为1,或者在双摄的情况下:主副摄会与前摄共用,这个值也会设为1,下面是两个camera分配情况:


  • 比如只有一个PHY interface 的msm8909平台就可以这样配置:

//前摄配置
151 static struct csi_lane_params_t csi_lane_params = {
152   .csi_lane_assign = 0x004,
153   .csi_lane_mask = 0x18,
154   .csi_if = 1, // not used
155   .csid_core = {0},
156   .csi_phy_sel = 0,
157 };
432   .csiphy_params = {
433     .lane_cnt = 1,
434     .settle_cnt = 0x1b,//0x1b,                                                                                                                                     
436     .combo_mode = 1,
438   },
//后摄配置
198 static struct csi_lane_params_t csi_lane_params = {
199   .csi_lane_assign = 0x4320,
200   .csi_lane_mask = 0x7,
201   .csi_if = 1, // not used
202   .csid_core = {0},
203   .csi_phy_sel = 0,
204 };
334   .csiphy_params = {
335     .lane_cnt = 2,                                                                                                                                  
336     .settle_cnt = 0x18,
338     .combo_mode = 1,
340   },

(3)pixel_clk

  • 像素时钟(pixel clk): 是经过主时钟MCLK(EXTCLK) 经过PLL得到的,决定了该sensor突出数据的速度;相关PLL设定需要查看sensor 寄存器的data sheet,以s5k2ya为例:


  • 如下为一个sensor的clk相关的配置:

static struct sensor_lib_out_info_t sensor_out_info[] = {
{
/* full size @ 24 fps*/
.x_output = 4208, 
.y_output = 3120,
.line_length_pclk = 4572,
.frame_length_lines = 3142,
.vt_pixel_clk = 360000000,
.op_pixel_clk = 360000000,
.binning_factor = 1,
.max_fps = 24.01,
.min_fps = 7.5,
.mode = SENSOR_DEFAULT_MODE,
},

vt_pixel_clk(video timing clk value) – Virtual clock value used for calculating shutter time,and used by 

AEC for correcting banding artifacts 

vt_pixel_clk = line_length_pclk * frame_length_lines * frame rate

  • 平台根据写入不同的曝光行来控制帧率,比如在暗处希望牺牲一点帧率,让Gain值更高,就用这个公式来计算,最后计算的 frame_length_lines 写入相应寄存器;

  • 注意一点的是不同的平台需要一个最小的blanking time,所以frame_length_lines是要大于真是有效数据行y_output,而且差值一般16对齐;


op_pixel_clk – Represents how much data comes out of the camera over MIPI lanes to set the VFE clock op_pixel_clk = (total data rate from sensor)/bits-per-pixel if the MIPI DDR clock value (speed of the clock lane of the MIPI camera sensor) is 300 MHz, and the sensor transmits on 4 lanes, each lane has a 600 MHz data rate.Thus, the total data rate is 2400 MHz. For 10 bits per pixel Bayer data, this translates to the op_pixel_clk value of 2400/10 = 240 MHz. These values must be filled in accordance with the sensor specifications.

  • 这个时钟决定了sensor mipi data lane 吐出数据的带宽;不同的平台的处理能力不一样,所以这个值不能超过平台规范定义的值;


【文章福利】小编推荐自己的Linux内核技术交流群:【891587639】整理了一些个人觉得比较好的学习书籍、视频资料共享在群文件里面,有需要的可以自行添加哦!!!前100名进群领取,额外赠送一份价值699的内核资料包(含视频教程、电子书、实战项目及代码)    

(4)settle_cnt

  • settle_cnt(即稳定计数)–表示mipi开始切换到高速模式的一个稳定时间,必须根据传感器输出特性配置该值,以确保传感器的 PHY 发送器与 MSM 的 PHY 接收器无障碍同步;

  • settle_cnt – For CSI_Tx (the sensor) and CRI_Rx (the device) to work properly, a period for syncing between them is required. This time is set here as number of timer clock ticks. It has to be between the MIN and MAX values calculated by the formulas:

  1. MIN [Settle count * T(Timer clock)] > T(HS_SETTLE)_MIN

  2. MAX [Settle count * T(Timer clock)] < T(HS-PREPARE)+T(HS_ZERO) - 4*T(Timer clock)

  • settle_cnt(即稳定计数)– 必须根据sensor传感器输出特性配置该值,以确保传感器的 PHY 发送器与 MSM 的 PHY 接收器无障碍同步;对于 28 nm 以及更小的 MSM 芯片,使用以下公式计算稳定计数:

  1. settle_cnt = T(HS_SETTLE)_avg /T(TIMER_CLK),

  2. 其中 T(HS_SETTLE)_avg = (T(HS_SETTLE)_min + T(HS_SETTLE)_max) / 2,如传感器数据表所指示:


  • 其中 T(HS_SETTLE)_avg = (T(HS_SETTLE)_min + T(HS_SETTLE)_max) / 2,如传感器数据表所指示。

  • TIMER_CLK 指摄像头传感器所连接的 PHY 接口的工作频率。(例如,PHY0 的CAMSS_PHY0_CSI0PHYTIMER_CLK)。该值在 kernel/arch/arm/boot/dts/msm/msmXXXX-camera.dtsi 文件中设置,其中 XXXX 指正在使用 MSM 芯片组。另外,也可在摄像头数据流传输期间确认,方法是通过 adb shell 检查相应的时钟信息。

  • 例如,可通过命令提示窗口发出以下命令以确认 PHY0 定时器时钟值:

adb root adb remount adb shell cd /sys/kernel/debug/clk/gcc_camss_csi0phytimer_clk cat measure 200000146

  • 对于 45 nm MSM 芯片,使用与 28 nm MSM 芯片相似的公式,其中的 T(TIMER_CLK)替换为 T(DDR_CLK)。

  • – DDR_CLK 指摄像头传感器的 MIPI CLK 通道的工作频率,该值由通过传感器摄像头驱动程序设置的摄像头传感器 PLL 配置确定。

  • – T(DDR_CLK) 为工作频率等于 DDR_CLK 时的时钟周期持续时间,以纳秒为单位表示。例如,DDR_CLK 200 MHz 的 T(DDR_CLK) 为 (1 * (10^9)) / (200 * (10^6)) =5 ns。

  • 有关 T(HS_SETTLE) 的定义,可参见针对 D-PHY(版本 1.1)的 MIPI(R)联盟规范。为了防止上述系数在传感器工作时所处的不同数据流传输模式间发生变化,必须为摄像头传感器驱动程序中每个唯一的数据流传输模式单独配置 settle_cnt。

(5)Binning Mode

  • Camera Binning Mode:像素合并模式,将相邻的像素单元电荷通过物理的方法叠加在一起作为一个像素输出信号;

935         .binning_factor = 1,                                                                                                936         .binning_method = 0,


  1. 水平方向Binning: 同列相邻行的电荷叠加;

  2. 垂直方向Binning: 同行相邻列的电荷叠加;

  3. Binning Mode 优势:增加感光面积,提高暗处对光感应的灵敏度;应用:增加物理感光像素单元,采用像素合并模式,提升暗处对光感应的灵敏度;

  4. Binning Mode 劣势:降低输出分辨率;

额外补充:

  1. sensor 开窗的不同模式:ROI, BIN,SKIP;

  2. ROI :Region of interes在相机传感器分辨范围内定义一个或多个感兴趣的窗口区域,仅对这些窗口内的图像信息进行读出,只获取该局部区域的图像;

  3. BIN :这种模式就是按照一定的规律,把想要的数据采集上来,把其余的数据扔掉;

  4. SKIP:就是把相邻的像素合成一个像素,然后再输出。

(6)I2C CLK

  • The available I2C frequency modes are defined in kernel/include/media/msm_cam_sensor.h:standard (100 kHz), fast (400 kHz), and Custom mode.

enum i2c_freq_mode_t {

I2C_STANDARD_MODE,

I2C_FAST_MODE,

I2C_CUSTOM_MODE,

I2C_MAX_MODES,

};
  • 高通平台上两条Camera I2C设备总线是专门为Camera用的,配置不同的i2c频率的参数值定义在dtsi里面;

479 &i2c_freq_100Khz {
480     qcom,hw-thigh = <78>;
481     qcom,hw-tlow = <114>;
482     qcom,hw-tsu-sto = <28>;
483     qcom,hw-tsu-sta = <28>;
484     qcom,hw-thd-dat = <10>;
485     qcom,hw-thd-sta = <77>;
486     qcom,hw-tbuf = <118>;
487     qcom,hw-scl-stretch-en = <0>;
488     qcom,hw-trdhld = <6>;
489     qcom,hw-tsp = <1>;
490 };
  • CCI clock = (src clock) / (hw_thigh + hw_tlow) //src clock 19.2MHZ

解释如下:

qcom,hw-thigh : should contain high period of the SCL clock in terms of CCI clock cycle qcom,hw-tlow : should contain high period of the SCL clock in terms of CCI clock cycle qcom,hw-tsu-sto : should contain setup time for STOP condition 

qcom,hw-tsu-sta : should contain setup time for Repeated START condition 

qcom,hw-thd-dat : should contain hold time for the data 

qcom,hw-thd-sta : should contain hold time for START condition 

qcom,hw-tbuf : should contain free time between a STOP and a START condition qcom,hw-scl-stretch-en : should contain enable or disable clock stretching 

qcom,hw-trdhld : should contain internal hold time for SDA 

qcom,hw-tsp : should contain filtering of glitches i2c burst mode: 

+-+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+-

(一)bus overflow

  • 摄像头传感器时钟通道(即 MIPI DDR 时钟)的工作频率与激活的数据通道数决定摄像头传感器在指定操作模式下的总数据传输速率(吞吐量)。每个通道的数据传输速率是 MIPI DDR 时钟速度的两倍。例如,工作在 200 MHz MIPI DDR 时钟频率和 4 个激活通道下的摄像头传感器的总数据传输速率为 1600 Mbps(每个通道的数据传输速率为 200 * 2 = 400 Mbps)。

  • 每个帧的分辨率、额外/虚拟像素/线数、水平消隐、垂直消隐、MIPI 包开销、每像素位数、数据格式、内部是否存在多个交错数据流以及每个流的数据传输速率/开销等,都会影响数据传输速率。指定工作模式下初步摄像头调通,计算:X = 帧宽 * (帧高垂直消隐) 每像素位数 * 每秒帧数 * (MIPI 协议和其他数据流的开销)在 VFE 时钟优化中为给定的 MSM 找到大于 X 的最接近的值作为 VFE 时钟的初始值。

  • 在标称时钟模式下,比如MSM8909的VFE最大速度为266MHz每条MIPI通道的PHY限制为1.5 Gbps (1.5 * 109 bps),由于存在MIPI/空白开销(约15-25%,各传感器的具体数值有所不同),实际帧数据吞吐量略少于预期原图拍摄接口数据传输速率与VFE时钟无关在4通道PHY接口上,每条通道的最大数据为(266 x bpp)/通道数;bpp → 每像素的传感器输出位数对于每通道10位数据传输速率 - (266*10)/4 - 665 Mbps;

当我们VFE 时钟设置为小于传感器输出MIPI的数据传输速率时,将出现溢出bus overflow; 502:        pr_err_ratelimited("%s: image master 0 bus overflow\n", 

507:        pr_err_ratelimited("%s: image master 1 bus overflow\n", 

512:        pr_err_ratelimited("%s: image master 2 bus overflow\n", 

517:        pr_err_ratelimited("%s: image master 3 bus overflow\n", 

522:        pr_err_ratelimited("%s: image master 4 bus overflow\n", 

527:        pr_err_ratelimited("%s: image master 5 bus overflow\n", 

532:        pr_err_ratelimited("%s: image master 6 bus overflow\n",

  • 增大VFE时钟可防止溢出发生。要更改VFE时钟,需打Vendor/qcom/proprietary/mm-camera/mm-camera2/media-controller/modules/sensors/sensor_libs/xxxx/ xxxx_lib.c文并编辑 op_pixel_clk 参数。

  • 选择正确的 VFE 时钟非常重要。VFE 时钟频率应足够高以匹配传感器输出端的数据速率(即传感器输出帧 x 帧/s),否则可能会引起 ISPIF 溢出。不过也不应设置过高的频率。设置过高的 VFE 时钟频率会导致两类问题:

  1. 由于可能填充内部 VFE 输出缓存(也称为统一缓存),总线溢出的几率增大。

  2. 如果 VFE 时钟频率较高,会导致功耗增大。

A. 检查与 VFE 总线溢出相关的总线时钟

  • 当过多的 VFE 数据流量以超过可用总线带宽的速率产生时,会导致 VFE 总线溢出错误。解决该问题的一种可行方法是检查能否通过设置更高的总线时钟频率来增加总线带宽。例如在 MSM8916 芯片组中,VFE 生成处理后的输出帧到系统 NoC (SNoC) 总线。数据流随后被转发到总线集成内存控制器 (BIMC) 总线,暂时保存在 DDR 内存中。VFE 生成的数据流将在这两条总线形成的路径上运行。因此,SNoC 和 BMIC 总线都必须进行检查。adb shell 脚本每隔一秒会转储 SNoC 和 BIMC 时钟频率。

#adb shell "while true; do cat /d/clk/snoc_clk/measure; cat /d/clk/bimc_clk/measure; echo '-----'; sleep 1; done" 200001391 748805675 -----

B. 将时钟总线设为最大频率

  • VFE 总线溢出分类的第一步是检查能否通过设置更高总线时钟频率来增加可用总线带宽。增加总线带宽后,查看 VFE 总线溢出问题是否得以解决。

adb root adb shell sleep 1 

adb shell mount -t debugfs none /d 

adb shell echo "22 > /d/msm-bus-dbg/shell-client/mas" 

adb shell echo "512 > /d/msm-bus-dbg/shell-client/slv" 

adb shell echo "0 > /d/msm-bus-dbg/shell-client/ab" 

adb shell echo "6400000000 > /d/msm-bus-dbg/shell-client/ib" 

adb shell echo "1 > /d/msm-bus-dbg/shell-client/update_request"

  • 以上脚本尝试设置从 MDP(显示硬件模块)到 DDR 内存路径中的所有总线。不管摄像头如何操作,通过从 MDP 显示屏侧(ID 22 表示 MDP)请求高带宽,总线会始终保持最大时钟频率。选择显示屏 (MDP) 而不是摄像头 ISP (VFE) 的原因是显示屏 MDP 一直运行,而摄像头驱动程序在启动和停止时会覆盖摄像头表决。而且这种更简单的测试场景能解决所有起伏问题。通过以上测试,再次检查总线时钟是否增加到最大频率。应用上述设置后,SNoC 和BIMC 时钟频率分别应为 266 MHz 和 533 MHz(不同平台参数不一致,对应不同的性能等级)。

  • 如果没有任何改进,可尝试按以下步骤在 CPU 高性能模式下运行系统并设置最大总线时钟频率:

adb shell "echo 1 > /sys/devices/system/cpu/cpu1/online" adb shell "echo performance > /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor"

C. 从 VFE 检查 AB/IB 表决带宽

  • 在检查 VFE 侧要求的总 AB 和 IB 带宽时,确保摄像头已启动。

  • 运行以下命令:

adb root 

adb shell cat /d/msm-bus-dbg/client-data/msm_camera_isp 

1223.023734896 

curr   : 1 

masters: 29   

slaves : 512   

ab     : 100000000   

ib     : 100000000   

1223.024648282 

curr   : 2 

masters: 29   

slaves : 512   

ab     : 200000000   

ib     : 200000000   

1228.214552238 

curr   : 1 

masters: 29   

slaves : 512   

ab     : 921819520   

ib     : 921819520

  • 输出第一行中的数字 351.706326427 表示发出请求时的内核时间戳。Master(s) 29 表示总线流量来自 VFE,Slave(s) 512 表示总线流量的目的地设为 memory;AB/IB VFE 发出的最终宽带请求分别为 930 MBps/1.62 GBps。

D. 识别 AXI 配置

  • VFE 总线溢出日志经常始于表明某个具体写入主控上出现溢出,因此内核日志显示的首个溢出实例就显得非常重要,可以帮助确认溢出来源。在 VFE 总线溢出分析(特别是 ZSL 预览场景)过程中,通常要求找到具体图像写入主器件和预览/快照输出帧面的映射关系,以确定要优化的数据流。例如,确定预览数据流的总线溢出后,仅关注预览数据流。在内核中添加以下调试日志消息,并在 Salesforce 用列系统分享该日志。

--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c
@@ -1384,8 +1384,10 @@ static int  msm_isp_axi_stream_enable_cfg(
        if (stream_info->state == START_PENDING ||
                stream_info->state == RESUME_PENDING) {
                enable_wm = 1;
+        pr_err("__debug__: WM[%d] ENABLE, src = %d, max_width = %u\n",stream_info->wm[i], stream_info->stream_src, stream_info->max_width);
        } else {
                enable_wm = 0;
+        pr_err("__debug__: WM[%d] DISENABLE, src = %d, max_width = %u\n",stream_info->wm[i], stream_info->stream_src, stream_info->max_width);
        }

E. 增加 AB/IB

  • 如果将时钟总线设为最大频率,能够解决buffer ovflow的问题,可以尝试增加总体总线时钟频率,总线时钟频率只会在摄像头工作时增加,逐渐增加或将原来数字乘2或逐渐减少来找出最优数量。

//kernel/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c

62 #define MSM_ISP_MIN_AB 100000000                                                                                                                   63 #define MSM_ISP_MIN_IB 100000000

F. 提高VFE 突发长度变化

  • 尽管最优 VFE 突发长度没有明确答案,但改变 VFE 突发长度也能够减少 VFE 总线溢出问题。

28 #define VFE40_BURST_LEN 1                                                                                                                         29 #define VFE40_BURST_LEN_8916_VERSION 2 30 #define VFE40_BURST_LEN_8952_VERSION 3 33 #define VFE40_STATS_BURST_LEN 1 34 #define VFE40_STATS_BURST_LEN_8916_VERSION 2

(二)sof freeze

  • sof freeze(SOF:start of frame)表示ISP这边没有收到sensor这边输出的图像帧数据,这时必须检查 CSID/CSIPHY/CAMIF是否出错。有专门建立了thread来负责SOF的检测,start_sof_check_thread() -> mct_bus_sof_thread_run(),log当中会有下面的错误发出:

// msm-3.18/drivers/media/platform/msm/camera_v2/msm.c

803     case MSM_CAM_V4L2_IOCTL_NOTIFY_DEBUG: { 804         if (event_data->status) { 805             pr_err("%s:Notifying subdevs about potential sof freeze\n", 806                 __func__);

  • 首先看能否dump出现数据:

  /*
        0 Disabled; this value is set by default
        2 Dump preview frames
        8 Dump snapshot frames
        16 Dump video frames
        */

        adb root
        adb shell setprop persist.camera.isp.dump 8
        adb shell chmod 777 /data
Verifying the VFE hardware configuration

    In the msm_isp_axis_util.c file, locate the following code snippet:

    if (vfe_dev->dump_reg)
     msm_camera_io_dump_2(vfe_dev->vfe_base, 0x900);
  • Replace it with:

24 if (1) 25 msm_camera_io_dump_2(vfe_dev->vfe_base, 0x900);

  • 若声明的传感器输出大小与 VFE 实际接收到的传感器输出大小之间不匹配,将发生 CAMIF错误。

//mm-camera/mm-camera2/media-controller/modules/iface2/iface_util.c

//mm-camera/mm-camera2/media-controller/modules/iface2/iface_util.c

8878 static void iface_util_dump_camif_cfg(struct msm_vfe_input_cfg *input_cfg)                                                                       8879 { 8880   struct msm_vfe_pix_cfg *pix_cfg = NULL; 8881 8882   if (input_cfg == NULL) 8883     return; 8884 8885   pix_cfg = &input_cfg->d.pix_cfg; 8886   IFACE_HIGH("=====Camif DUMP cfg for PIX interface====\n"); 8887   IFACE_HIGH("camif input type = %d(MIPI=3), op_pix_clk = %d\n", 8888     pix_cfg->camif_cfg.camif_input, input_cfg->input_pix_clk); 8889   IFACE_HIGH("camif pix_pattern(RGRG-0/GRGR-1/BGBG-2/GBGB-3) = %d\n", 8890     pix_cfg->pixel_pattern); 8891   IFACE_HIGH("camif first_pix = %d, last_pix = %d\n", 8892     pix_cfg->camif_cfg.first_pixel, pix_cfg->camif_cfg.last_pixel); 8893   IFACE_HIGH("camif first_line = %d, last_line = %d\n", 8894     pix_cfg->camif_cfg.first_line, pix_cfg->camif_cfg.last_line); 8895   IFACE_HIGH("camif pixels_per_line = %d, lines_per_frame = %d\n", 8896     pix_cfg->camif_cfg.pixels_per_line, pix_cfg->camif_cfg.lines_per_frame); 8897   IFACE_HIGH("camif irq subsample pattern = %x, period = %d sof_step %d\n", 8898     pix_cfg->camif_cfg.subsample_cfg.irq_subsample_pattern, 8899     pix_cfg->camif_cfg.subsample_cfg.irq_subsample_period, 8900     pix_cfg->camif_cfg.subsample_cfg.sof_counter_step); 8901 }

  • 将调试消息中指示的帧大小与 ISP 传感器的帧大小进行比较。在以下 CAMIF 错误示例中,错误状态 0x9a70a00 表示 ISP 接收帧的大小为 2471x2560(0x9a7 = 2471,0xa00 = 2560)。

01-01 08:07:20.175 E/mm-camera( 302): isp_hw_camif_dump_cfg: camif input_format= 0 01-01 08:07:20.175 E/mm-camera( 302): isp_hw_camif_dump_cfg: camif last_pix = 6527 01-01 08:07:20.175 E/mm-camera( 302): isp_hw_camif_dump_cfg: camif last_line = 0 01-01 08:07:20.175 E/mm-camera( 302): isp_hw_camif_dump_cfg: camif lines per frame = 2448 01-01 08:07:24.335 E/klogd (640): [81.563301] msm_vfe40_process_error_status: camif error status: 0x9a70a00

  • 如果存在不匹配,则根本原因可能如下:

  • 检查传感器设置是否正确,是否满足分辨率大小的要求。例如,传感器的输出大小配置为 12 MB,但 ISP 的接收大小却配置为 8 MB。可能有些传感器无法确保在新分辨率设置发送至传感器后,最初的帧大小能够满足要求。在这种情况下,需要与传感器供应商一起解决此问题。


高通Camera驱动--调试技术大全(看完悟了)的评论 (共 条)

分享到微博请遵守国家法律