RK平台5640 camera预览界面帧率过低的分析

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

@@ -142,8 +142,8 @@ static const struct sensor_register ov5640_dvp_init_regs[] = {
        {0x3017, 0xff},
        {0x3018, 0xff},
        {0x3034, 0x1a},
-       {0x3036, 0x46},
+       {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, 0x46},
+       {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},//0x03
@@ -519,7 +519,7 @@ static const struct sensor_register ov5640_dvp_svga_30fps[] = {
        {0x3002, 0x1c},
        {0x4713, 0x03},
        {0x3035, 0x21},
-       {0x3036, 0x46},
+       {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,
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值