How to enable two csi camera at same time on i.mx6Q?

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

How to enable two csi camera at same time on i.mx6Q?

1,647 Views
ct3paul
Contributor II

Hi all

     I'm using i.mx6Q SD borad now.My BSP is linux-3.0.35.

     I want to use two csi camera now(two ADV7180).My camera chip is ADV7180 and csi0 camera is working now.But csi2 camera cat't work.

     This is what I've done:

     step1:

    the followed setting was needed in board-mx6q_sabresd.c:

static struct fsl_mxc_capture_platform_data capture_data[] = {
{
  .csi = 0,
  .ipu = 0,
  .mclk_source = 0,
  .is_mipi = 0,
}, {
  .csi = 1,
  .ipu = 0,
  .mclk_source = 0,
  .is_mipi = 1,
}, {
  .csi = 1,
  .ipu = 1,
  .mclk_source = 0,
  .is_mipi = 0,
},
};

static struct mipi_csi2_platform_data mipi_csi2_pdata = {
.ipu_id  = 0,
.csi_id = 1,
.v_channel = 0,
.lanes = 2,
.dphy_clk = "mipi_pllref_clk",
.pixel_clk = "emi_clk",
};

static struct fsl_mxc_camera_platform_data mipi_csi2_data = {
.mclk = 24000000,
.mclk_source = 0,
.csi = 1,
.io_init = mx6q_mipi_sensor_io_init,
.pwdn = mx6q_mipi_powerdown,
};

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,
};

static struct fsl_mxc_camera_platform_data camera2_data = {
.mclk = 24000000,
.mclk_source = 0,
.csi = 1,
.io_init = mx6q_csi1_io_init,
.pwdn = mx6q_csi1_cam_powerdown,
};

static struct i2c_board_info mxc_i2c0_board_info[] __initdata = {
{
  I2C_BOARD_INFO("ov564x", 0x3c),
  .platform_data = (void *)&camera_data,
},
};

static struct i2c_board_info mxc_i2c1_board_info[] __initdata = {
{
  I2C_BOARD_INFO("ov5640_mipi", 0x3c),
  .platform_data = (void *)&mipi_csi2_data,
},
};

static struct i2c_board_info mxc_i2c2_board_info[] __initdata = {
{
  I2C_BOARD_INFO("ov564x", 0x3c),
  .platform_data = (void *)&camera2_data,
},
};

In function mx6q_mipi_sensor_io_init():
if (cpu_is_mx6q())
  mxc_iomux_set_gpr_register(1, 19, 1, 1);

In function mx6q_csi0_io_init():
if (cpu_is_mx6q())
  mxc_iomux_set_gpr_register(1, 19, 1, 1);

In function mx6q_csi1_io_init():
if (cpu_is_mx6q())
  mxc_iomux_set_gpr_register(1, 20, 1, 1);

In function mx6_sabresd_board_init():
imx6q_add_v4l2_capture(0, &capture_data[0]);
imx6q_add_v4l2_capture(1, &capture_data[1]);
imx6q_add_v4l2_capture(2, &capture_data[2]);
imx6q_add_mipi_csi2(&mipi_csi2_pdata);

step2:

enable both cameras at the same time by using the following patch:

Index: kernel/linux-3.0.35-4.0.0/drivers/media/video/mxc/capture/ipu_csi_enc.c

===================================================================

--- kernel.orig/linux-3.0.35-4.0.0/drivers/media/video/mxc/capture/ipu_csi_enc.c 2013-10-07 14:42:58.927083104 -0600

+++ kernel/linux-3.0.35-4.0.0/drivers/media/video/mxc/capture/ipu_csi_enc.c 2013-10-07 14:44:19.031082649 -0600

@@ -56,6 +56,24 @@

}

/*!

+ * Get CSI dma channel

+ * @param csi       csi number

+ *

+ * @return  DMA channel

+ */

+static ipu_channel_t csi_get_dma_channel(int csi)

+{

+ switch(csi){

+ case 0:

+ return CSI_MEM0;

+ case 1:

+ return CSI_MEM1;

+ default:

+ return CSI_MEM0;

+ }

+}

+

+/*!

  * CSI ENC enable channel setup function

  *

  * @param cam       struct cam_data * mxc capture instance

@@ -74,6 +92,8 @@

  int csi_id;

#endif

+ uint32_t chan = csi_get_dma_channel(cam->csi);

+

  CAMERA_TRACE("In csi_enc_setup\n");

  if (!cam) {

  printk(KERN_ERR "cam private is NULL\n");

@@ -162,13 +182,13 @@

  }

#endif

- err = ipu_init_channel(cam->ipu, CSI_MEM, &params);

+ err = ipu_init_channel(cam->ipu, chan, &params);

  if (err != 0) {

  printk(KERN_ERR "ipu_init_channel %d\n", err);

  return err;

  }

- err = ipu_init_channel_buffer(cam->ipu, CSI_MEM, IPU_OUTPUT_BUFFER,

+ err = ipu_init_channel_buffer(cam->ipu, chan, IPU_OUTPUT_BUFFER,

       pixel_fmt, cam->v2f.fmt.pix.width,

       cam->v2f.fmt.pix.height,

       cam->v2f.fmt.pix.bytesperline,

@@ -180,7 +200,7 @@

  printk(KERN_ERR "CSI_MEM output buffer\n");

  return err;

  }

- err = ipu_enable_channel(cam->ipu, CSI_MEM);

+ err = ipu_enable_channel(cam->ipu, chan);

  if (err < 0) {

  printk(KERN_ERR "ipu_enable_channel CSI_MEM\n");

  return err;

@@ -197,18 +217,20 @@

  *

  * @return  status

  */

