Connecting OV2640 camera to CSI0 in parallel mode

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Connecting OV2640 camera to CSI0 in parallel mode

2,717 Views
krzysztofsza_ac
Contributor III

Hello, we're trying to connect OV2640 camera to CSI0 in parallel mode. What we have achieved till now:

  1. added OV2640 driver to kernel compliation
  2. have working clock on CLKO2 output
  3. OV2640 i2c interface is recognized by kernel as it locks proper (0x30) address on i2c bus
  4. made changes in board-mx6q_var_som.c as follows:
    1. in static void mx6q_mipi_sensor_io_init(void) added
      if (cpu_is_mx6q())
         mxc_iomux_set_gpr_register(1, 19, 1, 1) // enable csi0
    2. changed static struct fsl_mxc_camera_platform_data mipi_csi2_data = {
         .mclk = 24000000,
         .mcl_source = 0,
         .csi = 0,
         .io_init = mx6q_mipi_sensor_io_init,
         .pwdn = mx6q_mipi_powerdown,
      }
    3. added i2c device in static struct i2c_board_info mxc_i2c2_board_info[] __initdata = {
         {
            I2C_BOARD_INFO("ov2640", 0x30),
            .platform_data = (void *)&mipi_csi2_data
      }
    4. changed static struct fsl_mxc_capture_platform_data capture_data[] = {
        .csi = 0,
         .ipu = 1,
         .mclk_source = 0,
         .is_mipi = 0,
      }
    5. in static void __init mx6_var_som_board_init(void) {
         ...
        imx6q_add_v4l2_capture(0, &capture_data[0]);
         voutdev = imx6q_add_v4l2_output(0);
         ...
      }
      and removed imx6q_add_mipi_csi2(&mipi_csi2_pdata)
  5. added port mux in board-mx6q_var_som.h:
    MX6Q_PAD_CSI0_DAT12__IPU1_CSI0_D_12
    MX6Q_PAD_CSI0_DAT13__IPU1_CSI0_D_13
    MX6Q_PAD_CSI0_DAT14__IPU1_CSI0_D_14
    MX6Q_PAD_CSI0_DAT15__IPU1_CSI0_D_15
    MX6Q_PAD_CSI0_DAT16__IPU1_CSI0_D_16
    MX6Q_PAD_CSI0_DAT17__IPU1_CSI0_D_17
    MX6Q_PAD_CSI0_DAT18__IPU1_CSI0_D_18
    MX6Q_PAD_CSI0_DAT19__IPU1_CSI0_D_19
    MX6Q_PAD_CSI0_VSYNC__IPU1_CSI0_VSYNC
    MX6Q_PAD_CSI0_MCLK__IPU1_CSI0_HSYNC
    MX6Q_PAD_CSI0_PIXCLK__IPU1_CSI0_PIXCLK
    MX6Q_PAD_GPIO_7__GPIO_1_7
    MX6Q_PAD_GPIO_8__GPIO_1_8
  6. changed in init.rc
    setprop back_camera_name ov2640

From dmesg:

Linux video capture interface: v2.00

mxc_v4l2_output mxc_v4l2_output.0: V4L2 device registered as video16

mxc_v4l2_output mxc_v4l2_output.0: V4L2 device registered as video17

usbcore: registered new interface driver uvcvideo

USB Video Class driver (v1.1.0)

And finally when we open Camera2 apk we see error - Can't connetc to camera. It all looks like ov2640 driver is not working properly. It allocates i2c bus resources, but something is wrong. Did we miss anything in the configuration?

Labels (4)
0 Kudos
3 Replies

1,332 Views
weidong_sun
NXP TechSupport
NXP TechSupport

Hi Krzysztof,

    see following steps, please !

-----------------

/* the following codes are based on MCIMX6Q-SabreSDP board, see board-mx6q_sabresd.c & board-mx6q_sabresd.c file */

Step 1: /* IOMUX csi0 port : adding them to .h file*/

static iomux_v3_cfg_t mx6q_sabresd_csi0_sensor_pads[] = {

    /* IPU1 Camera */

    MX6Q_PAD_CSI0_DAT12__IPU1_CSI0_D_12,

    MX6Q_PAD_CSI0_DAT13__IPU1_CSI0_D_13,

    MX6Q_PAD_CSI0_DAT14__IPU1_CSI0_D_14,

    MX6Q_PAD_CSI0_DAT15__IPU1_CSI0_D_15,

    MX6Q_PAD_CSI0_DAT16__IPU1_CSI0_D_16,

    MX6Q_PAD_CSI0_DAT17__IPU1_CSI0_D_17,

    MX6Q_PAD_CSI0_DAT18__IPU1_CSI0_D_18,

    MX6Q_PAD_CSI0_DAT19__IPU1_CSI0_D_19,

    MX6Q_PAD_CSI0_MCLK__IPU1_CSI0_HSYNC,

    MX6Q_PAD_CSI0_PIXCLK__IPU1_CSI0_PIXCLK,

    MX6Q_PAD_CSI0_VSYNC__IPU1_CSI0_VSYNC,

    MX6Q_PAD_GPIO_3__CCM_CLKO2,            /* using CLKO2 camera clk */

    MX6Q_PAD_GPIO_7__GPIO_1_7,        /* camera PWDN */

    MX6Q_PAD_GPIO_8__GPIO_1_8,        /* camera RESET */

};

Step 2:/* add the following code to board-mx6q_sabresd.c */

...

#define SABRESD_CSI0_RST    IMX_GPIO_NR(1, 8)         /* assume reset pin is GPIO1_8 */

#define SABRESD_CSI0_PWN    IMX_GPIO_NR(1, 7)            /* assume pwdn pin is GPIO1_7 */

...

static void mx6q_csi0_io_init(void)

{

    /* cpu is i.MX6q */

        mxc_iomux_v3_setup_multiple_pads(mx6q_sabresd_csi0_sensor_pads,ARRAY_SIZE(mx6q_sabresd_csi0_sensor_pads));

    /* Camera reset */

    gpio_request(SABRESD_CSI0_RST, "cam-reset");

    gpio_direction_output(SABRESD_CSI0_RST, 1);

    /* Camera power down */

    gpio_request(SABRESD_CSI0_PWN, "cam-pwdn");

    gpio_direction_output(SABRESD_CSI0_PWN, 1);

    msleep(5);

    gpio_set_value(SABRESD_CSI0_PWN, 0);

    msleep(5);

    gpio_set_value(SABRESD_CSI0_RST, 0);

    msleep(1);

    gpio_set_value(SABRESD_CSI0_RST, 1);

    msleep(5);

    gpio_set_value(SABRESD_CSI0_PWN, 1);

    /* CPU is i.MX6Q*/

    mxc_iomux_set_gpr_register(1, 19, 1, 1);

}

static void mx6q_csi0_cam_powerdown(int powerdown)

{

    if (powerdown)

        gpio_set_value(SABRESD_CSI0_PWN, 1);

    else

        gpio_set_value(SABRESD_CSI0_PWN, 0);

    msleep(2);

}

static struct fsl_mxc_camera_platform_data camera_data = {

    .mclk = 24000000,

    .mclk_source = 0,

    .csi = 0,

    .io_init = mx6q_csi0_io_init,

    .pwdn = mx6q_csi0_cam_powerdown,

};

Step 3: /* add ov2640 to i2c3 bus */

static struct i2c_board_info mxc_i2c2_board_info[] __initdata = {

    {

        I2C_BOARD_INFO("ov2640", 0x30),

        .platform_data = (void *)&camera_data,

    },

};

Step 4: /* add ov2640 to board init */

static void __init mx6_sabresd_board_init(void)

{

......

imx6q_add_imx_i2c(2, &mx6q_sabresd_i2c_data);

i2c_register_board_info(2, mxc_i2c2_board_info,ARRAY_SIZE(mxc_i2c2_board_info));

......

/* enable CLKO2 for ov2640*/

    clko2 = clk_get(NULL, "clko2_clk");

    if (IS_ERR(clko2))

        pr_err("can't get CLKO2 clock.\n");

    new_parent = clk_get(NULL, "osc_clk");

    if (!IS_ERR(new_parent)) {

        clk_set_parent(clko2, new_parent);

        clk_put(new_parent);

    }

    rate = clk_round_rate(clko2, 24000000);

    clk_set_rate(clko2, rate);

    clk_enable(clko2);

    ......

}

step 5: /* add the following code to ov2640.c */

static int ov2640_probe(struct i2c_client *client,const struct i2c_device_id *id)

{

    int retval;

    u8 chip_id_high, chip_id_low;

...

    if (plat_data->gpo_regulator) {

        gpo_regulator =

            regulator_get(&client->dev, plat_data->gpo_regulator);

        if (!IS_ERR(gpo_regulator)) {

            if (regulator_enable(gpo_regulator) != 0) {

                pr_err("%s:gpo3 set voltage error\n", __func__);

                goto err4;

            } else {

                dev_dbg(&client->dev,

                    "%s:gpo3 set voltage ok\n", __func__);

            }

        } else

            gpo_regulator = NULL;

    }

    /*------------------ and the following code--------------------- */   

    if (plat_data->io_init)

        plat_data->io_init();

    if (plat_data->pwdn)

        plat_data->pwdn(0);            /* ov2640 power down */

       

        /* read product ID */

        chip_id_high = i2c_smbus_read_byte_data(client,0x0a); /* read product ID MSB */

    if (chip_id_high != 0x26) {

        pr_warning("camera ov2640 is not found\n");

        retval = -ENODEV;

        goto err4;

    }

    chip_id_low = i2c_smbus_read_byte_data(client,0x0b); /* read product ID LSB */

    if (chip_id_low != 0x41) {

        pr_warning("camera ov2640 is not found\n");

        retval = -ENODEV;

        goto err4;

    }

    if (plat_data->pwdn)

        plat_data->pwdn(1);        /* ov2640 power on */

       

/*--------- extra code ended--------------------- */       

    /* This function attaches this structure to the /dev/video0 device.

     * The pointer in priv points to the ov2640_data structure here.*/

    ov2640_int_device.priv = &ov2640_data;

...

}

step 6: /* when running make menuconfig, select ov2640 dirver module to linux image */

step 7: /* modify init.rc */

    setprop back_camera_name ov2640

step 8: /* modify camera HAL */

    in android BSP, camera HAL source code is at path ~/myandroid/hardware/imx/mx6/libcamera2

    customer can add ov2640 device to here by referring to other example devices , such as ov5642 etc.

-----------------------------------

Regards,

Weidong

1,332 Views
krzysztofsza_ac
Contributor III

Hello Weidong Sun!

I appreciate your help, there were some thing that I probably won't ever get to (like extedning Android's libcamera2). Unfortunatelly still i have no luck to connect to camera.

