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, ¶ms);
+ err = ipu_init_channel(cam->ipu, chan, ¶ms);
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
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
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
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