AnsweredAssumed Answered

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

Question asked by tao chen on Oct 9, 2014
Latest reply on Oct 27, 2014 by tao chen

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

Outcomes