RK3588 camera调试:HDR调试(IMX577)

这篇文章主要介绍一下RK3588 平台camera sensor HDR 的驱动调试与调试IMX577 HDR模式过程中遇到的问题分享。

目录

(1)HDR简介

(2)RK3588 ISP支持HDR介绍

(3)IMX577:HDR调试

1.IMX577 HDR支持情况

2.获取HDR配置序列,查阅HDR应用手册,获取HDR相关寄存器

3.驱动添加HDR相关的IOCTL接口

4.根据手册指导,完善HDR曝光增益控制的函数

5.驱动其他接口的增加:

6.dts配置与xml配置

(4)IMX577:HDR调试与问题排查

1.抓取长短帧的raw图

2.效果异常问题排查

(5)总结


(1)HDR简介

高动态范围成像,实现比普通的数字图像技术更大曝光动态范围,简单点说就是可以显示更大的亮度范围(更大的明暗差别)。

简单点就是通过摄像头,同一时刻拍摄曝光时间不同的两张或者三张图像(称为短曝光、中曝光和长曝光),然后通过算法把3张照片中明暗表现优秀的部分提取出来,融合成一张新的图像。

例如:如上三张分别是短曝光时间、中等曝光时间、长曝光时间,最终通过ISP的算法将三张图像融合成效果比较好的图像。

具体关于HDR的介绍,这里不再赘述,可以参考如下的文章:

HDR是什么|极客笔记 (deepinout.com)

(2)RK3588 ISP支持HDR介绍

通过RK官方的文档可以了解到RK3588 ISP支持HDR,支持2合1,3合1的多帧HDR模式:

 RK3588支持的HDR类型有:Sequential / Framebase HDR 、 Staggered / DOL HDR、DCG HDR。

不支持:SME HDR、BME HDR、 QBC HDR、 Lateral overflow HDR、 Splite-diode pixel HDR。

所以在选择HDR的sensor的时候需要注意,选择RK3588支持的类型。关于更多的HDR类型的描述,这里不再赘述,以后有时间可以在学习一下。

(3)IMX577:HDR调试

这里以调试IMX577 HDR模式为例,分享一下调试HDR过程的经验。

1.IMX577 HDR支持情况

通过sensor的datasheet可以看出IMX577支持DOL-HDR 的模式,符合RK3588的要求,可以在RK3588上面验证。

IMX577支持2帧模式和3帧模式,这里以2帧的模式作为示例进行调试。

注意:RK3588平台接收长短帧只支持VC mode的形式,也就是长帧和短帧图像分别通过MIPI的虚拟通道VC0和VC1输出,ISP接收进行合并。

2.获取HDR配置序列,查阅HDR应用手册,获取HDR相关寄存器

HDR相关的配置与线性模式差异较大,需要sensor的原厂提供对应的初始化序列。

同样的,HDR有长帧和短帧需要控制曝光增益等寄存器,因此需要从应用手册或者datasheet中提取出相关的寄存器控制,添加到驱动。

IMX577添加长短帧控制的寄存器如下:

@@ -67,6 +71,25 @@
 #define IMX577_GAIN_STEP               0x1
 #define IMX577_GAIN_DEFAULT            0x20
 
+#define IMX577_LF_GAIN_REG_H           0x00f0
+#define IMX577_LF_GAIN_REG_L           0x00f1
+#define IMX577_SEF1_GAIN_REG_H         0x00f2
+#define IMX577_SEF1_GAIN_REG_L         0x00f3
+#define IMX577_SEF2_GAIN_REG_H         0x00f4
+#define IMX577_SEF2_GAIN_REG_L         0x00f5
+
+#define IMX577_LF_EXPO_REG_H           0x00ea
+#define IMX577_LF_EXPO_REG_L           0x00eb
+#define IMX577_SEF1_EXPO_REG_H         0x00ec
+#define IMX577_SEF1_EXPO_REG_L         0x00ed
+#define IMX577_SEF2_EXPO_REG_H         0x00ee
+#define IMX577_SEF2_EXPO_REG_L         0x00ef
+
+#define IMX577_RHS1_REG_H              0x00e6
+#define IMX577_RHS1_REG_L              0x00e7
+#define IMX577_RHS2_REG_H              0x00e8
+#define IMX577_RHS2_REG_L              0x00e9
+
 #define IMX577_REG_TEST_PATTERN                0x0600
 #define        IMX577_TEST_PATTERN_ENABLE      0x02
 #define        IMX577_TEST_PATTERN_DISABLE     0x0
