高通Camera驱动--调试技术大全

2023-02-20 00:00:00 溢出 时钟 总线 传感器 频率

本文主要介绍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 吐出数据的带宽;不同的平台的处理能力不一样,所以这个值不能超过平台规范定义的值;

(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:

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

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 芯片,使用以下公式计算稳定计数:

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

其中 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,

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

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

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

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

额外补充:

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

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

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

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


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。可能有些传感器无法确保在新分辨率设置发送至传感器后,初的帧大小能够满足要求。在这种情况下,需要与传感器供应商一起解决此问题。

版权声明:本文为CSDN博主「ForDream321」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。

原文链接:高通Camera 驱动调试要点(二)

相关文章