5.17.6. HDR Sensor Bring-Up

重要提示:当接入 HDR Sensor 时,VIN 和 ISP 的连接方式只能选择 online,由于 online 模式独占 ISP 资源,所以支持 1 路。

  • 本文Sony imx415 DOL2 为例,说明在 X5 平台适配 HDR 模式 Camera Sensor 的完整流程。

  • Sony sensor 的 HDR 实现方式是Sensor 在一个周期内,交替输出不同曝光时间图像数据

  • 流程包括驱动实现、App 配置程序验证, 通用概念与 dts 配置阅读 Camera 调试指南

源码位置

  • 驱动接口实现hbre/camsys/libcam/src/sensor/imx415/imx415_utility.c

  • 增益表与 Setting 配置hbre/camsys/libcam/src/sensor/imx415/inc/imx415_setting.hgain_lut、init/stream_on/stream_off 寄存器数组)


5.17.6.1. dts配置

  • 关于dts配置和sensor的id识别验证参考修改平台设备树

  • DOL2 模式的 dts 配置与 Linear 模式一致,无额外修改。


5.17.6.2. 驱动

sensor_module_t 与文件命名

  • 文件名:imx415_utility.c;结构体/模块名:imx415;库名:libimx415.so.1.0.0,部署板端 /usr/hobot/lib/sensor/

  • 实现接口:init、deinit、start、stop、power_on、power_off、aexp_gain_control、aexp_line_control、userspace_control。

  • HDR 模式与 Linear 模式共用同一个 sensor_module_t,通过 sensor_mode 区分不同分支。