@@ -79,14 +102,30 @@
 #define IMX577_FETCH_AGAIN_H(VAL)      (((VAL) >> 8) & 0x03)
 #define IMX577_FETCH_AGAIN_L(VAL)      ((VAL) & 0xFF)
 
+#define IMX577_FETCH_GAIN_H(VAL)       (((VAL) >> 8) & 0xFF)
+#define IMX577_FETCH_GAIN_L(VAL)       ((VAL) & 0xFF)
+
+#define IMX577_FETCH_RHS1_H(VAL)       (((VAL) >> 8) & 0xFF)
+#define IMX577_FETCH_RHS1_L(VAL)       ((VAL) & 0xFF)
+
 #define REG_NULL                       0xFFFF
 
 #define IMX577_REG_VALUE_08BIT         1
 #define IMX577_REG_VALUE_16BIT         2
 #define IMX577_REG_VALUE_24BIT         3
 
+#define IMX577_GROUP_HOLD_REG          0x0104
+#define IMX577_GROUP_HOLD_START                0x01
+#define IMX577_GROUP_HOLD_END          0x00
+
+/* Basic Readout Lines. Number of necessary readout lines in sensor */
+#define BRL_FULL                       3077
+
+#define CIT_MARGIN                     22
+
 #define OF_CAMERA_PINCTRL_STATE_DEFAULT        "rockchip,camera_default"
 #define OF_CAMERA_PINCTRL_STATE_SLEEP  "rockchip,camera_sleep"
+#define OF_CAMERA_HDR_MODE             "rockchip,camera-hdr-mode"

在驱动的support mode中添加对应的HDR mode的支持:

	{
		.width = 4056,
		.height = 3040,
		.max_fps = {
			.numerator = 10000,
			.denominator = 250000,
		},
		.exp_def = 0x0c10,
		.hts_def = 0x11a0,
		.vts_def = 0x0e8a,
		.bpp = 10,
		.bus_fmt = MEDIA_BUS_FMT_SRGGB10_1X10,
		.reg_list = imx577_hdr2_10bit_4056x3040_30fps_regs,
		.link_freq_idx = 0,
		.hdr_mode = HDR_X2,
		.vc[PAD0] = V4L2_MBUS_CSI2_CHANNEL_1,
		.vc[PAD1] = V4L2_MBUS_CSI2_CHANNEL_0,//L->csi wr0
		.vc[PAD2] = V4L2_MBUS_CSI2_CHANNEL_1,
		.vc[PAD3] = V4L2_MBUS_CSI2_CHANNEL_1,//M->csi wr2
	},

3.驱动添加HDR相关的IOCTL接口

