RK3588硬件平台-摄像头外设驱动overview 以及bringup 调试流程
目录
2.配置camera3_profiles.xml文件... 8
Android平台camera_engine的使用与调试... 14
目的:
- 可以使嵌入式软件开发工程师迅速了解RK3588平台的csi驱动软件架构
- 可以使嵌入式软件开发工程师迅速上手RK3588平台的csi驱动bringup工作
开场
本文档概述了Linux Android 摄像头模块软件驱动程序的流程以及bringup过程
适用对象:嵌入式软件开发工程师
一.摄像头模块相关框图
模块硬件框图
- CSI:camera接口,接收图像数据,RGB/YUV/JPEG等;
- CCDC:视频处理前端,CCDC为图像传感器和数字视频源提供接口,并处理图像数据;
- Preview/Resizer:视频处理后端,Preview提供预览功能,可针对不同类型的传感器进行定制,Resizer提供将输入图像数据按所需的显示或视频编码分辨率调整大小的方法;
- H3A/HIST:静态统计模块,H3A支持AF(自动对焦)、AWB(自动白平衡)、AE(自动曝光)的回路控制,HIST根据输入数据,提供各种3A算法所需的统计数据;
官方摄像头原理图参考:
1. full mode:节点名称使用csi2_dphy0,最多支持4 lane。
2. split mode:拆分成2个phy使用,分别为csi2_dphy1(使用0/1 lane)、csi2_dphy2(使用2/3 lane),每个phy最多支持2 lane。
3. 当dphy0_hw使用full mode时,链路需要按照csi2_dphy1这条链路来配置,但是节点名称csi2_dphy1需要修改为csi2_dphy0,软件上是通过phy的序号来区分phy使用的模式。
4. rk3588支持2个isp硬件,每个isp设备可虚拟出多个虚拟节点,软件上通过回读的方式,依次从ddr读取每一路的图像数据进isp处理。对于多摄方案,建议将数据流平均分配到两个isp上。
5. 直通与回读模式:
- 直通:指数据经过vicap采集,直接发送给isp处理,不存储到ddr。需要注意的是hdr直通时,只有短帧是真正的直通,长帧需要存在ddr,isp再从ddr读取。
2) 回读:指数据经过vicap采集到ddr,应用获取到数据后,将buffer地址推送给isp,isp再从ddr获取图像数据。
3)dts配置时,一个isp硬件,如果只配置一个虚拟节点,默认使用直通模式,如果配置了多个虚拟节点默认使用回读模式。
6. rk3588多摄dts参考arch/arm64/boot/dts/rockchip/rk3588-evb1-cam-6x.dtsi,硬件支持最多采7路sensor:6mipi+1dvp,多sensor软件通路如下:
摄像头模块软件框图
摄像头软件驱动(Driver)
CIS 设备dts设备注册
Rkisp1 的DTS节点在kernel源码中有文档说明,路径如下:
Documentation/devicetree/bindings/media/rockchip-isp1.txt。
mipi dphy驱动节点kernel源码中有文档说明,路径如下:
Documentation/devicetree/bindings/media/rockchip-mipi-dphy.txt
MIPI CIS注册如图所示:
设备树解析如图:
dvp CIS注册如图所示:
CIS 设备驱动代码
下面以rk3588 isp1和ov13850 为例进行说明:
摄像头驱动移植步骤
1.实现标准 I2C 子设备驱动部分。
1.1 根据 struct i2c_driver 说明实现以下成员:
struct driver.name
struct driver.pm
struct driver. of_match_table
probe 函数
remove 函数
1.2 probe 函数实现细节描述:
- CIS 设备资源的获取,主要是解析DTS文件中定义资源:
- RK私有资源定义,命名方式如下rockchip,camera-module-xxx, 该部分资源会由驱动上传给用户态的 camera_engine 来决定IQ效果参数的匹配;
- CIS设备资源定义,RK相关参考驱动一般包含以下几项:
CIS 设备工作参考时钟;
CIS 设备控制 GPIO;
CIS 设备控制电源;
-
- CIS设备ID号检查, 通过以上步骤获取必要资源后,建议驱动读取设备ID号以便检查硬件的准确性。
- CIS v4l2设备以及media实体的初始化;
v4l2子设备:v4l2_i2c_subdev_init,RK CIS驱动要求subdev拥有自己的设备节点供用户态 camera_engine访问,通过该设备节点实现曝光控制;
media实体:media_entity_init
2.参考struct v4l2_subdev_ops说明实现v4l2子设备驱动,主要实现成员:
struct v4l2_subdev_ops |
struct v4l2_subdev_core_ops (核心回调函数) |
struct v4l2_subdev_video_ops (视频模式回调函数) |
struct v4l2_subdev_pad_ops (pad水平操作函数) |
-
- 参考struct v4l2_subdev_core_ops说明实现其回调函数,主要实现以下回调:
struct v4l2_subdev_core_ops |
.ioctl (IO控制函数) |
.compat_ioctl32 (32位程序使用64位内核时调用) |
私有的驱动ioctl()的IO控制函数涉及:
RKMODULE_GET_MODULE_INFO (dts定义的模组信息)
RKMODULE_AWB_CFG (模组OTB信息使能,传递AWB标定信息)
RKMODULE_LSC_CFG (模组OTB信息使能,控制LSC标定值使能)
-
- 参考 struct v4l2_subdev_video_ops 说明实现其回调函数,主要实现以下 2 个回调函数:
- 参考struct v4l2_subdev_pad_ops说明实现其回调函数,主要实现以下4个回调函数:
- 参考struct v4l2_ctrl_ops说明实现,主要实现以下回调:
struct v4l2_subdev_video_ops |
int (*s_stream)(struct v4l2_subdev *sd, int enable);(通知驱动程序视频流启动和停止) |
int (*g_frame_interval)(struct v4l2_subdev *sd, struct v4l2_subdev_frame_interval *interval); |
struct v4l2_subdev_pad_ops |
.enum_mbus_code(枚举当前 CIS 驱动支持数据格式) |
.enum_frame_size(枚举当前 CIS 驱动支持分辨率) |
.get_fmt(Rkisp driver通过该回调获取CIS输出的数据格式,务必实现;针对Bayer raw sensor、SOC yuv sensor、BW raw sensor输出的数据类型定义) |
.set_fmt(设置 CIS 驱动输出数据格式以及分辨率) |
struct v4l2_ctrl_ops |
.s_ctrl(Rkisp driver、camera_engine通过设置不同的命令来实现CIS曝光控制) |
参考CIS驱动V4L2-controls列表1实现各控制ID,其中以下ID属于信息获取类:
V4L2_CID_LINK_FREQ (获取mipi总线频率)
V4L2_CID_PIXEL_RATE (像素速率,针对MIPI总线:pixel_rate = link_freq * 2 * nr_of_lanes / bits_per_sample)
V4L2_CID_HBLANK (垂直消隐)
V4L2_CID_VBLANK (水平消隐)
RK camera_engine 会通过以上命令获取必要信息来计算曝光,其中涉及的公式如下:
line_time = HTS * PIXEL_RATE;
HTS = sensor_width_out + HBLANK;
VTS = sensor_height_out + VBLANK;
其中以下ID属于控制类,RK camera_engine通过该类命令控制CIS:
V4L2_CID_VBLANK (调整VBLANK,进而调整frame rate、Exposure time max)
V4L2_CID_EXPOSURE (设置曝光时间,单位:曝光行数)
V4L2_CID_ANALOGUE_GAIN (设置曝光增益,实际为total gain=analog gain*digital gain; 单位:增益寄存器值)
3.CIS驱动不涉及硬件数据接口信息定义, CIS设备与AP的接口连接关系由DTS设备节点的Port来体现其连接关系。
二.HAL层数据流调试
在 sensor 驱动已经调通的基础上,HAL 中添加新 sensor 支持需要配置如下文件:
1) 获取tuning文件,SOC sensor可略过此步骤 ;
2) 配置camera3_profiles.xml ;
3) 将配置文件push到板子,并重新启动camera进程。
1.获取tunning.xml文件
tunning.mxl文件是效果参数文件,只有Raw sensor才需该此文件。该文件如何获取可以联系FAE。
该文件需要以如下方式命令:<sensor_name>_<module_name>_<lens_name>.xml,并将该文件push到板子的/vendor/etc/camera/rkisp1目录下。最终3a库会从该目录中读取符合规则的tuning文件。
2.配置camera3_profiles.xml文件
在<hal3_camera>/etc/camera目录下有多个camera3_profiles_<platform>.xml,最终会有一个文件push到 /vendor/etc/camera/camera3_profiles.xml. 选择一个适用的camera3_profiles_<platform>.xml文件,参照前面sensor的配置添加新sensor。
camera3_profiles.xml中包含了多个Profiles节点,Profiles节点包含一个camera完整属性列表。开发板上接了几个 sensor,即需要配置几个Profiles节点。
Profiles 节点下又包含了如下四个子节点。
<Profiles cameraId="0" name="ov5695" moduleId="m00">
<Supported_hardware>
</Supported_hardware>
<Android_metadata>
</Android_metadata>
<Hal_tuning_RKISP1>
</Hal_tuning_RKISP1>
<Sensor_info_RKISP1>
</Sensor_info_RKISP1>
</Profiles>
1.自动配置方式的说明:
camera3_profiles.xml中增加forceAutoGenAndroidMetas配置选项,以选择是否使用自动生成配置项的方式。 forceAutoGenAndroidMetas在camera3_profiles.xml中所处位置:
<Hal_tuning_RKISP1>
<forceAutoGenAndroidMetas value="false"/>
</Hal_tuning_RKISP1>
forceAutoGenAndroidMetas 配置为”true”时,表示使用自动生成的方式;
forceAutoGenAndroidMetas 配置为”false”时,表示使用手动配置的方式;
未配置 forceAutoGenAndroidMetas 时,默认使用手动配置的方式。
2. 手动配置方式的说明:
各平台已有提供参考的xml配置文件,另外camera3_profiles_default.xml中有提供RAW sensor及SOC sensor的参考配置,配置时务清楚是SOC还是RAW sensor,然后根据对应的参考配置来进行配置。
该项配置所需要上报给应用的Camera项,每个Camera对应一项Profiles字段配置。该字段主要的配置项如下:
cameraId //不再作为关键项,可配置0或者1
name //需要与驱动名称一致,注意有大小写区别
moduleId //关键配置项,值格式为“mxx”,其中“m”为“module”缩写,“xx”为十进制数字,标示camera 唯一编号,moduleId 需要与驱动DTS中配置相一致,否则将探测错误。另外,配置多个camera时,多个camera的<profiles>项需要按照moduleId升序排列。
通过如下命令:adb shell cat /sys/class/video4linux/*/name可以获取所有v4l2设备点节的名字,其中形如 m00_b_ov5695 2-0036为sensor节点名称。该命令规则中,m00代表moduleId,主要为匹配 len,flash之用,‘b’代表camera方向为后置,如果是前置则为‘f’,‘ov5695’代表sensor name , ‘2-0036’代表I2c地址。
以下Android_metadata设置项主要为Android相关配置项,各字段具体可参考<SDK>/system/media/camera/docs/docs.html 说明。
control.aeAvailableAntibandingModes
SOC:AUTO
RAW:50HZ,60Hz // 以排在首位的作为初始化配置
control.aeAvailableModes
ON // 不支持 flash 时
ON,ON_AUTO_FLASH,ON_ALWAYS_FLASH // 支持 flash 时
control.aeAvailableTargetFpsRanges
该设置项有多个限制需要注意:
1) 录像必需要有一组恒定帧率, 假如帧率为 x, 那就要包含(x,x)
2) 录像帧率必需至少要一组大于 24 帧
3) 第一组必需 Min <= 15. 所以第一组一般为(15,x)
4) 各组帧率需要按升序排列
升序具体意义为,假设有定义有两组帧率:(min1,max1),(min2,max2),则 max2 >=max1,max2 == max1 时,还需要满足 min1 <= min2。
一般情况下 sensor 驱动只会输出两组分辨率,全分辨率及 binning 分辨率,其他分辨率即使有调试也一般不使用。
jpeg.maxSize
计算公式如下:最大分辨率为:scaler.availableStreamConfigurations中BLOB项最大分辨率项 jpeg.maxSize >= max_blob_w * max_blob_h * 3 / 2。
scaler.availableStreamConfigurations
HAL 层支持的分辨率列表,有如下限制:
1)需要按照分辨率依次降序排列
2)为了满足CTS要求,需要包含352x288,320x240,176x144 配置项
3)如果在 media_profiles_V1_0.xml 中有指定录像分辨率,那么该列表中需要包含该分辨率
4)列表中需要支持BLOB,YCbCr_420_888,IMPLEMENTATION_DEFINED三种格式输出配置,三种格式中支持的分辨率都要相同
5)为了不影响拍照速度,如果sensor最大输出尺寸宽度大于4096时,需将最大分辨率宽度限制在4096
如图是imx464的scaler.availableStreamConfigurations设置:
scaler.availableMinFrameDurations
配置 scaler.availableStreamConfigurations 中各分辨率下最小帧间隔(即最大帧率),需要满足以下条件:
1)需要包含 scaler.availableStreamConfigurations 中定义的所有格式,分辨率
2)各分辨率最大帧率可从sensor驱动获取,一般sensor只输出full及binning两种分辨率,列表中上报的支持分辨率如果sensor驱动不能直接支持,那么会由ISP裁剪及缩放得到,因此非sensor直接输出的分辨率帧率与比之更大的最接近的sensor输出分辨率相同。
sensor.info.activeArraySize
设置成sensor驱动输出的最大分辨率,可从sensor驱动得到。
sensor.info.physicalSize
sensor 物理尺寸,可从模组规格书中得到。也可从FOV计算得到。
sensor.info.pixelArraySize
设置成sensor驱动输出的最大分辨率,可从sensor驱动得到。
sensor.orientation
模组的安装方向,可设置0,90,180,270。
3.1 编译:
-
- 确认/device/rockchip/common/BoardConfig.mk文件中,是否有定义BOARD_DEFAULT_CAMERA_HAL_VERSION,如无定义,请在文件末添加如下:BOARD_DEFAULT_CAMERA_HAL_VERSION := 3.3。
- 在目录 <android_root> 下输入命令:
$ source build/envsetup.sh
$ lunch
-
- 进入hal3源码目录 下输入命令:
$ mma –j8
3.2 生成库:
1) Hal3 库: /vendor/lib<64>/hw/camera.rk30board.so
2) librkisp : /vendor/lib<64>/librkisp.so
3) 3a lib : /vendor/lib<64>/rkisp/<ae/awb/af>/
4) 配置文件: /vendor/etc/camera/
上述配置文件是通过预编译将<hal3>/etc/camera中的文件copy到android out目录。当修改源码编译后,只需push camera.rk30board.so即可,如修改配置文件,也只需要push相应配置文件。
3.3 运行:
1.将需要更新的库或者xml配置文件push到板子相应的目录。
$ adb root && adb remount
$ adb push <hal3_camera>/etc/camera /vendor/etc/ (android version >= 8.0)
$ adb push <hal3_camera>/etc/camera /system/etc/ (android version < 8.0)
2.重新启动camera服务进程
$ adb shell pkill camera && adb shell pkill provider
3.通过如下命令查看camera是否加载成功。
$ adb shell dumpsys media.camera
4.如果没有打印出camera相关信息(camera正常信息有好几百行),则加载失败。此时:
5.再次确认配置文件是否有Push到板子:
$ adb shell
$ cat /vendor/camera/camera3_profiles.xml //查看该文件是否是修改过后的文件
$ adb logcat|grep "E RkCamera" 查看是否是致命错误,定位分析。
6. 如果前三步都没有问题,底层驱动正常,可用v4l2-ctl抓到数据,此时camera应该可以打开了。Camera如果打不开,可以打开相关camera log的开关来定位问题。
$ adb shell setprop persist.vendor.camera.hal.debug 5
三.Camera engine 基本框架
camera engine 模块结构:
Engine layer:
Core engine主体功能为获取驱动数据流,实现上层帧参数控制,如3A模式等,从ISP驱动获取3A统计,调用 3A 库实现3A调整,librkisp_ae.so,librkisp_awb.so及librkisp_af.so为RK实现的3A库,实现为动态加载库,且有标准接口。
Interface layer:
在engine层基础上为Android及Linux封装了不同接口。Android 层不需要数据流部分,只需要3A控制部分,控制接口及说明请参考头文件rkisp_control_loop.h。libgstrkisp 是为gstreamer实现的插件,通过该插件,用户可通过 gsreamer 获取数据流以及控制 3A。
Application layer:
应用层,目前有适配Android的Camera Hal3及Linux平台的gstreamer。
API 简要说明
Camera engine主要提供3A功能,3A功能主要由interace/rkisp_control_loop.h文件提供,以下主要介绍该文件相关接口。
rkisp_cl_init | 初始化control loop |
rkisp_cl_prepare | 准备control loop |
rkisp_cl_start | 调用成功后control loop开始运行,3A开始工作 |
rkisp_cl_stop | 停止control loop |
rkisp_cl_deinit | 反初始化control loop |
rkisp_cl_set_frame_params | 设置新的帧参数,主要包括3A模式等 |
句柄函数设置metadata参数的基本步骤:
- 包含如下头文件:CameraMetadata.h,rkcamera_vendor_tags.h文件
- 初始化metadata:提供一些camera的基础能力信息,如支持的3A模式,最大曝光时间,支持的帧率范围,支持的分辨率等等。初始化metadata信息需要rkisp_cl_prepare时传入。
- 参数设置:设置参数时所传入的metadata可重新构造,也可以与初始化时传入的复用;但是,如果使用不同的metadata变量,则一些初始化时的参数不可再通过rkisp_cl_set_frame_params进行更改。
- 获取参数:rkisp_cl_init时需传入metadata callback函数,engine从驱动中得到统计数据,然后根据当前设置,计算出新的参数后,会将当前统计帧对应的参数及3A状态等通过该callback返回。
- 支持的metadata列表:
TAG 名称 | 描述 |
ANDROID_CONTROL_AE_LOCK | Lock住ae |
ANDROID_CONTROL_AE_MODE | 支持on/off,off时为manual模式,可设置手动曝光参数 |
ANDROID_CONTROL_AE_REGIONS | ae的测光区域 |
ANDROID_CONTROL_AE_TARGET_FPS_RANGE | 帧率范围,上限值等于下限值时代表固定 帧率 |
ANDROID_SENSOR_INFO_EXPOSURE_TIME_RA NGE | 定义曝光时间范围 |
ANDROID_SENSOR_INFO_SENSITIVITY_RANG E | 定义曝光增益范围 |
ANDROID_CONTROL_AE_STATE | 获取当前ae状态 |
ANDROID_CONTROL_AWB_MODE | 支持off/auto/INCANDESCENT/FLUORESCENT/DA YLIGHT/CLOUDY_DAYLIGHT |
ANDROID_CONTROL_AWB_REGIONS | Awb 统计窗口 |
ANDROID_CONTROL_AWB_STATE | 获取当前 awb 状态 |
ANDROID_CONTROL_AF_MODE | 支持 OFF/AUTO/CONTINUOUS_PICTURE |
ANDROID_CONTROL_AF_REGIONS | af 统计窗口 |
ANDROID_CONTROL_AF_TRIGGER | 主动触发 af 对焦 |
ANDROID_CONTROL_AF_STATE | 获取af状态 |
ANDROID_SENSOR_SENSITIVITY | 设置手动曝光时的增益及反馈当前曝光增益 |
ANDROID_SENSOR_EXPOSURE_TIME | 设置手动曝光时的时长及反馈当前曝光时长 |
RKCAMERA3_PRIVATEDATA_EFFECTIVE_DRIV ER_FRAME_ID | 反馈的当前帧metada对应的帧id,与数据帧id做对应后,可做到帧与生效参数的对应 |
RKCAMERA3_PRIVATEDATA_FRAME_SOF_TIME STAMP | 当前帧的开始传输时刻,减去曝光时间可知当前帧的起始曝光时刻 |
IQ 效果文件
IQ文件放置于iqfiles文件夹,文件名定义需要遵循以下规则:
<sensor 名称>_<模组名称>_<lens 名称>.xml
上述信息需要与内核中dts文件里定义的相一致。否则,camera engine将找不到对应的iq文件。
版本号及特帧码可通过如下方式获取:
- 通过log确认。
- 通过源码确认:
rkisp/ia-engine/calib_xml/calibdb.cpp 中有版本信息。
Android平台camera_engine的使用与调试
1.编译:
a. 将camera engine源码放至<android 工程根目录>/hardware/rockchip/
b. 工程编译环境设置好后,camera engine源码目录执行mm编译,编译后生成 librkisp.so, 3A库不提供源码,随工程提供编好的库在plugins/rkiq/<aec/af/awb>/<lib32/lib64>。
2.Android 平台调试:
a. log 开关: setprop persist.vendor.rkisp.log
b.更新库:
android 8.x 及以上库路径:
librkisp : /vendor/lib
3a: /vendor/lib/rkisp/<ae/awb/af>/
iq: /vendor/etc/camera/rkisp/
更新库后重启 camera 服务:
pkill provider && pkill camera
android 7.x 及以下库路径:
librkisp: /system/lib/
3a: /system/lib/rkisp/<ae/awb/af>/
iq: /system/etc/camera/rkisp/
更新库后重启 camera 服务:
pkill camera*