One thing was that my camera is using different ID. In your example there is 0x2641, while my camera has 0x2642. I've changed it and driver is allocating camera address (I'm checking this by using i2cdetect on specifis bus - if Kernel driver allocates some address, there is UU written on this address position, if it's not allocated - then it's address (0x30 in my case) itself).

I've created Ov2640Csi files from Ov5642Csi in libcamera2 folder. I suppose there will be some diffrences in resolutions supported, but as a beggining it should work without any change.

I'm wondering about two things:

- are you sure about powerdown function? In original board-mx6q_var_som.c file 0 and 1 state are replaced, like this:

static void mx6q_csi0_cam_powerdown(int powerdown)

{

    if (powerdown)

        gpio_set_value(SABRESD_CSI0_PWN, 0);

    else

        gpio_set_value(SABRESD_CSI0_PWN, 1);

    msleep(2);

}

- shouldn't I add in fsl_mxc_camera_platform_data value .ipu = 0?

0 Kudos

1,332 Views
weidong_sun
NXP TechSupport
NXP TechSupport

Hi,

>>shouldn't I add in fsl_mxc_camera_platform_data value .ipu = 0?

    you know two cameras are supported on i.mx6 sabreSDP EVK board, one is based on CSI0 parallel, the other is based on MIPI-CSI2 port, if the camera you are using is parallel, for your application, you don't need to modify settings in BSP.

>>I've created Ov2640Csi files from Ov5642Csi in libcamera2 folder. I suppose there will be some diffrences in resolutions supported, but as a beggining it should work without any change.

Yes, the way is correct, but you shoud do some ajustment on your source code in your Camera HAL, for example, initialization is different from ov5642,etc.

>> other reminder about data flow:

up to low : Camer HAL configuration--->mxc_v4l2_caputure(get capbilities of camera from camera driver)----->camera driver.

low to up : camera driver(start video stream according to configuration from HAL)---->mxc_v4l2_caputure----->IPU CSI interface--->IDMA--->IPU display.

Hope above suggestions can help you !

good luck !

Regards,

Weidong

0 Kudos