#ifdef CAMERA_FRAMEWORK_HBN
SENSOR_MODULE_F(imx415, CAM_MODULE_FLAG_A16D8);
sensor_module_t imx415 = {
        .module = SENSOR_MNAME(imx415),
#else
sensor_module_t imx415 = {
        .module = "imx415",
#endif
        .init = sensor_init,
        .start = sensor_start,
        .stop = sensor_stop,
        .deinit = sensor_deinit,
        .power_on = sensor_poweron,
        .power_off = sensor_poweroff,
        .aexp_gain_control = sensor_aexp_gain_control,
        .aexp_line_control = sensor_aexp_line_control,
        .userspace_control = sensor_userspace_control,
};

power_on

  1. power_on 通过 X5 GPIO 控制 sensor 上电,需结合 spec 上电时序。

  2. sensor_poweron 一般在 sensor_init 中调用,只需要控制 XCLR 即可。

  3. HDR 模式与 Linear 模式流程完全一致,以下为 imx415 power_on 的代码实现:

../../_images/screenshot-20260422-193603.png

static int sensor_poweron(sensor_info_t *sensor_info)
{
        int gpio, ret = RET_OK;
        vin_dbg("%s gpio_num = %d \n", sensor_info->sensor_name, sensor_info->gpio_num);
        if(sensor_info->gpio_num > 0) {
                for(gpio = 0; gpio < sensor_info->gpio_num; gpio++) {
                        vin_dbg("%s gpio_pin[%d] = %d \n", sensor_info->sensor_name, gpio, sensor_info->gpio_pin[gpio]);
                        if(sensor_info->gpio_pin[gpio] != -1) {
                                ret = vin_power_ctrl(sensor_info->gpio_pin[gpio],
                                                sensor_info->gpio_level[gpio]);
                                usleep(100 * 1000);  // 100ms
                                ret |= vin_power_ctrl(sensor_info->gpio_pin[gpio],
                                                1 - sensor_info->gpio_level[gpio]);
                                if(ret < 0) {
                                        vin_err("vin_power_ctrl fail\n");
                                        return -HB_CAM_SENSOR_POWERON_FAIL;
                                }
                                usleep(100 * 1000);  // 100ms
                        }
                }
        }
        return ret;
}

power_off

  1. power_off 通过 X5 GPIO 控制 sensor 下电,需结合 spec 上电时序。

  2. sensor_poweroff 一般在 sensor_deinit 中调用,只需要控制 XCLR 即可,以下为 imx415 power_off 的代码实现:

../../_images/screenshot-20260422-193628.png

static int sensor_poweroff(sensor_info_t *sensor_info)
{
        int gpio, ret = RET_OK;
        if(sensor_info->gpio_num > 0) {
                for(gpio = 0; gpio < sensor_info->gpio_num; gpio++) {
                        if(sensor_info->gpio_pin[gpio] != -1) {
                                ret = vin_power_ctrl(sensor_info->gpio_pin[gpio],
                                        sensor_info->gpio_level[gpio]);
                                if(ret < 0) {
                                        vin_err("vin_power_ctrl fail\n");
                                        return -HB_CAM_SENSOR_POWEROFF_FAIL;
                                }
                        }
                }
        }
        return ret;
}

init

  1. 将 sensor 初始化寄存器列表通过 i2c 写函数写入 sensor;HDR 模式使用 DOL2 专用的 setting 数组。

  2. imx415_dol2_data_init 用于填充 turning_data 信息。

  3. sensor_init 调用时机为 hbn_camera_attach_to_vin。

  4. HDR 模式通过 sensor_mode == DOL2_M独立分支。

static int sensor_init(sensor_info_t *sensor_info)
{
        int ret = RET_OK;
        int setting_size = 0;

        ret = sensor_poweron(sensor_info);
        if (ret < 0) {
                vin_err("%d : sensor reset %s fail\n", __LINE__, sensor_info->sensor_name);
                return ret;
        }
        switch(sensor_info->sensor_mode) {
        case NORMAL_M:
                // ... linear 模式初始化(略)...
                break;
        case DOL2_M:
                vin_info("imx415 in dol2/hdr mode\n");
                setting_size = sizeof(imx415_init_3840x2160_dol2_4lane_setting) / sizeof(uint32_t) / 2;
                ret = vin_write_array(sensor_info->bus_num, sensor_info->sensor_addr, REG_WIDTH,
                                setting_size, imx415_init_3840x2160_dol2_4lane_setting);
                if (ret < 0) {
                        vin_err("%d : init %s fail\n", __LINE__, sensor_info->sensor_name);
                        return -HB_CAM_I2C_WRITE_FAIL;
                }
                ret = imx415_dol2_data_init(sensor_info);
                if (ret < 0) {
                        vin_err("%d : hdr data init %s fail\n", __LINE__, sensor_info->sensor_name);
                        return -HB_CAM_INIT_FAIL;
                }
                break;
        default:
                vin_err("%d not support mode %d\n", __LINE__, sensor_info->sensor_mode);
                ret = -HB_CAM_INIT_FAIL;
                break;
        }
        return ret;
}

deinit

  1. deinit 一般用于 sensor 的初始化,直接调用 power_off 下电即可。

  2. sensor_deinit 调用时机为 hbn_camera_destroy 或者 hbn_camera_detach_from_vin。

  3. HDR 模式与 Linear 模式一致。

static int sensor_deinit(sensor_info_t *sensor_info)
{
        int ret = RET_OK;
        ret = sensor_poweroff(sensor_info);
        if (ret < 0) {
                vin_err("%d : deinit %s fail\n", __LINE__, sensor_info->sensor_name);
                return ret;
        }
        return ret;
}

start

  1. start 实现下发开流寄存器 0x3000 为 0x00、0x3002 为 0x00,使 sensor 出流。

  2. sensor_start 调用时机上层调用 hbn_vflow_start。

  3. HDR 模式与 Linear 模式使用相同的 stream_on 寄存器。

../../_images/screenshot-20260422-214020.png

../../_images/screenshot-20260422-214035.png

static int sensor_start(sensor_info_t *sensor_info)
{
        int ret = RET_OK;
        int setting_size = 0;

        switch (sensor_info->sensor_mode) {
        case NORMAL_M:
        case DOL2_M:
                setting_size = sizeof(imx415_stream_on_setting) / sizeof(uint32_t) / 2;
                ret = vin_write_array(sensor_info->bus_num, sensor_info->sensor_addr, 2,
                                      setting_size, imx415_stream_on_setting);
                if (ret < 0) {
                        vin_err("start %s fail\n", sensor_info->sensor_name);
                        return ret;
                }
                break;
        }
        return ret;
}

stop

  1. stop 实现下发关流寄存器 0x3000 为 0x01、0x3002 为 0x01,使 sensor 关流。

  2. sensor_stop 调用时机上层调用 hbn_vflow_stop。

  3. HDR 模式与 Linear 模式使用相同的 stream_off 寄存器。

static int sensor_stop(sensor_info_t *sensor_info)
{
        int ret = RET_OK;
        int setting_size = 0;

        setting_size = sizeof(imx415_stream_off_setting) / sizeof(uint32_t) / 2;
        vin_info("%s sensor stop\n", sensor_info->sensor_name);
        ret = vin_write_array(sensor_info->bus_num, sensor_info->sensor_addr, REG_WIDTH,
                        setting_size, imx415_stream_off_setting);
        if (ret < 0) {
                vin_err("start %s fail\n", sensor_info->sensor_name);
                return -HB_CAM_I2C_WRITE_FAIL;
        }
        return ret;
}

ISP 配置与 dol2_data_init

下面关于 imx415 的 hdr 的一些名词解释:

../../_images/screenshot-20260422-165005.png

下面关于 bayerpattern 和 bayer_start的描述:

../../_images/screenshot-20260422-221051.png

在 DOL2 模式下,IMX415 需要一个周期交替输出 LEF(长曝光帧) 和 SEF1(短曝光帧) 的数据。占用时间为 VMAX × 2 ../../_images/screenshot-20260422-163831.png

../../_images/screenshot-20260422-162608.png

imx415_dol2_data_init填充 tuning 参数

  • 需要从 sensor 读取 VMAX(0x3024-0x3026)和 RHS1(0x3060-0x3062),计算 FSC = VMAX × 2;

  • exposure_time_long_max / exposure_time_max 根据SPEC中 DOL2 公式计算;

  • gain_lut 使用 turning_data.dol2.again_lut

  • 设置 turning_type = 6

DOL2 曝光时间公式来自图:

咨询 sensor FAE 后 Toffset 可以忽略不计,可知

LEF 曝光行数:  t_LEF  = FSC  - SHR0,  FSC = VMAX × 2
SEF1 曝光行数: t_SEF1 = RHS1 - SHR1

关键参数配置:

  • lines_per_second = FSC * sensor_info->fps(FSC = VMAX × 2)

  • exposure_time_long_max = FSC - (RHS1 + 9) LEF 最大曝光

  • exposure_time_max = RHS1 - 9 SEF1 最大曝光

  • exposure_time_min = 8

  • analog_gain_max = 255 与 gain_lut 最大索引一致

  • digital_gain_max = 0

  • sensor_data_bayer_fill(..., 10, BAYER_START_GB, BAYER_PATTERN_RGGB)sensor_data_bits_fill(..., 12)

static int imx415_dol2_data_init(sensor_info_t *sensor_info)
{
        int ret = RET_OK;
        sensor_turning_data_t turning_data;
        uint32_t *stream_on = turning_data.stream_ctrl.stream_on;
        uint32_t *stream_off = turning_data.stream_ctrl.stream_off;

        int val_l = 0, val_m = 0, val_h = 0;
        uint32_t Vmax = 0, rhs1 = 0, fsc = 0;

        val_l = hb_vin_i2c_read_reg16_data8(sensor_info->bus_num, sensor_info->sensor_addr, IMX415_VMAX);
        val_m = hb_vin_i2c_read_reg16_data8(sensor_info->bus_num, sensor_info->sensor_addr, IMX415_VMAX + 1);
        val_h = hb_vin_i2c_read_reg16_data8(sensor_info->bus_num, sensor_info->sensor_addr, IMX415_VMAX + 2);
        Vmax = ((val_h & 0x0F) << 16) | (val_m << 8) | val_l;

        val_l = hb_vin_i2c_read_reg16_data8(sensor_info->bus_num, sensor_info->sensor_addr, IMX415_RHS1);
        val_m = hb_vin_i2c_read_reg16_data8(sensor_info->bus_num, sensor_info->sensor_addr, IMX415_RHS1 + 1);
        val_h = hb_vin_i2c_read_reg16_data8(sensor_info->bus_num, sensor_info->sensor_addr, IMX415_RHS1 + 2);
        rhs1 = ((val_h & 0x0F) << 16) | (val_m << 8) | val_l;

        fsc = Vmax * 2;

        memset(&turning_data, 0, sizeof(sensor_turning_data_t));

        turning_data.bus_num = sensor_info->bus_num;
        turning_data.bus_type = sensor_info->bus_type;
        turning_data.port = sensor_info->port;
        turning_data.reg_width = sensor_info->reg_width;
        turning_data.mode = sensor_info->sensor_mode;
        turning_data.sensor_addr = sensor_info->sensor_addr;
        strncpy(turning_data.sensor_name, sensor_info->sensor_name,
                sizeof(turning_data.sensor_name));
        turning_data.sensor_data.turning_type = 6;
        turning_data.sensor_data.active_width = sensor_info->width;
        turning_data.sensor_data.active_height = sensor_info->height;

        turning_data.sensor_data.lines_per_second = fsc * sensor_info->fps;
        turning_data.sensor_data.exposure_time_long_max = fsc - (rhs1 + 9);
        turning_data.sensor_data.exposure_time_max = rhs1 - 9;
        turning_data.sensor_data.exposure_time_min = 8;
        turning_data.sensor_data.analog_gain_max = 255;
        turning_data.sensor_data.digital_gain_max = 0;

        sensor_data_bayer_fill(&turning_data.sensor_data, 10, (uint32_t)BAYER_START_GB, (uint32_t)BAYER_PATTERN_RGGB);
        sensor_data_bits_fill(&turning_data.sensor_data, 12);

        turning_data.stream_ctrl.data_length = 1;
        memcpy(stream_on, imx415_stream_on_setting, sizeof(imx415_stream_on_setting));
        memcpy(stream_off, imx415_stream_off_setting, sizeof(imx415_stream_off_setting));

        turning_data.dol2.again_lut = malloc(256 * sizeof(uint32_t));
        if (turning_data.dol2.again_lut != NULL) {
                memset(turning_data.dol2.again_lut, 0xff, 256 * sizeof(uint32_t));
                memcpy(turning_data.dol2.again_lut, imx415_gain_lut, sizeof(imx415_gain_lut));
        }

        ret = ioctl(sensor_info->sen_devfd, SENSOR_TURNING_PARAM, &turning_data);

        if (turning_data.dol2.again_lut) {
                free(turning_data.dol2.again_lut);
                turning_data.dol2.again_lut = NULL;
        }
        if (ret < 0) {
                vin_err("%s sync gain lut ioctl fail %d\n", sensor_info->sensor_name, ret);
                return -RET_ERROR;
        }
        return ret;
}

aexp_gain_control

DOL2 模式需要分别控制 LEF 和 SEF1 两路增益:

  • again[0] → LEF 增益,写入 GAIN_PGC0 (0x3090)

  • again[1] → SEF1 增益,写入 GAIN_PGC1 (0x3092)

    ../../_images/screenshot-20260422-163403.png

static int sensor_aexp_gain_control(hal_control_info_t *info, uint32_t mode, uint32_t *again, uint32_t *dgain, uint32_t gain_num)
{
        const uint16_t AGAIN = GAIN_PGC0;
        const uint16_t S_AGAIN = GAIN_PGC1;
        char again_reg_value = 0, s_again_reg_value = 0;
        int again_index = 0, s_again_index = 0;

        if (mode == NORMAL_M) {
                if (again[0] >= sizeof(imx415_gain_lut)/sizeof(uint32_t))
                        again_index = sizeof(imx415_gain_lut)/sizeof(uint32_t) - 1;
                else
                        again_index = again[0];

                again_reg_value = (imx415_gain_lut[again_index] >> 0) & 0xFF;
                set_gain_registers(info, AGAIN, again_reg_value);
        } else if (mode == DOL2_M) {
                if (again[0] >= sizeof(imx415_gain_lut)/sizeof(uint32_t))
                        again_index = sizeof(imx415_gain_lut)/sizeof(uint32_t) - 1;
                else
                        again_index = again[0];
                if (again[1] >= sizeof(imx415_gain_lut)/sizeof(uint32_t))
                        s_again_index = sizeof(imx415_gain_lut)/sizeof(uint32_t) - 1;
                else
                        s_again_index = again[1];

                again_reg_value = (imx415_gain_lut[again_index] >> 0) & 0xFF;
                s_again_reg_value = (imx415_gain_lut[s_again_index] >> 0) & 0xFF;

                set_gain_registers(info, AGAIN, again_reg_value);
                set_gain_registers(info, S_AGAIN, s_again_reg_value);
        } else {
                vin_err(" unsupport mode %d\n", mode);
        }
        return 0;
}

aexp_line_control

aexp_line_control 在 DOL2 模式需要同时设置 LEF 和 SEF1 两路曝光,主要负责:

  1. 接收 ISP 3A 算法下发曝光数:line[0](LEF)、line[1](SEF1)

  2. 曝光转换为 SHR0 和 SHR1 寄存器

  3. 进行边界检查和奇偶对齐

  4. 通过 i2c 下发给 sensor

../../_images/screenshot-20260422-162608.png

DOL2 曝光公式:

SHR0 = FSC  - line[0]     (LEF,  FSC = VMAX × 2)
SHR1 = RHS1 - line[1]     (SEF1)

约束:SHR0 为偶数(2n)   (RHS1 + 9)  SHR0  (FSC - 8)
      SHR1 为奇数(2n+1) 9  SHR1  (RHS1 - 8)

Linear 模式曝光公式:

SHR0 = VMAX - line[0]

约束:8  SHR0  (VMAX - 4)
static int sensor_aexp_line_control(hal_control_info_t *info, uint32_t mode, uint32_t *line, uint32_t line_num)
{
        uint32_t tmp = 0;
        char temp0 = 0, temp1 = 0, temp2 = 0;
        int val_l = 0, val_m = 0, val_h = 0;
        uint32_t Vmax = 0;

        val_l = hb_vin_i2c_read_reg16_data8(info->bus_num, info->sensor_addr, IMX415_VMAX);
        val_m = hb_vin_i2c_read_reg16_data8(info->bus_num, info->sensor_addr, IMX415_VMAX + 1);
        val_h = hb_vin_i2c_read_reg16_data8(info->bus_num, info->sensor_addr, IMX415_VMAX + 2);
        Vmax = ((val_h & 0x0F) << 16) | (val_m << 8) | val_l;

        if ((mode == NORMAL_M) || (line_num == 1)) {
                int shr0 = Vmax - line[0];
                if (shr0 < 8)              shr0 = 8;
                if (shr0 > (int)(Vmax - 4)) shr0 = Vmax - 4;

                tmp = shr0;
                temp2 = (tmp >> 16) & 0x0F;
                vin_i2c_write8(info->bus_num, 16, info->sensor_addr, IMX415_SHR0 + 2, temp2);
                temp1 = (tmp >> 8) & 0xFF;
                vin_i2c_write8(info->bus_num, 16, info->sensor_addr, IMX415_SHR0 + 1, temp1);
                temp0 = (tmp & 0xFF);
                vin_i2c_write8(info->bus_num, 16, info->sensor_addr, IMX415_SHR0, temp0);
        } else if (mode == DOL2_M) {
                uint32_t rhs1 = 0, fsc = 0;
                int shr0 = 0, shr1 = 0;

                val_l = hb_vin_i2c_read_reg16_data8(info->bus_num, info->sensor_addr, IMX415_RHS1);
                val_m = hb_vin_i2c_read_reg16_data8(info->bus_num, info->sensor_addr, IMX415_RHS1 + 1);
                val_h = hb_vin_i2c_read_reg16_data8(info->bus_num, info->sensor_addr, IMX415_RHS1 + 2);
                rhs1 = ((val_h & 0x0F) << 16) | (val_m << 8) | val_l;

                fsc = Vmax * 2;
                shr0 = fsc - line[0];
                shr1 = rhs1 - line[1];

                if (shr1 < 9)              shr1 = 9;
                if (shr1 > (int)(rhs1 - 8)) shr1 = rhs1 - 8;
                if (shr0 < (int)(rhs1 + 9)) shr0 = rhs1 + 9;
                if (shr0 > (int)(fsc - 8))   shr0 = fsc - 8;

                shr1 |= 0x01;               // SHR1 强制为奇数 (2n+1)
                shr0 = (shr0 >> 1) << 1;    // SHR0 强制为偶数 (2n)

                // 写 SHR0 (3字节 LSB first: 0x3050, 0x3051, 0x3052)
                tmp = shr0;
                vin_i2c_write8(info->bus_num, 16, info->sensor_addr, IMX415_SHR0 + 2, (tmp >> 16) & 0x0F);
                vin_i2c_write8(info->bus_num, 16, info->sensor_addr, IMX415_SHR0 + 1, (tmp >> 8) & 0xFF);
                vin_i2c_write8(info->bus_num, 16, info->sensor_addr, IMX415_SHR0,     tmp & 0xFF);

                // 写 SHR1 (3字节 LSB first: 0x3054, 0x3055, 0x3056)
                tmp = shr1;
                vin_i2c_write8(info->bus_num, 16, info->sensor_addr, IMX415_SHR1 + 2, (tmp >> 16) & 0x0F);
                vin_i2c_write8(info->bus_num, 16, info->sensor_addr, IMX415_SHR1 + 1, (tmp >> 8) & 0xFF);
                vin_i2c_write8(info->bus_num, 16, info->sensor_addr, IMX415_SHR1,     tmp & 0xFF);
        } else {
                vin_err(" unsupport mode %d\n", mode);
                return -1;
        }
        return 0;
}

userspace_control

  • 这里 sensor_userspace_control 用于 Gain Control 与 Exposure Control 开关。

  • 用于 hbplayer 调试排查 flicker 或画面异常,可开关 HAL_GAIN_CONTROL / HAL_LINE_CONTROL 确认问题。

  • HDR 模式与 Linear 模式一致。

static int sensor_userspace_control(uint32_t port, uint32_t *enable)
{
        vin_info("enable userspace gain control and line control\n");
        *enable = HAL_GAIN_CONTROL | HAL_LINE_CONTROL;
        return 0;
}

驱动部署

  1. ./bd.sh hbre camsys/libcam 编译。

  2. out/deploy/hbre/lib/sensor/libimx415.so.1.0.0 拷贝到板端 /usr/hobot/lib/sensor/


5.17.6.3. App 配置

  • 路径 app/samples/platform_samples/vp_sensors/imx415/ 中为 imx415 DOL2 添加配置。

  • HTS/VTS 可寄存器 0x3028/0x3029、0x3024~0x3026 读取咨询 Sensor FAE 提供或者使用示波器测量,测量方法参考 mipi-参数确定

  • mipiclk 一般询问 Sensor FAE 即可,计算方法参考 MIPI CLK

  • 其他通用配置,参考文档 数据结构。 进行配置即可

vp_sensor 配置文件:dol2_3840x2160_raw10_30fps_4lane.c

  • 配置文件路径:imx415/dol2_3840x2160_raw10_30fps_4lane.c

  • 配置结构体名:imx415_dol2_3480x2160_raw10_30fps_4lane(需在 vp_sensor_config_list 中注册)。

  • 当前示例RAW10 输出;datatype/format 配置为 0x2B。

DOL2 模式相比 Linear 模式多处关键差异,以下模块说明:

MIPI 配置

DOL2 模式下,sensor 通过 Virtual Channel同一 MIPI 链路传输 LEF(VC0)和 SEF1(VC1),SoC 端需要配置 2 个通道分别接收:

static mipi_config_t imx415_mipi_config = {
        .rx_enable = 1,
        .rx_attr = {
                .phy = 0,
                .lane = 4,
                .datatype = RAW10,
                .fps = 30,
                .mclk = 1,
                .mipiclk = 7128,
                .width = 3840,
                .height = 2160,
                .linelenth = 6400,
                .framelenth = 4700,
                .settle = 10,
                .channel_num = 2,          // DOL2: 2 通道(Linear 为 1)
                .channel_sel = {0, 1},     // VC0=LEF, VC1=SEF1
        },
        .rx_ex_mask = 0x40,
        .rx_attr_ex = {
                .stop_check_instart = 1,
        }
};

与 Linear 模式差异:

  • channel_num = 2:DOL2 需要接收 VC0 和 VC1 两个虚拟通道数据,Linear 为 1

  • channel_sel = {0, 1}:指定接收 VC0 和 VC1

  • framelenth:DOL2 与 Linear 的不同,需根据实际 VMAX 配置确认

Camera 配置

static camera_config_t imx415_camera_config = {
        .name = "imx415",
        .addr = 0x1a,
        .sensor_mode = DOL2_M,                    //DOL2 模式(Linear 为 NORMAL_M)
        .fps = 30,
        .format = RAW10,
        .width = 3840,
        .height = 2160,
        .gpio_enable_bit = 0x01,
        .gpio_level_bit = 0x00,
        .mipi_cfg = &imx415_mipi_config,
        .calib_lname = "imx415_hdr_tuning.json",  //HDR 专用 tuning 文件
};

与 Linear 模式差异:

  • sensor_mode = DOL2_M:决定驱动 init/start/gain/line 走 DOL2 分支

  • calib_lname:需要 HDR 专用的 tuning 文件

VIN 配置

VIN 配置是 DOL2 与 Linear 差异最大部分:

static vin_node_attr_t imx415_vin_node_attr = {
        .cim_attr = {
                .mipi_rx = 0,
                .vc_index = 0,             // 从 VC0 开始
                .ipi_channel = 2,          // DOL2: 2 个 IPI 通道(Linear 为 1)
                .cim_isp_flyby = 1,        // DOL2只支持online 模式
                .func = {
                        .enable_frame_id = 1,
                        .set_init_frame_id = 0,
                        .hdr_mode = DOL_2,  //通知 ISP 做两帧合成(Linear 为 NOT_HDR)
                        .time_stamp_en = 0,
                },
        },
};

关键参数说明(参考 VIN API 数据结构):

参数 Linear 值 DOL2 值 说明
ipi_channel 1 2 DOL2 需要 2 个 IPI 通道分别接收 VC0(LEF)和 VC1(SEF1)
cim_isp_flyby 0 1 DOL2 通常使用 VIN online ISP(PASSTHROUGH_MODE)
hdr_mode NOT_HDR (0) DOL_2 (1) 0: 不合成;1: SoC 侧合成;2: 三帧合成(X5 不支持)

VIN 输出通道配置:

static vin_ochn_attr_t imx415_vin_ochn_attr = {
        .ddr_en = 0,                   //online 模式下为 0
        .ochn_attr_type = VIN_BASIC_ATTR,
        .vin_basic_attr = {
                .format = RAW10,
                .wstride = (SENSOR_WIDTH) * 2,
        },
};

ISP 配置

ISP 需要设置为 DOL2 合成模式,与 VIN online 配合:

static isp_attr_t imx415_isp_attr = {
        .input_mode = PASSTHROUGH_MODE,  // online
        .sensor_mode = ISP_DOL2_M,       // DOL2 合成模式
        .tile_mode = 0,
        .crop = {
                .x = 0, .y = 0,
                .h = 2160, .w = 3840,
        },
};

关键参数说明(参考 HBN API 数据结构):

参数 Linear 值 DOL2 值 说明
input_mode DDR_MODE (2) PASSTHROUGH_MODE (0) 与 cim_isp_flyby=1 对应,VIN 和 ISP 间经 DDR
sensor_mode ISP_NORMAL_M (0) ISP_DOL2_M (1) ISP 内部做 DOL2 两帧 HDR 合成

注意:VIN online ISP 时,hbn_vflow_bind_vnode绑定方式src_out_channel=1, dst_input_channel=0,与 Linear offline 模式src_out_channel=0 不同。

完整参数汇总

配置 参数名 / 位置 取值说明
顶层 config_file "dol2_3840x2160_raw10_30fps_4lane.c"
sensor_name "imx415-30fps-4lane-dol2"
chip_id_reg / chip_id 0x3F12 / 0x0514
sensor_i2c_addr_list {0x1A}
support_sensor_mode {DOL2_M}
MIPI lane 4
datatype RAW10 (0x2B)
fps 30
mipiclk 7128(Mbps)
width / height 3840 / 2160
linelenth / framelenth 6400 / 4700
settle 10
channel_num 2
channel_sel {0, 1}
stop_check_instart 1
Camera name / addr "imx415" / 0x1A
sensor_mode DOL2_M
format RAW10
gpio_enable_bit / gpio_level_bit 0x01 / 0x00
calib_lname "imx415_hdr_tuning.json"
VIN mipi_rx 0
vc_index 0
ipi_channel 2
cim_isp_flyby 1(online)
hdr_mode DOL_2
mclk_freq (vin_attr_ex) 24000000
VIN 输出 ddr_en 0(online 模式)
wstride SENSOR_WIDTH × 2(RAW10 为 ×2)
ISP 输入 input_mode PASSTHROUGH_MODE
sensor_mode ISP_DOL2_M
crop x=0, y=0, w=3840, h=2160
input_fmt FRM_FMT_RAW
input_bit_width 10
ISP 输出 output_fmt FRM_FMT_NV12
output_bit_width 8
ddr_en 1

5.17.6.4. 程序验证

  1. get_vin_data:确认 raw 图严重偏色、帧符合配置。DOL2 模式下会两个 channel 的数据。

  2. get_isp_data:准备 imx415_hdr_tuning.json(可拷贝分辨率 hdr json 并改 sensor_name),确认 ISP 合成的 YUV 图像正常,亮暗区域细节应比 Linear 模式丰富。

  3. hbplayer:连接板端预览短帧以及YUV数据,见 hbplayer 和 tuning_tool 工具使用指南

  4. tuning_tool:使用 tuning_tool 连接 hbplayer 后,输入命令 e,配置 Manual AE,分别设置 LEF 和 SEF1 的 aGain、integrationTime,看驱动打印核对 SHR0 (0x3050~0x3052)、SHR1 (0x3054~0x3056)、GAIN_PGC0 (0x3090)、GAIN_PGC1 (0x3092) 与 spec 一致,ISP 增益限制在 imx415_hdr_tuning.json 中配置以便自测。

常见问题Camera Sensor FAQ