-static int csi_enc_eba_update(struct ipu_soc *ipu, dma_addr_t eba, int *buffer_num)

+static int csi_enc_eba_update(unsigned int csi, struct ipu_soc *ipu, dma_addr_t eba, int *buffer_num)

{

  int err = 0;

+ uint32_t chan = csi_get_dma_channel(csi);

+

  pr_debug("eba %x\n", eba);

- err = ipu_update_channel_buffer(ipu, CSI_MEM, IPU_OUTPUT_BUFFER,

+ err = ipu_update_channel_buffer(ipu, chan, IPU_OUTPUT_BUFFER,

  *buffer_num, eba);

  if (err != 0) {

- ipu_clear_buffer_ready(ipu, CSI_MEM, IPU_OUTPUT_BUFFER,

+ ipu_clear_buffer_ready(ipu, chan, IPU_OUTPUT_BUFFER,

        *buffer_num);

- err = ipu_update_channel_buffer(ipu, CSI_MEM, IPU_OUTPUT_BUFFER,

+ err = ipu_update_channel_buffer(ipu, chan, IPU_OUTPUT_BUFFER,

  *buffer_num, eba);

  if (err != 0) {

  pr_err("ERROR: v4l2 capture: fail to update "

@@ -217,7 +239,7 @@

  }

  }

- ipu_select_buffer(ipu, CSI_MEM, IPU_OUTPUT_BUFFER, *buffer_num);

+ ipu_select_buffer(ipu, chan, IPU_OUTPUT_BUFFER, *buffer_num);

  *buffer_num = (*buffer_num == 0) ? 1 : 0;

@@ -234,6 +256,7 @@

{

  cam_data *cam = (cam_data *) private;

  int err = 0;

+ uint32_t irq;

  CAMERA_TRACE("IPU:In csi_enc_enabling_tasks\n");

  cam->dummy_frame.vaddress = dma_alloc_coherent(0,

@@ -250,8 +273,10 @@

     PAGE_ALIGN(cam->v2f.fmt.pix.sizeimage);

  cam->dummy_frame.buffer.m.offset = cam->dummy_frame.paddress;

- ipu_clear_irq(cam->ipu, IPU_IRQ_CSI0_OUT_EOF);

- err = ipu_request_irq(cam->ipu, IPU_IRQ_CSI0_OUT_EOF,

+ irq = IPU_IRQ_CSI0_OUT_EOF + cam->csi;

+

+ ipu_clear_irq(cam->ipu, irq);

+ err = ipu_request_irq(cam->ipu, irq,

       csi_enc_callback, 0, "Mxc Camera", cam);

  if (err != 0) {

  printk(KERN_ERR "Error registering rot irq\n");

@@ -283,9 +308,11 @@

  int csi_id;

#endif

- err = ipu_disable_channel(cam->ipu, CSI_MEM, true);

+ uint32_t chan = csi_get_dma_channel(cam->csi);

+

+ err = ipu_disable_channel(cam->ipu, chan, true);

- ipu_uninit_channel(cam->ipu, CSI_MEM);

+ ipu_uninit_channel(cam->ipu, chan);

  if (cam->dummy_frame.vaddress != 0) {

  dma_free_coherent(0, cam->dummy_frame.buffer.length,

@@ -341,7 +368,8 @@

  /* free csi eof irq firstly.

  * when disable csi, wait for idmac eof.

  * it requests eof irq again */

- ipu_free_irq(cam->ipu, IPU_IRQ_CSI0_OUT_EOF, cam);

+

+ ipu_free_irq(cam->ipu, IPU_IRQ_CSI0_OUT_EOF + cam->csi, cam);

  return ipu_disable_csi(cam->ipu, cam->csi);

}

Index: kernel/linux-3.0.35-4.0.0/drivers/media/video/mxc/capture/mxc_v4l2_capture.c

===================================================================

--- kernel.orig/linux-3.0.35-4.0.0/drivers/media/video/mxc/capture/mxc_v4l2_capture.c 2013-10-07 14:42:58.939083104 -0600

+++ kernel/linux-3.0.35-4.0.0/drivers/media/video/mxc/capture/mxc_v4l2_capture.c 2013-10-07 14:43:15.471083010 -0600

@@ -429,7 +429,7 @@

  list_del(cam->ready_q.next);

  list_add_tail(&frame->queue, &cam->working_q);

  frame->ipu_buf_num = cam->ping_pong_csi;

- err = cam->enc_update_eba(cam->ipu, frame->buffer.m.offset,

+ err = cam->enc_update_eba(cam-> csi, cam->ipu, frame->buffer.m.offset,

   &cam->ping_pong_csi);

  frame =

@@ -437,7 +437,7 @@

  list_del(cam->ready_q.next);

  list_add_tail(&frame->queue, &cam->working_q);

  frame->ipu_buf_num = cam->ping_pong_csi;

- err |= cam->enc_update_eba(cam->ipu, frame->buffer.m.offset,

+ err |= cam->enc_update_eba(cam-> csi, cam->ipu, frame->buffer.m.offset,

    &cam->ping_pong_csi);

  spin_unlock_irqrestore(&cam->queue_int_lock, lock_flags);

  } else {

@@ -2615,7 +2615,7 @@

  struct mxc_v4l_frame,

  queue);

  if (cam->enc_update_eba)

- if (cam->enc_update_eba(cam->ipu, ready_frame->buffer.m.offset,

+ if (cam->enc_update_eba(cam->csi, cam->ipu, ready_frame->buffer.m.offset,

  &cam->ping_pong_csi) == 0) {

  list_del(cam->ready_q.next);

  list_add_tail(&ready_frame->queue,

@@ -2625,7 +2625,7 @@

  } else {

  if (cam->enc_update_eba)

  cam->enc_update_eba(

- cam->ipu, cam->dummy_frame.buffer.m.offset,

+ cam->csi, cam->ipu, cam->dummy_frame.buffer.m.offset,

  &cam->ping_pong_csi);

  }

Index: kernel/linux-3.0.35-4.0.0/drivers/media/video/mxc/capture/mxc_v4l2_capture.h

===================================================================

--- kernel.orig/linux-3.0.35-4.0.0/drivers/media/video/mxc/capture/mxc_v4l2_capture.h 2013-10-07 14:42:58.963083104 -0600

+++ kernel/linux-3.0.35-4.0.0/drivers/media/video/mxc/capture/mxc_v4l2_capture.h 2013-10-07 14:43:15.471083010 -0600

@@ -178,7 +178,7 @@

  struct v4l2_rect crop_defrect;

  struct v4l2_rect crop_current;

- int (*enc_update_eba) (struct ipu_soc *ipu, dma_addr_t eba, int *bufferNum);

+ int (*enc_update_eba) (unsigned int csi, struct ipu_soc *ipu, dma_addr_t eba, int *bufferNum);

  int (*enc_enable) (void *private);

  int (*enc_disable) (void *private);

  int (*enc_enable_csi) (void *private);

please help me!

thanks

chen

4 Replies

698 Views
igorpadykov
NXP Employee
NXP Employee

Hi tao

please check below

IPU2 for CSI parallel camera

Best regards

igor

0 Kudos

698 Views
ct3paul
Contributor II

Hi igor

Thank you for your reply

I also read this post bofore.But I don't konw how to do it ,can you help me solve it?

Thanks!

Chen

0 Kudos

698 Views
igorpadykov
NXP Employee
NXP Employee

Hi tao

also one can try attached patch.

Two cameras can work at unit test level:

/unit_tests/mxc_v4l2_capture.out -iw 1024 -ih 768  -ow 1024 -oh 768  -m 8 -fr 15 -d /dev/video0 -i 1 -c 100 /test1.yuv & /unit_tests/mxc_v4l2_capture.out -iw 1024 -ih 768  -ow 1024 -oh 768  -m 8 -fr 15 -d /dev/video1 -i 0 -c 100 /test2.yuv

~igor

0 Kudos

698 Views
ct3paul
Contributor II

Hi

igor

My two csi camera also can't work when I do like you said.

My camera chip is ADV7180.It can work well when I loaded one chip driver.

But when I add two devices to i2c struct like this:

static struct i2c_board_info mxc_i2c0_board_info[] __initdata = {

  #if 1

  {

  I2C_BOARD_INFO("adv7180", 0x20),

  .platform_data = (void *)&adv7180_data,

  },

  #endif

#if 1

  {

  I2C_BOARD_INFO("adv7180", 0x21),

  .platform_data = (void *)&camera2_data,

  },

  #endif

};

I can't load my driver.I enter a loop and I cat't break it when I loadind drivers if I add two devices to i2c struct.

My drivers:

insmod ipu_bg_overlay_sdc.ko

insmod ipu_csi_enc.ko

insmod ipu_fg_overlay_sdc.ko

insmod ipu_prp_enc.ko

insmod ipu_still.ko

insmod adv7180_tvin.ko

insmod mxc_v4l2_capture.ko

Thanks

Chen

0 Kudos