hal 层
/hardware/rockchip/camera
├── AAL Android Abstraction Layer, 负责与 framework 交互
├── common 公用文件,如线程,消息处理,Log 打印等实现
├── etc 配置文件目录
├── include Control loop 的头文件,buffer_manager 相关头文件
├── lib 3a engine 相关库
├── psl Physical Layer,物理实现层,所有的实现逻辑基本都在这里
│ └── rkisp1 目前只有 Rkisp1 一套实现方案
│ ├── tasks 基本只用到了里面的几个 Notify 的接口类和 JpegEncodeTask
│ └── workers 数据的获取处理都在这里
Driver层:
Linux Kernel-4.4:
|
|arch/arm64/boot/dts/rockchip DTS 配置文件
|phy/rockchip/phy-rockchip-mipi-rx.c mipi dphy 驱动,独立于 cif 驱动
|drivers/media
|
|platform/rockchip/cif
|── capture.c RKCIF 驱动 主要完成硬件配置,v4l2、vb2 框架下的相关回调,帧中断处理
|── dev.c 主要完成 probe,sub-device 异步(Async)注册,
iommu 及 clk 管理
|── dev.h 驱动相关结构体定义
|── regs.h 寄存器宏定义
|i2c/ Camera Sensor 驱动
打开前摄配置:
device/rockchip/common/device.mk
device/rockchip/common/device_tab10_rk66.mk
hardware/rockchip/camera/etc/camera/camera3_profiles_rk356x.xml
替换文件命令:
adb push camera3_profiles_rk356x.xml /vendor/etc/camera/camera3_profiles.xml
adb push camera3_profiles_rk356x.xml /vendor/etc/camera/
打开hal和driver相关debug log:
adb shell
setprop persist.vendor.camera.hal.debug 5 && echo 1 > /sys/module/video_rkcif/parameters/debug && echo 1 > /sys/module/video_rkisp1/parameters/debug
adb reboot
hal层向驱动下发的分辨率及帧率,是正常的,driver层设置给Sensor的也是30帧。log如下:
04-18 22:21:36.168 0 0 I ov5640 2-003c: ov5640_s_stream: on: 1, 800x600@30
kernal/drivers/media/i2c/ov5640.c:1383
static int ov5640_s_stream(struct v4l2_subdev *sd, int on)
{
struct i2c_client *client = v4l2_get_subdevdata(sd);
struct ov5640 ov5640 = to_ov5640(sd);
int ret = 0;
dev_info(&client->dev, "%s: on: %d, %dx%d@%d\n", func, on,
ov5640->frame_size->width,
ov5640->frame_size->height,
ov5640->frame_size->fps);
mutex_lock(&ov5640->lock);
on = !!on;
if (ov5640->streaming == on)
goto unlock;
if (!on) {
/ Stop Streaming Sequence */
ov5640_set_streaming(ov5640, on);
ov5640->streaming = on;
goto unlock;
}
ret = ov5640_write_array(client, ov5640->frame_size->regs);
if (ret)
goto unlock;
ov5640_set_streaming(ov5640, on);
ov5640->streaming = on;
unlock:
mutex_unlock(&ov5640->lock);
return ret;
}
但是实际只有不到15帧,帧率减半。
04-18 22:21:55.858 336 2043 I RkCamera: Stream: showDebugFPS: Preview FPS : 14.2126: mFrameCount=281
04-18 22:21:56.900 336 2043 I RkCamera: Stream: showDebugFPS: Preview FPS : 14.3890: mFrameCount=296
疑点1怀疑是否是单帧模式,查询RK相关问题,发现在单帧(单buffer)模式下最高只有15帧。
/rk3566/tab10-rk66-gms/kernel/drivers/media$ grep -nr RKCIF_WORKMODE_PINGPONG
platform/rockchip/cif/dev.h:86: RKCIF_WORKMODE_PINGPONG = 0x01,
platform/rockchip/cif/procfs.c:225: dev->workmode == RKCIF_WORKMODE_PINGPONG ? “ping pong” : “line loop”);
添加如下log验证,是否走到pingpong,双buffer模式的方法。
/kernel/drivers/media/drivers/media/platform/rockchip/cif/capture.c添加log:
static void rkcif_assign_new_buffer_pingpong(struct rkcif_stream *stream,
int init, int channel_id)
{
-
struct rkcif_device *dev = stream->cifdev;
-
v4l2_info(&dev->v4l2_dev,"rkcif_assign_new_buffer_pingpong!\n");
if (init)
rkcif_assign_new_buffer_init(stream, channel_id);
可以发现使用的是双buffer模式,dmesg log如下:
[ 766.474865] ov5640 2-003c: ov5640_s_stream: on: 1, 800x600@30
[ 766.499639] ov5640 2-003c: ov5640_set_streaming: on: 1
[ 766.500305] rkcif_dvp: set dual edge mode(off,0x2000000)!!!
[ 766.500337] rkcif_dvp: rkcif_assign_new_buffer_pingpong!
[ 766.545358] rkcif_dvp: rkcif_irq_pingpong!
[ 766.610300] rkcif_dvp: rkcif_irq_pingpong!
[ 766.610345] rkcif_dvp: rkcif_assign_new_buffer_pingpong!
疑点2 跟 MCLK 有关
逻辑上 Sensor 输出的帧率只跟写入 OV5640的寄存器配置一样,驱动及配置一样的话,帧率应该一样的,分析可能跟 MCLK 有关。
在xxxx_power_on 或 xxxx_s_power 中重新设置 clk,
/kernel/drivers/media/i2c/ov5640.c
ret = clk_set_rate(ov5640->xvclk, OV5640_XVCLK_FREQ);
if (ret < 0) {
dev_err(dev, "Failed to set xvclk rate (24MHz)\n");
return ret;
}
if (clk_get_rate(ov5640->xvclk) != OV5640_XVCLK_FREQ)
dev_warn(dev, "xvclk mismatched, modes are based on 24MHz\n");
ret = clk_prepare_enable(ov5640->xvclk);
if (ret < 0) {
dev_err(dev, "Failed to enable xvclk\n");
return ret;
}
经验证仅仅添加如上代码验证失败。
将OV5640_XVCLK_FREQ设置为27000000后帧率提高到16.5帧
/kernel/drivers/media/i2c/ov5640.c
#define OV5640_XVCLK_FREQ 27000000
于是考虑提高时钟频率,查看ov5640文档:
24Mzh时钟倍频寄存器0x3036的值 0x21增加为0x69(10进制:105)后帧率提高到24帧。
kernel/drivers/media/i2c/ov5640.c
[url=home.php?mod=space&uid=1999721]@@[/url] -142,8 +142,8 @@ static const struct sensor_register ov5640_dvp_init_regs[] = {
{0x3017, 0xff},
{0x3018, 0xff},
{0x3034, 0x1a},
-
{0x3036, 0x69},
{0x3037, 0x13},
{0x3108, 0x01},
{0x3630, 0x36},
@@ -426,8 +426,8 @@ static const struct sensor_register ov5640_dvp_init_regs[] = {
{0x4004, 0x02},
{0x3002, 0x1c},
{0x4713, 0x03},
-
{0x3035, 0x21},
-
{0x3036, 0x46},
-
{0x3035, 0x11},
-
{0x3036, 0x69},
{0x4837, 0x22},
{0x3824, 0x02},
{0x5001, 0xa3},
@@ -518,8 +518,8 @@ static const struct sensor_register ov5640_dvp_svga_30fps[] = {
{0x4004, 0x02},
{0x3002, 0x1c},
{0x4713, 0x03},
-
{0x3036, 0x69},
{0x4837, 0x22},
{0x3824, 0x02},
{0x5001, 0xa3},
@@ -1644,6 +1644,18 @@ static int ov5640_power(struct v4l2_subdev *sd, int on)
usleep_range(2000, 5000);
}
}
-
ret = clk_set_rate(ov5640->xvclk, OV5640_XVCLK_FREQ)
-
if (ret < 0) {
-
dev_err(dev, "Failed to set xvclk rate (24MHz)\n");
-
return ret;
-
}
-
if (clk_get_rate(ov5640->xvclk) != OV5640_XVCLK_FREQ)
-
dev_warn(dev, "xvclk mismatched, modes are based on 24MHz\n");
-
ret = clk_prepare_enable(ov5640->xvclk)
-
if (ret < 0) {
-
dev_err(dev, "Failed to enable xvclk\n");
-
return ret;
-
}
return 0;
}
将寄存器{0x3035, 0x21}改为{0x3035, 0x11}后,预览几秒中会出现dvp overflow err错误,应该是时钟太快导致。
[ 1471.425173] rkcif_dvp: ERROR: DVP_ALL_ERROR_INTEN:0xa!!
[ 1471.425206] rkcif_dvp: dvp pix err
[ 1471.425211] rkcif_dvp: ERROR: DVP_ALL_ERROR_INTEN:0x40a!!
[ 1471.425220] rkcif_dvp: dvp overflow err
[ 1471.425225] rkcif_dvp: ERROR: DVP_ALL_ERROR_INTEN:0x420!!
[ 1471.425391] rkcif_dvp: dvp pix err
[ 1471.425401] rkcif_dvp: ERROR: DVP_ALL_ERROR_INTEN:0x40a!!
24Mzh时钟倍频寄存器0x3036 0x21增加为0x7d (10进制:125)后,帧率提高到26.5帧,显示正常。
24Mzh时钟倍频寄存器0x3036 0x21增加为0x84 (10进制:132)后,预览几秒后花屏,帧率达到26.9。
24Mzh时钟倍频寄存器0x3036 0x21增加为0x8c(10进制:140)后,帧率预览几秒后花屏,帧率达到28.6。
于是设置为0x7d ,26.5帧这个结果暂时满足GMS认证需求。
在1.0.6 版本时,前摄主要报出的fail项主要是帧率过低相关,
将帧率提升到26.5帧,目前重测pass的cts有:
android.hardware.cts.CameraGLTest pass
android.hardware.cts.CameraTest#testPreviewFpsRange pass
android.camera.cts android.hardware.camera2.cts.RecordingTest pass
driver修改分辨率1296×968 如下
@@ -492,10 +492,10 @@ static const struct sensor_register ov5640_dvp_svga_30fps[] = {
{0x3803, 0x04},
{0x3806, 0x07},///
{0x3807, 0x9b},
-
{0x3808, 0x03},
-
{0x3809, 0x20},
-
{0x380a, 0x02},
-
{0x380b, 0x58},
-
{0x3808, 0x05},
-
{0x3809, 0x10},
-
{0x380a, 0x03},
-
{0x380b, 0xc8},
{0x380c, 0x07},
{0x380d, 0x68},
{0x380e, 0x04},
@@ -519,7 +519,7 @@ static const struct sensor_register ov5640_dvp_svga_30fps[] = {
{0x3002, 0x1c},
{0x4713, 0x03},
{0x3035, 0x21},
-
{0x3036, 0x84},
{0x4837, 0x22},
{0x3824, 0x02},
{0x5001, 0xa3},
@@ -1022,8 +1022,8 @@ static const struct sensor_register ov5640_mipi_full[] = {
static const struct ov5640_framesize ov5640_dvp_framesizes[] = {
{ /* SVGA */
-
.width = 800,
-
.height = 600,
-
.width = 1296,
-
.height = 968,
原作者:小陈博客