包括PREISP_CMD_SET_HDRAE_EXP、RKMODULE_GET_HDR_CFG、RKMODULE_SET_HDR_CFG、RKMODULE_GET_CHANNEL_INFO等接口,因为RK的camera使用标准的V4L2框架,V4L2框架的ctrl没有HDR的控制接口,因此需要添加RK私有的ioctl接口。核心是PREISP_CMD_SET_HDRAE_EXP接口,该接口主要实现对长短帧曝光增益的控制。

	case PREISP_CMD_SET_HDRAE_EXP:
		if (imx577->cur_mode->hdr_mode == HDR_X2)
			ret = imx577_set_hdrae(imx577, arg);
		break;
	case RKMODULE_GET_MODULE_INFO:
		imx577_get_module_inf(imx577, (struct rkmodule_inf *)arg);
		break;
	case RKMODULE_GET_HDR_CFG:
		hdr = (struct rkmodule_hdr_cfg *)arg;
		hdr->esp.mode = HDR_NORMAL_VC;
		hdr->hdr_mode = imx577->cur_mode->hdr_mode;
		break;
	case RKMODULE_SET_HDR_CFG:
		hdr = (struct rkmodule_hdr_cfg *)arg;
		w = imx577->cur_mode->width;
		h = imx577->cur_mode->height;
		for (i = 0; i < ARRAY_SIZE(supported_modes); i++) {
			if (w == supported_modes[i].width &&
			    h == supported_modes[i].height &&
			    supported_modes[i].hdr_mode == hdr->hdr_mode) {
				imx577->cur_mode = &supported_modes[i];
				break;
			}
		}
		if (i == ARRAY_SIZE(supported_modes)) {
			dev_err(&imx577->client->dev,
				"not find hdr mode:%d %dx%d config\n",
				hdr->hdr_mode, w, h);
			ret = -EINVAL;
		} else {
			mode = imx577->cur_mode;
			imx577->cur_vts = mode->vts_def;
			w = mode->hts_def - mode->width;
			h = mode->vts_def - mode->height;
			mutex_lock(&imx577->mutex);
			__v4l2_ctrl_modify_range(imx577->hblank, w, w, 1, w);
			__v4l2_ctrl_modify_range(imx577->vblank, h,
				IMX577_VTS_MAX - mode->height,
				1, h);
			__v4l2_ctrl_s_ctrl(imx577->link_freq, mode->link_freq_idx);
			dst_pixel_rate = (u32)link_freq_items[mode->link_freq_idx] /
					mode->bpp * 2 * lane_num;
			__v4l2_ctrl_s_ctrl_int64(imx577->pixel_rate,
						 dst_pixel_rate);
			mutex_unlock(&imx577->mutex);
		}
		break;

4.根据手册指导,完善HDR曝光增益控制的函数

根据IMX577的手册描述,HDR模式下,长短帧的曝光增益的限制条件如下:

驱动代码需要根据如上的限制条件,对曝光增益的控制进行限制,具体如下:

+static int imx577_set_hdrae(struct imx577 *imx577,
+                           struct preisp_hdrae_exp_s *ae)
+{
+       struct i2c_client *client = imx577->client;
+       u32 l_exp_time, m_exp_time, s_exp_time;
+       u32 l_a_gain, m_a_gain, s_a_gain;
+       int ret = 0;
+       u32 fll, dol_cit1, dol_cit2, dol_off2;
+
+       if (!imx577->has_init_exp && !imx577->streaming) {
+               imx577->init_hdrae_exp = *ae;
+               imx577->has_init_exp = true;
+               dev_dbg(&imx577->client->dev, "imx577 is not streaming, save hdr ae!\n");
+               return ret;
+       }
+       l_exp_time = ae->long_exp_reg;
+       m_exp_time = ae->middle_exp_reg;
+       s_exp_time = ae->short_exp_reg;
+       l_a_gain = ae->long_gain_reg;
+       m_a_gain = ae->middle_gain_reg;
+       s_a_gain = ae->short_gain_reg;
+       dev_dbg(&client->dev,
+               "rev exp req: L_exp: 0x%x, 0x%x, M_exp: 0x%x, 0x%x S_exp: 0x%x, 0x%x\n",
+               l_exp_time, m_exp_time, s_exp_time,
+               l_a_gain, m_a_gain, s_a_gain);
+
+       if (imx577->cur_mode->hdr_mode == HDR_X2) {
+               l_a_gain = m_a_gain;
+               l_exp_time = m_exp_time;
+       }
+
+       ret = imx577_write_reg(client, IMX577_GROUP_HOLD_REG,
+               IMX577_REG_VALUE_08BIT, IMX577_GROUP_HOLD_START);
+       /* gain effect n+1 */
+       if (l_a_gain > 0x160)
+               l_a_gain = 0x160;
+       if (l_a_gain < 0x10)
+               l_a_gain = 0x10;
+       if (s_a_gain > 0x160)
+               s_a_gain = 0x160;
+       if (s_a_gain < 0x10)
+               s_a_gain = 0x10;
+       l_a_gain = 1024 - 1024 * 16 / l_a_gain;
+       s_a_gain = 1024 - 1024 * 16 / s_a_gain;
+
+       ret |= imx577_write_reg(client, IMX577_LF_GAIN_REG_H,
+               IMX577_REG_VALUE_08BIT, IMX577_FETCH_GAIN_H(l_a_gain));
+       ret |= imx577_write_reg(client, IMX577_LF_GAIN_REG_L,
+               IMX577_REG_VALUE_08BIT, IMX577_FETCH_GAIN_L(l_a_gain));
+       ret |= imx577_write_reg(client, IMX577_SEF1_GAIN_REG_H,
+               IMX577_REG_VALUE_08BIT, IMX577_FETCH_GAIN_H(s_a_gain));
+       ret |= imx577_write_reg(client, IMX577_SEF1_GAIN_REG_L,
+               IMX577_REG_VALUE_08BIT, IMX577_FETCH_GAIN_L(s_a_gain));
+
+       fll = imx577->cur_vts;
+       dol_cit1 = l_exp_time/* >> 1*/;
+       dol_cit2 = s_exp_time/* >> 1*/;
+
+       /*dol_cit1 dol_cit2 dol_off2 should be even*/
+       if (dol_cit1 < 2)
+               dol_cit1 = 2;
+       else if (dol_cit1 > fll - 2 * CIT_MARGIN - 2)
+               dol_cit1 = fll - 2 * CIT_MARGIN - 2;
+       dol_cit1 &= (~0x1);
+       
+       if (dol_cit2 < 2)
+               dol_cit2 = 2;
+       else if (dol_cit2 > fll - BRL_FULL - CIT_MARGIN)
+               dol_cit2 = fll - BRL_FULL - CIT_MARGIN;
+       dol_cit2 &= (~0x1);
+
+       dol_off2 = (dol_cit2 + CIT_MARGIN) & (~0x1);
+       if (dol_off2 < dol_cit2 + CIT_MARGIN)
+               dol_off2 = (dol_cit2 + CIT_MARGIN) & (~0x1);
+       else if (dol_off2 > fll - BRL_FULL)
+               dol_off2 = (fll - BRL_FULL) & (~0x1);
+
+       dev_dbg(&client->dev,
+               "l_exp_time=%d,s_exp_time=%d,fll=%d,rhs1=%d,l_a_gain=%d,s_a_gain=%d\n",
+               l_exp_time, s_exp_time, fll, dol_off2, l_a_gain, s_a_gain);
+
+       ret |= imx577_write_reg(client,
+               IMX577_RHS1_REG_L,
+               IMX577_REG_VALUE_08BIT,
+               IMX577_FETCH_RHS1_L(dol_off2));
+       ret |= imx577_write_reg(client,
+               IMX577_RHS1_REG_H,
+               IMX577_REG_VALUE_08BIT,
+               IMX577_FETCH_RHS1_H(dol_off2));
+
+       ret |= imx577_write_reg(client,
+               IMX577_SEF1_EXPO_REG_L,
+               IMX577_REG_VALUE_08BIT,
+               IMX577_FETCH_EXP_L(dol_cit2));
+       ret |= imx577_write_reg(client,
+               IMX577_SEF1_EXPO_REG_H,
+               IMX577_REG_VALUE_08BIT,
+               IMX577_FETCH_EXP_H(dol_cit2));
+       ret |= imx577_write_reg(client,
+               IMX577_LF_EXPO_REG_L,
+               IMX577_REG_VALUE_08BIT,
+               IMX577_FETCH_EXP_L(dol_cit1));
+       ret |= imx577_write_reg(client,
+               IMX577_LF_EXPO_REG_H,
+               IMX577_REG_VALUE_08BIT,
+               IMX577_FETCH_EXP_H(dol_cit1));
+
+       ret |= imx577_write_reg(client, IMX577_GROUP_HOLD_REG,
+               IMX577_REG_VALUE_08BIT, IMX577_GROUP_HOLD_END);
+
+       return ret;
+}

 其中使用了group hold的寄存器,该寄存器的作用:让写寄存器的同时生效,避免长帧的寄存器写完,短帧还没开始写,长帧就已经生效了。

5.驱动其他接口的增加:

imx577_enum_frame_interval:该接口最后的reverse需要上报对应的HDR mode。

@@ -1329,6 +1910,7 @@ static int imx577_enum_frame_interval(struct v4l2_subdev *sd,
        fie->width = supported_modes[fie->index].width;
        fie->height = supported_modes[fie->index].height;
        fie->interval = supported_modes[fie->index].max_fps;
+       fie->reserved[0] = supported_modes[fie->index].hdr_mode;
 
        return 0;
 }

imx577_g_mbus_config:配置使用的MIPI通道数量。

@@ -1337,12 +1919,15 @@ static int imx577_g_mbus_config(struct v4l2_subdev *sd, unsigned int pad,
                                struct v4l2_mbus_config *config)
 {
        struct imx577 *imx577 = to_imx577(sd);
+       const struct imx577_mode *mode = imx577->cur_mode;
        u32 lane_num = imx577->bus_cfg.bus.mipi_csi2.num_data_lanes;
        u32 val = 0;
 
        val = 1 << (lane_num - 1) |
                V4L2_MBUS_CSI2_CHANNEL_0 |
                V4L2_MBUS_CSI2_CONTINUOUS_CLOCK;
+       if (mode->hdr_mode != NO_HDR)
+               val |= V4L2_MBUS_CSI2_CHANNEL_1;
 
        config->type = V4L2_MBUS_CSI2_DPHY;
        config->flags = val;

6.dts配置与xml配置

dts需要添加如下:

rockchip,camera-hdr-mode = <5>; // 0: no_hdr; 5: hdr2; 6: hdr3

xml添加配置:

            <isoAnalogGain1 value="75"/> <!--Pseudo ISO corresponding analog gain value 1.0. -->
            <cITMaxMargin value="10"/> <!--coarse integration time max margin -->
            <aiq.workingMode value="HDR2"/> <!-- NORMAL or HDR2 or HDR3 -->

(4)IMX577:HDR调试与问题排查

1.抓取长短帧的raw图

先设置为非紧凑模式:

echo 0 0 1 0 > /sys/devices/platform/rkcif-mipi-lvds2/compact_test

抓取video0长帧raw:

v4l2-ctl -d /dev/video0 --set-fmt-video=width=4056,height=3040,pixelformat='BG10' --stream-mmap=3 --stream-skip=4 --stream-to=/data/out_long.raw --stream-count=1 --stream-poll

抓取video1短帧raw:

v4l2-ctl -d /dev/video1 --set-fmt-video=width=4056,height=3040,pixelformat='BG10' --stream-mmap=3 --stream-skip=4 --stream-to=/data/out_short.raw --stream-count=1 --stream-poll

2.效果异常问题排查

调试过程中遇到了一个致命的问题,发现HDR融合后的效果不佳,经过排查是sensor抓到的长短帧的亮度不一致(此处:长短帧抓到的raw本身是亮度不一样的,RK同事可以使用仿真工具将曝光比换算回去,得出的图像发现长短帧亮度依旧不一致),因此是sensor的驱动给出来的图像就有问题。

排查HDR的曝光增益设置:

CIT_MARGIN参数固定为22.

 RBL参数,固定为3077:

 长短帧曝光增益的限制条件如下:

 如上图所示,默认的序列FLL也就是VTS为3102,那么短帧曝光就始终被限制在2,因此导致短帧曝光无法调节,导致效果异常的问题。

解决方式:提高VTS,增加短帧曝光的调整范围,但是增加VTS,就会导致帧率的下降,需要取舍。

(5)总结

文章主要介绍了sensor驱动增加HDR模式的调试,同时也分享了我在IMX577 HDR调试过程中遇到的一个比较严重的问题,并对问题的排查与解决进行分享,希望对正在调试HDR的同学有所帮助。

  • 7
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

人生苦短,我想躺平

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值