[PATCH 2/4] [media] marvell-ccic: core: add soc camera support on marvell-ccic mcam-core

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Libin Yang <lbyang@xxxxxxxxxxx>

This patch adds the support of Soc Camera on marvell-ccic mcam-core.
The Soc Camera mode does not compatible with current mode.
Only one mode can be used at one time.

To use Soc Camera, CONFIG_VIDEO_MMP_SOC_CAMERA should be defined.
What's more, the platform driver should support Soc camera at the same time.

Also add MIPI interface and dual CCICs support in Soc Camera mode.

Signed-off-by: Albert Wang <twang13@xxxxxxxxxxx>
Signed-off-by: Libin Yang <lbyang@xxxxxxxxxxx>
---
 drivers/media/platform/marvell-ccic/mcam-core.c | 1034 ++++++++++++++++++++++----
 drivers/media/platform/marvell-ccic/mcam-core.h |  126 +++-
 2 files changed, 997 insertions(+), 163 deletions(-)

diff --git a/drivers/media/platform/marvell-ccic/mcam-core.c b/drivers/media/platform/marvell-ccic/mcam-core.c
index ce2b7b4..4adb1ca 100755
--- a/drivers/media/platform/marvell-ccic/mcam-core.c
+++ b/drivers/media/platform/marvell-ccic/mcam-core.c
@@ -3,6 +3,12 @@
  * so it needs platform-specific support outside of the core.
  *
  * Copyright 2011 Jonathan Corbet corbet@xxxxxxx
+ *
+ * History:
+ * Support Soc Camera
+ * Support MIPI interface and Dual CCICs in Soc Camera mode
+ * Sep-2012: Libin Yang <lbyang@xxxxxxxxxxx>
+ *           Albert Wang <twang13@xxxxxxxxxxx>
  */
 #include <linux/kernel.h>
 #include <linux/module.h>
@@ -27,16 +33,14 @@
 #include <media/videobuf2-vmalloc.h>
 #include <media/videobuf2-dma-contig.h>
 #include <media/videobuf2-dma-sg.h>
+#ifdef CONFIG_VIDEO_MRVL_SOC_CAMERA
+#include <media/soc_camera.h>
+#include <media/soc_mediabus.h>
+#endif
+#include <mach/regs-apmu.h>
 
 #include "mcam-core.h"
 
-/*
- * Basic frame stats - to be deleted shortly
- */
-static int frames;
-static int singles;
-static int delivered;
-
 #ifdef MCAM_MODE_VMALLOC
 /*
  * Internal DMA buffer management.  Since the controller cannot do S/G I/O,
@@ -100,10 +104,50 @@ MODULE_PARM_DESC(buffer_mode,
 #define CF_CONFIG_NEEDED 4	/* Must configure hardware */
 #define CF_SINGLE_BUFFER 5	/* Running with a single buffer */
 #define CF_SG_RESTART	 6	/* SG restart needed */
+#define CF_FRAME_SOF0	 7	/* Frame 0 started */
+#define CF_FRAME_SOF1	 8
+#define CF_FRAME_SOF2	 9
 
+#ifdef CONFIG_VIDEO_MRVL_SOC_CAMERA
+#define sensor_call(cam, o, f, args...) \
+	v4l2_subdev_call(soc_camera_to_subdev(cam->icd), o, f, ##args)
+#else
 #define sensor_call(cam, o, f, args...) \
 	v4l2_subdev_call(cam->sensor, o, f, ##args)
+#endif
 
+#ifdef CONFIG_VIDEO_MRVL_SOC_CAMERA
+static const struct soc_mbus_pixelfmt mcam_formats[] = {
+	{
+		.fourcc	= V4L2_PIX_FMT_UYVY,
+		.name = "YUV422PACKED",
+		.bits_per_sample = 8,
+		.packing = SOC_MBUS_PACKING_2X8_PADLO,
+		.order = SOC_MBUS_ORDER_LE,
+	},
+	{
+		.fourcc = V4L2_PIX_FMT_YUV422P,
+		.name = "YUV422PLANAR",
+		.bits_per_sample = 8,
+		.packing = SOC_MBUS_PACKING_2X8_PADLO,
+		.order = SOC_MBUS_ORDER_LE,
+	},
+	{
+		.fourcc = V4L2_PIX_FMT_YUV420,
+		.name = "YUV420PLANAR",
+		.bits_per_sample = 12,
+		.packing = SOC_MBUS_PACKING_NONE,
+		.order = SOC_MBUS_ORDER_LE,
+	},
+	{
+		.fourcc = V4L2_PIX_FMT_YVU420,
+		.name = "YVU420PLANAR",
+		.bits_per_sample = 12,
+		.packing = SOC_MBUS_PACKING_NONE,
+		.order = SOC_MBUS_ORDER_LE,
+	},
+};
+#else
 static struct mcam_format_struct {
 	__u8 *desc;
 	__u32 pixelformat;
@@ -147,6 +191,7 @@ static struct mcam_format_struct *mcam_find_format(u32 pixelformat)
 	/* Not found? Then return the first format. */
 	return mcam_formats;
 }
+#endif
 
 /*
  * The default format we use until somebody says otherwise.
@@ -175,19 +220,6 @@ struct mcam_dma_desc {
 	u32 segment_len;
 };
 
-/*
- * Our buffer type for working with videobuf2.  Note that the vb2
- * developers have decreed that struct vb2_buffer must be at the
- * beginning of this structure.
- */
-struct mcam_vb_buffer {
-	struct vb2_buffer vb_buf;
-	struct list_head queue;
-	struct mcam_dma_desc *dma_desc;	/* Descriptor virtual address */
-	dma_addr_t dma_desc_pa;		/* Descriptor physical address */
-	int dma_desc_nent;		/* Number of mapped descriptors */
-};
-
 static inline struct mcam_vb_buffer *vb_to_mvb(struct vb2_buffer *vb)
 {
 	return container_of(vb, struct mcam_vb_buffer, vb_buf);
@@ -226,8 +258,10 @@ static void mcam_reset_buffers(struct mcam_camera *cam)
 	int i;
 
 	cam->next_buf = -1;
-	for (i = 0; i < cam->nbufs; i++)
+	for (i = 0; i < cam->nbufs; i++) {
 		clear_bit(i, &cam->flags);
+		clear_bit(CF_FRAME_SOF0 + i, &cam->flags);
+	}
 }
 
 static inline int mcam_needs_config(struct mcam_camera *cam)
@@ -367,10 +401,10 @@ static void mcam_frame_tasklet(unsigned long data)
 		if (!test_bit(bufno, &cam->flags))
 			continue;
 		if (list_empty(&cam->buffers)) {
-			singles++;
+			cam->frame_state.singles++;
 			break;  /* Leave it valid, hope for better later */
 		}
-		delivered++;
+		cam->frame_state.delivered++;
 		clear_bit(bufno, &cam->flags);
 		buf = list_first_entry(&cam->buffers, struct mcam_vb_buffer,
 				queue);
@@ -422,11 +456,8 @@ static inline int mcam_check_dma_buffers(struct mcam_camera *cam)
 	return 0;
 }
 
-
-
 #endif /* MCAM_MODE_VMALLOC */
 
-
 #ifdef MCAM_MODE_DMA_CONTIG
 /* ---------------------------------------------------------------------- */
 /*
@@ -443,27 +474,38 @@ static inline int mcam_check_dma_buffers(struct mcam_camera *cam)
 static void mcam_set_contig_buffer(struct mcam_camera *cam, int frame)
 {
 	struct mcam_vb_buffer *buf;
+	struct v4l2_pix_format *fmt = &cam->pix_format;
+	unsigned long flags = 0;
+
+	spin_lock_irqsave(&cam->list_lock, flags);
 	/*
 	 * If there are no available buffers, go into single mode
 	 */
 	if (list_empty(&cam->buffers)) {
 		buf = cam->vb_bufs[frame ^ 0x1];
-		cam->vb_bufs[frame] = buf;
-		mcam_reg_write(cam, frame == 0 ? REG_Y0BAR : REG_Y1BAR,
-				vb2_dma_contig_plane_dma_addr(&buf->vb_buf, 0));
 		set_bit(CF_SINGLE_BUFFER, &cam->flags);
-		singles++;
-		return;
+		cam->frame_state.singles++;
+	} else {
+		/*
+		 * OK, we have a buffer we can use.
+		 */
+		buf = list_first_entry(&cam->buffers, struct mcam_vb_buffer,
+					queue);
+		list_del_init(&buf->queue);
+		clear_bit(CF_SINGLE_BUFFER, &cam->flags);
 	}
-	/*
-	 * OK, we have a buffer we can use.
-	 */
-	buf = list_first_entry(&cam->buffers, struct mcam_vb_buffer, queue);
-	list_del_init(&buf->queue);
-	mcam_reg_write(cam, frame == 0 ? REG_Y0BAR : REG_Y1BAR,
-			vb2_dma_contig_plane_dma_addr(&buf->vb_buf, 0));
 	cam->vb_bufs[frame] = buf;
-	clear_bit(CF_SINGLE_BUFFER, &cam->flags);
+	mcam_reg_write(cam, frame == 0 ?
+			REG_Y0BAR : REG_Y1BAR, buf->yuv_p.y);
+	if (fmt->pixelformat == V4L2_PIX_FMT_YUV422P
+			|| fmt->pixelformat == V4L2_PIX_FMT_YUV420
+			|| fmt->pixelformat == V4L2_PIX_FMT_YVU420) {
+		mcam_reg_write(cam, frame == 0 ?
+				REG_U0BAR : REG_U1BAR, buf->yuv_p.u);
+		mcam_reg_write(cam, frame == 0 ?
+				REG_V0BAR : REG_V1BAR, buf->yuv_p.v);
+	}
+	spin_unlock_irqrestore(&cam->list_lock, flags);
 }
 
 /*
@@ -471,10 +513,10 @@ static void mcam_set_contig_buffer(struct mcam_camera *cam, int frame)
  */
 static void mcam_ctlr_dma_contig(struct mcam_camera *cam)
 {
-	mcam_reg_set_bit(cam, REG_CTRL1, C1_TWOBUFS);
 	cam->nbufs = 2;
 	mcam_set_contig_buffer(cam, 0);
 	mcam_set_contig_buffer(cam, 1);
+	mcam_reg_set_bit(cam, REG_CTRL1, C1_TWOBUFS);
 }
 
 /*
@@ -483,11 +525,14 @@ static void mcam_ctlr_dma_contig(struct mcam_camera *cam)
 static void mcam_dma_contig_done(struct mcam_camera *cam, int frame)
 {
 	struct mcam_vb_buffer *buf = cam->vb_bufs[frame];
+	unsigned long flags = 0;
 
+	spin_lock_irqsave(&cam->list_lock, flags);
 	if (!test_bit(CF_SINGLE_BUFFER, &cam->flags)) {
-		delivered++;
+		cam->frame_state.delivered++;
 		mcam_buffer_done(cam, frame, &buf->vb_buf);
 	}
+	spin_unlock_irqrestore(&cam->list_lock, flags);
 	mcam_set_contig_buffer(cam, frame);
 }
 
@@ -542,7 +587,6 @@ static void mcam_ctlr_dma_sg(struct mcam_camera *cam)
 	cam->nbufs = 3;
 }
 
-
 /*
  * Frame completion with S/G is trickier.  We can't muck with
  * a descriptor chain on the fly, since the controller buffers it
@@ -578,17 +622,16 @@ static void mcam_dma_sg_done(struct mcam_camera *cam, int frame)
 	 */
 	} else {
 		set_bit(CF_SG_RESTART, &cam->flags);
-		singles++;
+		cam->frame_state.singles++;
 		cam->vb_bufs[0] = NULL;
 	}
 	/*
 	 * Now we can give the completed frame back to user space.
 	 */
-	delivered++;
+	cam->frame_state.delivered++;
 	mcam_buffer_done(cam, frame, &buf->vb_buf);
 }
 
-
 /*
  * Scatter/gather mode requires stopping the controller between
  * frames so we can put in a new DMA descriptor array.  If no new
@@ -616,56 +659,110 @@ static inline void mcam_sg_restart(struct mcam_camera *cam)
  * Buffer-mode-independent controller code.
  */
 
-/*
- * Image format setup
- */
-static void mcam_ctlr_image(struct mcam_camera *cam)
+static int mcam_ctlr_image(struct mcam_camera *mcam)
 {
-	int imgsz;
-	struct v4l2_pix_format *fmt = &cam->pix_format;
+	struct v4l2_pix_format *fmt = &mcam->pix_format;
+	u32 widthy = 0, widthuv = 0, imgsz_h, imgsz_w;
+	int ret = 0;
+
+	cam_dbg(mcam, "camera: bytesperline = %d; height = %d\n",
+		fmt->bytesperline, fmt->sizeimage / fmt->bytesperline);
+	imgsz_h = (fmt->height << IMGSZ_V_SHIFT) & IMGSZ_V_MASK;
+	imgsz_w = fmt->bytesperline & IMGSZ_H_MASK;
+
+	if (fmt->pixelformat == V4L2_PIX_FMT_YUV420
+		|| fmt->pixelformat == V4L2_PIX_FMT_YVU420)
+		imgsz_w = (fmt->bytesperline * 4 / 3) & IMGSZ_H_MASK;
+	else if (fmt->pixelformat == V4L2_PIX_FMT_JPEG)
+		imgsz_h = (fmt->sizeimage / fmt->bytesperline) << IMGSZ_V_SHIFT;
+
+	switch (fmt->pixelformat) {
+	case V4L2_PIX_FMT_YUYV:
+	case V4L2_PIX_FMT_UYVY:
+		widthy = fmt->width * 2;
+		widthuv = fmt->width * 2;
+		break;
+	case V4L2_PIX_FMT_RGB565:
+		widthy = fmt->width * 2;
+		widthuv = 0;
+		break;
+	case V4L2_PIX_FMT_JPEG:
+		widthy = fmt->bytesperline;
+		widthuv = fmt->bytesperline;
+		break;
+	case V4L2_PIX_FMT_YUV422P:
+		widthy = fmt->width;
+		widthuv = fmt->width / 2;
+		break;
+	case V4L2_PIX_FMT_YUV420:
+	case V4L2_PIX_FMT_YVU420:
+		widthy = fmt->width;
+		widthuv = fmt->width / 2;
+		break;
+	default:
+		break;
+	}
+
+	mcam_reg_write_mask(mcam, REG_IMGPITCH, widthuv << 16 | widthy,
+			IMGP_YP_MASK | IMGP_UVP_MASK);
+	mcam_reg_write(mcam, REG_IMGSIZE, imgsz_h | imgsz_w);
+	mcam_reg_write(mcam, REG_IMGOFFSET, 0x0);
 
-	imgsz = ((fmt->height << IMGSZ_V_SHIFT) & IMGSZ_V_MASK) |
-		(fmt->bytesperline & IMGSZ_H_MASK);
-	mcam_reg_write(cam, REG_IMGSIZE, imgsz);
-	mcam_reg_write(cam, REG_IMGOFFSET, 0);
-	/* YPITCH just drops the last two bits */
-	mcam_reg_write_mask(cam, REG_IMGPITCH, fmt->bytesperline,
-			IMGP_YP_MASK);
 	/*
 	 * Tell the controller about the image format we are using.
 	 */
-	switch (cam->pix_format.pixelformat) {
+	switch (fmt->pixelformat) {
+	case V4L2_PIX_FMT_YUV422P:
+		mcam_reg_write_mask(mcam, REG_CTRL0,
+			C0_DF_YUV | C0_YUV_PLANAR | C0_YUVE_YVYU, C0_DF_MASK);
+		break;
+	case V4L2_PIX_FMT_YUV420:
+	case V4L2_PIX_FMT_YVU420:
+		mcam_reg_write_mask(mcam, REG_CTRL0,
+			C0_DF_YUV | C0_YUV_420PL | C0_YUVE_YVYU, C0_DF_MASK);
+		break;
 	case V4L2_PIX_FMT_YUYV:
-	    mcam_reg_write_mask(cam, REG_CTRL0,
-			    C0_DF_YUV|C0_YUV_PACKED|C0_YUVE_YUYV,
-			    C0_DF_MASK);
-	    break;
-
+		mcam_reg_write_mask(mcam, REG_CTRL0,
+			C0_DF_YUV | C0_YUV_PACKED | C0_YUVE_UYVY, C0_DF_MASK);
+		break;
+	case V4L2_PIX_FMT_UYVY:
+		mcam_reg_write_mask(mcam, REG_CTRL0,
+			C0_DF_YUV | C0_YUV_PACKED | C0_YUVE_YUYV, C0_DF_MASK);
+		break;
+	case V4L2_PIX_FMT_JPEG:
+		mcam_reg_write_mask(mcam, REG_CTRL0,
+			C0_DF_YUV | C0_YUV_PACKED | C0_YUVE_YUYV, C0_DF_MASK);
+		break;
 	case V4L2_PIX_FMT_RGB444:
-	    mcam_reg_write_mask(cam, REG_CTRL0,
-			    C0_DF_RGB|C0_RGBF_444|C0_RGB4_XRGB,
-			    C0_DF_MASK);
-		/* Alpha value? */
-	    break;
-
+		mcam_reg_write_mask(mcam, REG_CTRL0,
+			C0_DF_RGB | C0_RGBF_444 | C0_RGB4_XRGB, C0_DF_MASK);
+		break;
 	case V4L2_PIX_FMT_RGB565:
-	    mcam_reg_write_mask(cam, REG_CTRL0,
-			    C0_DF_RGB|C0_RGBF_565|C0_RGB5_BGGR,
-			    C0_DF_MASK);
-	    break;
-
+		mcam_reg_write_mask(mcam, REG_CTRL0,
+			C0_DF_RGB | C0_RGBF_565 | C0_RGB5_BGGR, C0_DF_MASK);
+		break;
 	default:
-	    cam_err(cam, "Unknown format %x\n", cam->pix_format.pixelformat);
-	    break;
+		cam_err(mcam, "camera: unknown format: %c\n", fmt->pixelformat);
+		break;
 	}
+
 	/*
 	 * Make sure it knows we want to use hsync/vsync.
 	 */
-	mcam_reg_write_mask(cam, REG_CTRL0, C0_SIF_HVSYNC,
-			C0_SIFM_MASK);
-}
+	mcam_reg_write_mask(mcam, REG_CTRL0, C0_SIF_HVSYNC, C0_SIFM_MASK);
+	/*
+	 * This field controls the generation of EOF(DVP only)
+	 */
+	if (mcam->bus_type != V4L2_MBUS_CSI2_LANES) {
+		mcam_reg_set_bit(mcam, REG_CTRL0,
+				C0_EOF_VSYNC | C0_VEDGE_CTRL);
+		mcam_reg_write(mcam, REG_CTRL3, 0x4);
+	}
 
+	return ret;
+}
 
+#ifndef CONFIG_VIDEO_MRVL_SOC_CAMERA
 /*
  * Configure the controller for operation; caller holds the
  * device mutex.
@@ -683,23 +780,6 @@ static int mcam_ctlr_configure(struct mcam_camera *cam)
 	return 0;
 }
 
-static void mcam_ctlr_irq_enable(struct mcam_camera *cam)
-{
-	/*
-	 * Clear any pending interrupts, since we do not
-	 * expect to have I/O active prior to enabling.
-	 */
-	mcam_reg_write(cam, REG_IRQSTAT, FRAMEIRQS);
-	mcam_reg_set_bit(cam, REG_IRQMASK, FRAMEIRQS);
-}
-
-static void mcam_ctlr_irq_disable(struct mcam_camera *cam)
-{
-	mcam_reg_clear_bit(cam, REG_IRQMASK, FRAMEIRQS);
-}
-
-
-
 static void mcam_ctlr_init(struct mcam_camera *cam)
 {
 	unsigned long flags;
@@ -721,7 +801,22 @@ static void mcam_ctlr_init(struct mcam_camera *cam)
 	mcam_reg_write_mask(cam, REG_CLKCTRL, 2, CLK_DIV_MASK);
 	spin_unlock_irqrestore(&cam->dev_lock, flags);
 }
+#endif
 
+static void mcam_ctlr_irq_enable(struct mcam_camera *cam)
+{
+	/*
+	 * Clear any pending interrupts, since we do not
+	 * expect to have I/O active prior to enabling.
+	 */
+	mcam_reg_write(cam, REG_IRQSTAT, FRAMEIRQS);
+	mcam_reg_set_bit(cam, REG_IRQMASK, FRAMEIRQS);
+}
+
+static void mcam_ctlr_irq_disable(struct mcam_camera *cam)
+{
+	mcam_reg_clear_bit(cam, REG_IRQMASK, FRAMEIRQS);
+}
 
 /*
  * Stop the controller, and don't return until we're really sure that no
@@ -796,6 +891,7 @@ static int __mcam_cam_reset(struct mcam_camera *cam)
 	return sensor_call(cam, core, reset, 0);
 }
 
+#ifndef CONFIG_VIDEO_MRVL_SOC_CAMERA
 /*
  * We have found the sensor on the i2c.  Let's try to have a
  * conversation.
@@ -824,7 +920,7 @@ static int mcam_cam_init(struct mcam_camera *cam)
 		ret = -EINVAL;
 		goto out;
 	}
-/* Get/set parameters? */
+	/* Get/set parameters? */
 	ret = 0;
 	cam->state = S_IDLE;
 out:
@@ -847,7 +943,6 @@ static int mcam_cam_set_flip(struct mcam_camera *cam)
 	return sensor_call(cam, core, s_ctrl, &ctrl);
 }
 
-
 static int mcam_cam_configure(struct mcam_camera *cam)
 {
 	struct v4l2_mbus_framefmt mbus_fmt;
@@ -923,7 +1018,6 @@ static int mcam_vb_queue_setup(struct vb2_queue *vq,
 	return 0;
 }
 
-
 static void mcam_vb_buf_queue(struct vb2_buffer *vb)
 {
 	struct mcam_vb_buffer *mvb = vb_to_mvb(vb);
@@ -941,7 +1035,6 @@ static void mcam_vb_buf_queue(struct vb2_buffer *vb)
 		mcam_read_setup(cam);
 }
 
-
 /*
  * vb2 uses these to release the mutex when waiting in dqbuf.  I'm
  * not actually sure we need to do this (I'm not sure that vb2_dqbuf() needs
@@ -1010,7 +1103,6 @@ static int mcam_vb_stop_streaming(struct vb2_queue *vq)
 	return 0;
 }
 
-
 static const struct vb2_ops mcam_vb2_ops = {
 	.queue_setup		= mcam_vb_queue_setup,
 	.buf_queue		= mcam_vb_buf_queue,
@@ -1020,7 +1112,6 @@ static const struct vb2_ops mcam_vb2_ops = {
 	.wait_finish		= mcam_vb_wait_finish,
 };
 
-
 #ifdef MCAM_MODE_DMA_SG
 /*
  * Scatter/gather mode uses all of the above functions plus a
@@ -1082,7 +1173,6 @@ static void mcam_vb_sg_buf_cleanup(struct vb2_buffer *vb)
 			mvb->dma_desc, mvb->dma_desc_pa);
 }
 
-
 static const struct vb2_ops mcam_vb2_sg_ops = {
 	.queue_setup		= mcam_vb_queue_setup,
 	.buf_init		= mcam_vb_sg_buf_init,
@@ -1151,7 +1241,6 @@ static void mcam_cleanup_vb2(struct mcam_camera *cam)
 #endif
 }
 
-
 /* ---------------------------------------------------------------------- */
 /*
  * The long list of V4L2 ioctl() operations.
@@ -1169,7 +1258,6 @@ static int mcam_vidioc_streamon(struct file *filp, void *priv,
 	return ret;
 }
 
-
 static int mcam_vidioc_streamoff(struct file *filp, void *priv,
 		enum v4l2_buf_type type)
 {
@@ -1182,7 +1270,6 @@ static int mcam_vidioc_streamoff(struct file *filp, void *priv,
 	return ret;
 }
 
-
 static int mcam_vidioc_reqbufs(struct file *filp, void *priv,
 		struct v4l2_requestbuffers *req)
 {
@@ -1195,7 +1282,6 @@ static int mcam_vidioc_reqbufs(struct file *filp, void *priv,
 	return ret;
 }
 
-
 static int mcam_vidioc_querybuf(struct file *filp, void *priv,
 		struct v4l2_buffer *buf)
 {
@@ -1232,8 +1318,6 @@ static int mcam_vidioc_dqbuf(struct file *filp, void *priv,
 	return ret;
 }
 
-
-
 static int mcam_vidioc_queryctrl(struct file *filp, void *priv,
 		struct v4l2_queryctrl *qc)
 {
@@ -1246,7 +1330,6 @@ static int mcam_vidioc_queryctrl(struct file *filp, void *priv,
 	return ret;
 }
 
-
 static int mcam_vidioc_g_ctrl(struct file *filp, void *priv,
 		struct v4l2_control *ctrl)
 {
@@ -1259,7 +1342,6 @@ static int mcam_vidioc_g_ctrl(struct file *filp, void *priv,
 	return ret;
 }
 
-
 static int mcam_vidioc_s_ctrl(struct file *filp, void *priv,
 		struct v4l2_control *ctrl)
 {
@@ -1272,7 +1354,6 @@ static int mcam_vidioc_s_ctrl(struct file *filp, void *priv,
 	return ret;
 }
 
-
 static int mcam_vidioc_querycap(struct file *file, void *priv,
 		struct v4l2_capability *cap)
 {
@@ -1284,7 +1365,6 @@ static int mcam_vidioc_querycap(struct file *file, void *priv,
 	return 0;
 }
 
-
 static int mcam_vidioc_enum_fmt_vid_cap(struct file *filp,
 		void *priv, struct v4l2_fmtdesc *fmt)
 {
@@ -1545,7 +1625,9 @@ static int mcam_v4l_open(struct file *filp)
 
 	filp->private_data = cam;
 
-	frames = singles = delivered = 0;
+	cam->frame_state.frames = 0;
+	cam->frame_state.singles = 0;
+	cam->frame_state.delivered = 0;
 	mutex_lock(&cam->s_mutex);
 	if (cam->users == 0) {
 		ret = mcam_setup_vb2(cam);
@@ -1561,13 +1643,13 @@ out:
 	return ret;
 }
 
-
 static int mcam_v4l_release(struct file *filp)
 {
 	struct mcam_camera *cam = filp->private_data;
 
-	cam_dbg(cam, "Release, %d frames, %d singles, %d delivered\n", frames,
-			singles, delivered);
+	cam_dbg(cam, "Release, %d frames, %d singles, %d delivered\n",
+			cam->frame_state.frames, cam->frame_state.singles,
+			cam->frame_state.delivered);
 	mutex_lock(&cam->s_mutex);
 	(cam->users)--;
 	if (cam->users == 0) {
@@ -1594,8 +1676,6 @@ static ssize_t mcam_v4l_read(struct file *filp,
 	return ret;
 }
 
-
-
 static unsigned int mcam_v4l_poll(struct file *filp,
 		struct poll_table_struct *pt)
 {
@@ -1608,7 +1688,6 @@ static unsigned int mcam_v4l_poll(struct file *filp,
 	return ret;
 }
 
-
 static int mcam_v4l_mmap(struct file *filp, struct vm_area_struct *vma)
 {
 	struct mcam_camera *cam = filp->private_data;
@@ -1620,8 +1699,6 @@ static int mcam_v4l_mmap(struct file *filp, struct vm_area_struct *vma)
 	return ret;
 }
 
-
-
 static const struct v4l2_file_operations mcam_v4l_fops = {
 	.owner = THIS_MODULE,
 	.open = mcam_v4l_open,
@@ -1632,7 +1709,6 @@ static const struct v4l2_file_operations mcam_v4l_fops = {
 	.unlocked_ioctl = video_ioctl2,
 };
 
-
 /*
  * This template device holds all of those v4l2 methods; we
  * clone it for specific real devices.
@@ -1647,6 +1723,672 @@ static struct video_device mcam_v4l_template = {
 	.release = video_device_release_empty,
 };
 
+#else  /* CONFIG_VIDEO_MRVL_SOC_CAMERA */
+
+static int mcam_config_phy(struct mcam_camera *mcam, int enable)
+{
+	if (mcam->bus_type == V4L2_MBUS_CSI2_LANES && enable) {
+		cam_dbg(mcam, "camera: DPHY3=0x%x, DPHY5=0x%x, DPHY6=0x%x\n",
+			(*mcam->dphy)[0], (*mcam->dphy)[1], (*mcam->dphy)[2]);
+		mcam_reg_write(mcam, REG_CSI2_DPHY3, (*mcam->dphy)[0]);
+		mcam_reg_write(mcam, REG_CSI2_DPHY6, (*mcam->dphy)[2]);
+		mcam_reg_write(mcam, REG_CSI2_DPHY5, (*mcam->dphy)[1]);
+
+		if (mcam->mipi_enabled == 0) {
+			/*
+			 * 0x41 actives 1 lane
+			 * 0x43 actives 2 lanes
+			 * 0x47 actives 4 lanes
+			 * There is no 3 lanes case
+			 */
+			if (mcam->lane == 1)
+				mcam_reg_write(mcam, REG_CSI2_CTRL0, 0x41);
+			else if (mcam->lane == 2)
+				mcam_reg_write(mcam, REG_CSI2_CTRL0, 0x43);
+			else if (mcam->lane == 4)
+				mcam_reg_write(mcam, REG_CSI2_CTRL0, 0x47);
+			else {
+				cam_err(mcam, "camera: lane number set err");
+				return -EINVAL;
+			}
+			mcam->mipi_enabled = 1;
+		}
+	} else {
+		mcam_reg_write(mcam, REG_CSI2_DPHY3, 0x0);
+		mcam_reg_write(mcam, REG_CSI2_DPHY6, 0x0);
+		mcam_reg_write(mcam, REG_CSI2_DPHY5, 0x0);
+		mcam_reg_write(mcam, REG_CSI2_CTRL0, 0x0);
+		mcam->mipi_enabled = 0;
+	}
+	return 0;
+}
+
+/*
+ * Get everything ready, and start grabbing frames.
+ */
+static int mcam_read_setup(struct mcam_camera *mcam)
+{
+	int ret = 0;
+
+	clear_bit(CF_DMA_ACTIVE, &mcam->flags);
+	mcam_reset_buffers(mcam);
+	ret = mcam_config_phy(mcam, 1);
+	if (ret < 0)
+		return ret;
+	mcam_ctlr_irq_enable(mcam);
+	mcam_ctlr_dma_contig(mcam);
+	mcam->state = S_STREAMING;
+	mcam_ctlr_start(mcam);
+
+	return 0;
+}
+
+void mcam_ctlr_reset(struct mcam_camera *mcam)
+{
+	unsigned long val;
+
+	/*
+	 * Used CCIC2
+	 */
+	if (mcam->ccic_id) {
+		val = readl(APMU_CCIC2_RST);
+		writel(val & ~0x2, APMU_CCIC2_RST);
+		writel(val | 0x2, APMU_CCIC2_RST);
+	}
+
+	val = readl(APMU_CCIC_RST);
+	writel(val & ~0x2, APMU_CCIC_RST);
+	writel(val | 0x2, APMU_CCIC_RST);
+}
+
+
+static int mcam_videobuf_setup(struct vb2_queue *vq,
+			const struct v4l2_format *fmt,
+			u32 *count, u32 *num_planes,
+			unsigned int sizes[], void *alloc_ctxs[])
+{
+	struct soc_camera_device *icd = container_of(vq,
+			struct soc_camera_device, vb2_vidq);
+	struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
+	struct mcam_camera *mcam = ici->priv;
+	int bytes_per_line = soc_mbus_bytes_per_line(icd->user_width,
+			icd->current_fmt->host_fmt);
+
+	int minbufs = 2;
+	if (*count < minbufs)
+		*count = minbufs;
+
+	if (bytes_per_line < 0)
+		return bytes_per_line;
+
+	*num_planes = 1;
+	sizes[0] = mcam->pix_format.sizeimage;
+	alloc_ctxs[0] = mcam->vb_alloc_ctx;
+	cam_dbg(mcam, "count = %d, size = %u\n", *count, sizes[0]);
+
+	return 0;
+}
+
+static int mcam_videobuf_prepare(struct vb2_buffer *vb)
+{
+	struct soc_camera_device *icd = container_of(vb->vb2_queue,
+			struct soc_camera_device, vb2_vidq);
+	struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
+	struct mcam_camera *mcam = ici->priv;
+	struct mcam_vb_buffer *buf =
+		container_of(vb, struct mcam_vb_buffer, vb_buf);
+	unsigned long size;
+	unsigned long flags = 0;
+	int bytes_per_line = soc_mbus_bytes_per_line(icd->user_width,
+			icd->current_fmt->host_fmt);
+
+	if (bytes_per_line < 0)
+		return bytes_per_line;
+
+	cam_dbg(mcam, "%s; (vb = 0x%p), 0x%p, %lu\n", __func__,
+		vb, vb2_plane_vaddr(vb, 0), vb2_get_plane_payload(vb, 0));
+	spin_lock_irqsave(&mcam->list_lock, flags);
+	/*
+	 * Added list head initialization on alloc
+	 */
+	WARN(!list_empty(&buf->queue), "Buffer %p on queue!\n", vb);
+	spin_unlock_irqrestore(&mcam->list_lock, flags);
+	BUG_ON(NULL == icd->current_fmt);
+	size = vb2_plane_size(vb, 0);
+	vb2_set_plane_payload(vb, 0, size);
+
+	return 0;
+}
+
+static void mcam_videobuf_queue(struct vb2_buffer *vb)
+{
+	struct soc_camera_device *icd = container_of(vb->vb2_queue,
+			struct soc_camera_device, vb2_vidq);
+	struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
+	struct mcam_camera *mcam = ici->priv;
+	struct mcam_vb_buffer *buf =
+		container_of(vb, struct mcam_vb_buffer, vb_buf);
+	unsigned long flags = 0;
+	int start;
+	dma_addr_t dma_handle;
+	u32 base_size = icd->user_width * icd->user_height;
+
+	mutex_lock(&mcam->s_mutex);
+	dma_handle = vb2_dma_contig_plane_dma_addr(vb, 0);
+	BUG_ON(!dma_handle);
+	spin_lock_irqsave(&mcam->list_lock, flags);
+	/*
+	 * Wait until two buffers already queued to the list
+	 * then start DMA
+	 */
+	start = (mcam->state == S_BUFWAIT) && !list_empty(&mcam->buffers);
+	spin_unlock_irqrestore(&mcam->list_lock, flags);
+
+	if (mcam->pix_format.pixelformat == V4L2_PIX_FMT_YUV422P) {
+		buf->yuv_p.y = dma_handle;
+		buf->yuv_p.u = buf->yuv_p.y + base_size;
+		buf->yuv_p.v = buf->yuv_p.u + base_size / 2;
+	} else if (mcam->pix_format.pixelformat == V4L2_PIX_FMT_YUV420) {
+		buf->yuv_p.y = dma_handle;
+		buf->yuv_p.u = buf->yuv_p.y + base_size;
+		buf->yuv_p.v = buf->yuv_p.u + base_size / 4;
+	} else if (mcam->pix_format.pixelformat == V4L2_PIX_FMT_YVU420) {
+		buf->yuv_p.y = dma_handle;
+		buf->yuv_p.v = buf->yuv_p.y + base_size;
+		buf->yuv_p.u = buf->yuv_p.v + base_size / 4;
+	} else {
+		buf->yuv_p.y = dma_handle;
+	}
+
+	spin_lock_irqsave(&mcam->list_lock, flags);
+	list_add_tail(&buf->queue, &mcam->buffers);
+	spin_unlock_irqrestore(&mcam->list_lock, flags);
+
+	if (start)
+		mcam_read_setup(mcam);
+	mutex_unlock(&mcam->s_mutex);
+}
+
+static void mcam_videobuf_cleanup(struct vb2_buffer *vb)
+{
+	struct mcam_vb_buffer *buf =
+		container_of(vb, struct mcam_vb_buffer, vb_buf);
+	struct soc_camera_device *icd = container_of(vb->vb2_queue,
+			struct soc_camera_device, vb2_vidq);
+	struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
+	struct mcam_camera *mcam = ici->priv;
+	unsigned long flags = 0;
+
+	spin_lock_irqsave(&mcam->list_lock, flags);
+	/*
+	 * queue list must be initialized before del
+	 */
+	if (buf->list_init_flag)
+		list_del_init(&buf->queue);
+	buf->list_init_flag = 0;
+	spin_unlock_irqrestore(&mcam->list_lock, flags);
+}
+
+/*
+ * only the list that queued could be initialized
+ */
+static int mcam_videobuf_init(struct vb2_buffer *vb)
+{
+	struct mcam_vb_buffer *buf =
+		container_of(vb, struct mcam_vb_buffer, vb_buf);
+	INIT_LIST_HEAD(&buf->queue);
+	buf->list_init_flag = 1;
+	return 0;
+}
+
+static int mcam_start_streaming(struct vb2_queue *vq, unsigned int count)
+{
+	struct soc_camera_device *icd = container_of(vq,
+			struct soc_camera_device, vb2_vidq);
+	struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
+	struct mcam_camera *mcam = ici->priv;
+	unsigned long flags = 0;
+	int ret = 0;
+
+	mutex_lock(&mcam->s_mutex);
+	if (count < 2) {
+		ret = -EINVAL;
+		goto out_unlock;
+	}
+
+	if (mcam->state != S_IDLE) {
+		ret = -EINVAL;
+		goto out_unlock;
+	}
+
+	/*
+	 * Videobuf2 sneakily hoards all the buffers and won't
+	 * give them to us until *after* streaming starts.	But
+	 * we can't actually start streaming until we have a
+	 * destination.	 So go into a wait state and hope they
+	 * give us buffers soon.
+	 */
+	spin_lock_irqsave(&mcam->list_lock, flags);
+	if (list_empty(&mcam->buffers)) {
+		mcam->state = S_BUFWAIT;
+		spin_unlock_irqrestore(&mcam->list_lock, flags);
+		ret = 0;
+		goto out_unlock;
+	}
+	spin_unlock_irqrestore(&mcam->list_lock, flags);
+
+	ret = mcam_read_setup(mcam);
+out_unlock:
+	mutex_unlock(&mcam->s_mutex);
+
+	return ret;
+}
+
+static int mcam_stop_streaming(struct vb2_queue *vq)
+{
+	struct soc_camera_device *icd = container_of(vq,
+			struct soc_camera_device, vb2_vidq);
+	struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
+	struct mcam_camera *mcam = ici->priv;
+	unsigned long flags = 0;
+	int ret = 0;
+
+	mutex_lock(&mcam->s_mutex);
+	if (mcam->state == S_BUFWAIT) {
+		/* They never gave us buffers */
+		mcam->state = S_IDLE;
+		goto out_unlock;
+	}
+
+	if (mcam->state != S_STREAMING) {
+		ret = -EINVAL;
+		goto out_unlock;
+	}
+
+	mcam_ctlr_stop_dma(mcam);
+	mcam->state = S_IDLE;
+	mcam_ctlr_reset(mcam);
+
+	spin_lock_irqsave(&mcam->list_lock, flags);
+	INIT_LIST_HEAD(&mcam->buffers);
+	spin_unlock_irqrestore(&mcam->list_lock, flags);
+out_unlock:
+	mutex_unlock(&mcam->s_mutex);
+
+	return ret;
+}
+
+static struct vb2_ops mcam_videobuf_ops = {
+	.queue_setup		= mcam_videobuf_setup,
+	.buf_prepare		= mcam_videobuf_prepare,
+	.buf_queue		= mcam_videobuf_queue,
+	.buf_cleanup		= mcam_videobuf_cleanup,
+	.buf_init		= mcam_videobuf_init,
+	.start_streaming	= mcam_start_streaming,
+	.stop_streaming		= mcam_stop_streaming,
+	.wait_prepare		= soc_camera_unlock,
+	.wait_finish		= soc_camera_lock,
+};
+
+static int mcam_camera_add_device(struct soc_camera_device *icd)
+{
+	struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
+	struct mcam_camera *mcam = ici->priv;
+	struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
+	int ret = 0;
+
+	if (mcam->icd)
+		return -EBUSY;
+
+	mcam->frame_complete = mcam_dma_contig_done;
+	mcam->frame_state.frames = 0;
+	mcam->frame_state.singles = 0;
+	mcam->frame_state.delivered = 0;
+
+	mcam->icd = icd;
+	mcam->state = S_IDLE;
+	mcam_ctlr_power_up(mcam);
+	mcam_ctlr_stop(mcam);
+	mcam_reg_write(mcam, REG_CTRL1,
+		mcam->burst | C1_RESERVED | C1_DMAPOSTED);
+	mcam_reg_write(mcam, REG_CLKCTRL,
+		(mcam->mclk_src << 29) | mcam->mclk_div);
+	cam_dbg(mcam, "camera: set sensor mclk = %dMHz\n", mcam->mclk_min);
+	/*
+	 * Need sleep 1ms to wait for CCIC stable
+	 * This is a workround for OV5640 MIPI
+	 * TODO: Fix me in the future
+	 */
+	usleep_range(1000, 2000);
+
+	/*
+	 * Mask all interrupts.
+	 */
+	mcam_reg_write(mcam, REG_IRQMASK, 0);
+	ret = v4l2_subdev_call(sd, core, init, 0);
+	/*
+	 * When v4l2_subdev_call return -ENOIOCTLCMD,
+	 * means No ioctl command
+	 */
+	if ((ret < 0) && (ret != -ENOIOCTLCMD) && (ret != -ENODEV)) {
+		dev_info(icd->parent,
+			"camera: Failed to initialize subdev: %d\n", ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static void mcam_camera_remove_device(struct soc_camera_device *icd)
+{
+	struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
+	struct mcam_camera *mcam = ici->priv;
+
+	BUG_ON(icd != mcam->icd);
+	cam_err(mcam, "Release %d frames, %d singles, %d delivered\n",
+		mcam->frame_state.frames, mcam->frame_state.singles,
+		mcam->frame_state.delivered);
+	mcam_config_phy(mcam, 0);
+	mcam_ctlr_power_down(mcam);
+	mcam->icd = NULL;
+}
+
+static int mcam_camera_set_fmt(struct soc_camera_device *icd,
+			struct v4l2_format *f)
+{
+	struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
+	struct mcam_camera *mcam = ici->priv;
+	struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
+	const struct soc_camera_format_xlate *xlate = NULL;
+	struct v4l2_mbus_framefmt mf;
+	struct v4l2_pix_format *pix = &f->fmt.pix;
+	struct v4l2_subdev_frame_interval inter;
+	int ret = 0;
+
+	cam_dbg(mcam, "camera: set_fmt: %c, width = %u, height = %u\n",
+		pix->pixelformat, pix->width, pix->height);
+	xlate = soc_camera_xlate_by_fourcc(icd, pix->pixelformat);
+	if (!xlate) {
+		cam_err(mcam, "camera: format: %c not found\n",
+			pix->pixelformat);
+		return -EINVAL;
+	}
+
+	mf.width = pix->width;
+	mf.height = pix->height;
+	mf.field = V4L2_FIELD_NONE;
+	mf.colorspace = pix->colorspace;
+	mf.code = xlate->code;
+
+	ret = v4l2_subdev_call(sd, video, s_mbus_fmt, &mf);
+	if (ret < 0) {
+		cam_err(mcam, "camera: set_fmt failed %d\n", __LINE__);
+		return ret;
+	}
+
+	if (mf.code != xlate->code) {
+		cam_err(mcam, "camera: wrong code %s %d\n", __func__, __LINE__);
+		return -EINVAL;
+	}
+
+	/*
+	 * To get frame_rate
+	 */
+	inter.pad = mcam->mclk_min;
+	ret = v4l2_subdev_call(sd, video, g_frame_interval, &inter);
+	if (ret < 0) {
+		cam_err(mcam, "camera: Can't get frame rate %s %d\n",
+			__func__, __LINE__);
+		mcam->frame_rate = 0;
+	} else
+		mcam->frame_rate =
+			inter.interval.numerator / inter.interval.denominator;
+
+	/*
+	 * Update CSI2_DPHY3 value
+	 */
+	mcam->calc_dphy(mcam, &inter);
+	cam_dbg(mcam, "camera: DPHY sets: dphy3=0x%x, dphy5=0x%x, dphy6=0x%x\n",
+			(*mcam->dphy)[0], (*mcam->dphy)[1], (*mcam->dphy)[2]);
+
+	pix->width = mf.width;
+	pix->height = mf.height;
+	pix->field = mf.field;
+	pix->colorspace = mf.colorspace;
+	mcam->pix_format.sizeimage = pix->sizeimage;
+	icd->current_fmt = xlate;
+
+	memcpy(&(mcam->pix_format), pix, sizeof(struct v4l2_pix_format));
+	ret = mcam_ctlr_image(mcam);
+
+	return ret;
+}
+
+static int mcam_camera_try_fmt(struct soc_camera_device *icd,
+			struct v4l2_format *f)
+{
+	struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
+	struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
+	struct mcam_camera *mcam = ici->priv;
+	const struct soc_camera_format_xlate *xlate;
+	struct v4l2_pix_format *pix = &f->fmt.pix;
+	struct v4l2_mbus_framefmt mf;
+	__u32 pixfmt = pix->pixelformat;
+	int ret = 0;
+
+	xlate = soc_camera_xlate_by_fourcc(icd, pixfmt);
+	if (!xlate) {
+		cam_err(mcam, "camera: format: %c not found\n",
+			pix->pixelformat);
+		return -EINVAL;
+	}
+
+	pix->bytesperline = soc_mbus_bytes_per_line(pix->width,
+						xlate->host_fmt);
+	if (pix->bytesperline < 0)
+		return pix->bytesperline;
+	if (pix->pixelformat == V4L2_PIX_FMT_JPEG) {
+		/*
+		 * Todo: soc_camera_try_fmt could clear
+		 * sizeimage, we can't get the value from
+		 * userspace, just hard coding
+		 */
+		pix->bytesperline = 2048;
+	} else
+		pix->sizeimage = pix->height * pix->bytesperline;
+
+	/*
+	 * limit to sensor capabilities
+	 */
+	mf.width = pix->width;
+	mf.height = pix->height;
+	mf.field = V4L2_FIELD_NONE;
+	mf.colorspace = pix->colorspace;
+	mf.code = xlate->code;
+
+	ret = v4l2_subdev_call(sd, video, try_mbus_fmt, &mf);
+	if (ret < 0)
+		return ret;
+
+	pix->width = mf.width;
+	pix->height = mf.height;
+	pix->colorspace = mf.colorspace;
+
+	switch (mf.field) {
+	case V4L2_FIELD_ANY:
+	case V4L2_FIELD_NONE:
+		pix->field = V4L2_FIELD_NONE;
+		break;
+	default:
+		cam_err(mcam, "camera: Field type %d unsupported.\n", mf.field);
+		ret = -EINVAL;
+		break;
+	}
+
+	return ret;
+}
+
+static int mcam_camera_set_parm(struct soc_camera_device *icd,
+			struct v4l2_streamparm *para)
+{
+	return 0;
+}
+
+static int mcam_camera_init_videobuf(struct vb2_queue *q,
+			struct soc_camera_device *icd)
+{
+	q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+	q->io_modes = VB2_USERPTR | VB2_MMAP;
+	q->drv_priv = icd;
+	q->ops = &mcam_videobuf_ops;
+	q->mem_ops = &vb2_dma_contig_memops;
+	q->buf_struct_size = sizeof(struct mcam_vb_buffer);
+
+	return vb2_queue_init(q);
+}
+
+static unsigned int mcam_camera_poll(struct file *file, poll_table *pt)
+{
+	struct soc_camera_device *icd = file->private_data;
+
+	return vb2_poll(&icd->vb2_vidq, file, pt);
+}
+
+static int mcam_camera_querycap(struct soc_camera_host *ici,
+			struct v4l2_capability *cap)
+{
+	struct v4l2_dbg_chip_ident id;
+	struct mcam_camera *mcam = ici->priv;
+	struct soc_camera_device *icd = mcam->icd;
+	struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
+	int ret = 0;
+
+	cap->version = KERNEL_VERSION(0, 0, 5);
+	cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
+	ret = v4l2_subdev_call(sd, core, g_chip_ident, &id);
+	if (ret < 0) {
+		cam_err(mcam, "%s %d\n", __func__, __LINE__);
+		return ret;
+	}
+
+	strcpy(cap->card, mcam->card_name);
+	strncpy(cap->driver, (const char *)&(id.ident), 4);
+
+	return 0;
+}
+
+static int mcam_camera_set_bus_param(struct soc_camera_device *icd)
+{
+	struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
+	struct mcam_camera *mcam = ici->priv;
+	struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
+	struct v4l2_mbus_config cfg;
+	int ret = 0;
+
+	ret = v4l2_subdev_call(sd, video, g_mbus_config, &cfg);
+	if ((ret < 0) && (ret != -ENOIOCTLCMD) && (ret != -ENODEV)) {
+		cam_err(mcam, "%s %d\n", __func__, __LINE__);
+		return ret;
+	}
+
+	ret = v4l2_subdev_call(sd, video, s_mbus_config, &cfg);
+	if ((ret < 0) && (ret != -ENOIOCTLCMD) && (ret != -ENODEV)) {
+		cam_err(mcam, "%s %d\n", __func__, __LINE__);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int mcam_camera_get_formats(struct soc_camera_device *icd, u32 idx,
+			struct soc_camera_format_xlate	*xlate)
+{
+	struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
+	struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
+	struct mcam_camera *mcam = ici->priv;
+	enum v4l2_mbus_pixelcode code;
+	const struct soc_mbus_pixelfmt *fmt;
+	int formats = 0, ret = 0, i;
+
+	ret = v4l2_subdev_call(sd, video, enum_mbus_fmt, idx, &code);
+	if (ret < 0)
+		/*
+		 * No more formats
+		 */
+		return 0;
+
+	fmt = soc_mbus_get_fmtdesc(code);
+	if (!fmt) {
+		cam_err(mcam, "camera: Invalid format #%u: %d\n", idx, code);
+		return 0;
+	}
+
+	switch (code) {
+	/*
+	 * Refer to mbus_fmt struct
+	 */
+	case V4L2_MBUS_FMT_UYVY8_2X8:
+		/*
+		 * Add support for YUV420 and YUV422P
+		 */
+		formats = ARRAY_SIZE(mcam_formats);
+		if (xlate) {
+			for (i = 0; i < ARRAY_SIZE(mcam_formats); i++) {
+				xlate->host_fmt = &mcam_formats[i];
+				xlate->code = code;
+				xlate++;
+			}
+		}
+		return formats;
+	case V4L2_MBUS_FMT_JPEG_1X8:
+		if (xlate)
+			cam_err(mcam, "camera: Providing format: %s\n",
+				fmt->name);
+		break;
+	default:
+		/*
+		 * camera controller can not support
+		 * this format, which might supported by the sensor
+		 */
+		cam_warn(mcam, "camera: Not support fmt: %s\n", fmt->name);
+		return 0;
+	}
+
+	formats++;
+	if (xlate) {
+		xlate->host_fmt = fmt;
+		xlate->code = code;
+		xlate++;
+	}
+
+	return formats;
+}
+
+struct soc_camera_host_ops mcam_soc_camera_host_ops = {
+	.owner		= THIS_MODULE,
+	.add		= mcam_camera_add_device,
+	.remove		= mcam_camera_remove_device,
+	.set_fmt	= mcam_camera_set_fmt,
+	.try_fmt	= mcam_camera_try_fmt,
+	.set_parm	= mcam_camera_set_parm,
+	.init_videobuf2	= mcam_camera_init_videobuf,
+	.poll		= mcam_camera_poll,
+	.querycap	= mcam_camera_querycap,
+	.set_bus_param	= mcam_camera_set_bus_param,
+	.get_formats	= mcam_camera_get_formats,
+};
+
+int mcam_soc_camera_host_register(struct mcam_camera *mcam)
+{
+	mcam->soc_host.drv_name = "mmp-camera";
+	mcam->soc_host.ops = &mcam_soc_camera_host_ops;
+	mcam->soc_host.priv = mcam;
+	mcam->soc_host.v4l2_dev.dev = mcam->dev;
+	mcam->soc_host.nr = mcam->ccic_id;
+	return soc_camera_host_register(&mcam->soc_host);
+}
+#endif
+
 /* ---------------------------------------------------------------------- */
 /*
  * Interrupt handler stuff
@@ -1658,9 +2400,9 @@ static void mcam_frame_complete(struct mcam_camera *cam, int frame)
 	 */
 	set_bit(frame, &cam->flags);
 	clear_bit(CF_DMA_ACTIVE, &cam->flags);
+	cam->frame_state.frames++;
 	cam->next_buf = frame;
 	cam->buf_seq[frame] = ++(cam->sequence);
-	frames++;
 	/*
 	 * "This should never happen"
 	 */
@@ -1672,14 +2414,14 @@ static void mcam_frame_complete(struct mcam_camera *cam, int frame)
 	cam->frame_complete(cam, frame);
 }
 
-
 /*
  * The interrupt handler; this needs to be called from the
  * platform irq handler with the lock held.
  */
 int mccic_irq(struct mcam_camera *cam, unsigned int irqs)
 {
-	unsigned int frame, handled = 0;
+	unsigned int frame, handled = IRQ_NONE;
+	struct vb2_buffer *vbuf;
 
 	mcam_reg_write(cam, REG_IRQSTAT, FRAMEIRQS); /* Clear'em all */
 	/*
@@ -1693,9 +2435,11 @@ int mccic_irq(struct mcam_camera *cam, unsigned int irqs)
 	 * each time.
 	 */
 	for (frame = 0; frame < cam->nbufs; frame++)
-		if (irqs & (IRQ_EOF0 << frame)) {
+		if (irqs & (IRQ_EOF0 << frame) &&
+			test_bit(CF_FRAME_SOF0 + frame, &cam->flags)) {
 			mcam_frame_complete(cam, frame);
-			handled = 1;
+			handled = IRQ_HANDLED;
+			clear_bit(CF_FRAME_SOF0 + frame, &cam->flags);
 			if (cam->buffer_mode == B_DMA_sg)
 				break;
 		}
@@ -1704,11 +2448,16 @@ int mccic_irq(struct mcam_camera *cam, unsigned int irqs)
 	 * code assumes that we won't get multiple frame interrupts
 	 * at once; may want to rethink that.
 	 */
-	if (irqs & (IRQ_SOF0 | IRQ_SOF1 | IRQ_SOF2)) {
-		set_bit(CF_DMA_ACTIVE, &cam->flags);
-		handled = 1;
-		if (cam->buffer_mode == B_DMA_sg)
-			mcam_ctlr_stop(cam);
+	for (frame = 0; frame < cam->nbufs; frame++) {
+		if (irqs & (IRQ_SOF0 << frame)) {
+			set_bit(CF_DMA_ACTIVE, &cam->flags);
+			set_bit(CF_FRAME_SOF0 + frame, &cam->flags);
+			vbuf = &(cam->vb_bufs[frame]->vb_buf);
+			do_gettimeofday(&vbuf->v4l2_buf.timestamp);
+			handled = IRQ_HANDLED;
+			if (cam->buffer_mode == B_DMA_sg)
+				mcam_ctlr_stop(cam);
+		}
 	}
 	return handled;
 }
@@ -1717,6 +2466,7 @@ int mccic_irq(struct mcam_camera *cam, unsigned int irqs)
 /*
  * Registration and such.
  */
+#ifndef CONFIG_VIDEO_MRVL_SOC_CAMERA
 static struct ov7670_config sensor_cfg = {
 	/*
 	 * Exclude QCIF mode, because it only captures a tiny portion
@@ -1725,20 +2475,25 @@ static struct ov7670_config sensor_cfg = {
 	.min_width = 320,
 	.min_height = 240,
 };
-
+#endif
 
 int mccic_register(struct mcam_camera *cam)
 {
+#ifndef CONFIG_VIDEO_MRVL_SOC_CAMERA
 	struct i2c_board_info ov7670_info = {
 		.type = "ov7670",
 		.addr = 0x42 >> 1,
 		.platform_data = &sensor_cfg,
 	};
+#endif
 	int ret;
 
 	/*
 	 * Validate the requested buffer mode.
 	 */
+
+	/* Only support B_DMA_contig mode in soc camera currently */
+#ifndef CONFIG_VIDEO_MRVL_SOC_CAMERA
 	if (buffer_mode >= 0)
 		cam->buffer_mode = buffer_mode;
 	if (cam->buffer_mode == B_DMA_sg &&
@@ -1747,24 +2502,27 @@ int mccic_register(struct mcam_camera *cam)
 			"attempting vmalloc mode instead\n");
 		cam->buffer_mode = B_vmalloc;
 	}
+#endif
 	if (!mcam_buffer_mode_supported(cam->buffer_mode)) {
 		printk(KERN_ERR "marvell-cam: buffer mode %d unsupported\n",
 				cam->buffer_mode);
 		return -EINVAL;
 	}
+#ifndef CONFIG_VIDEO_MRVL_SOC_CAMERA
 	/*
 	 * Register with V4L
 	 */
 	ret = v4l2_device_register(cam->dev, &cam->v4l2_dev);
 	if (ret)
 		return ret;
-
+#endif
 	mutex_init(&cam->s_mutex);
 	cam->state = S_NOTREADY;
 	mcam_set_config_needed(cam, 1);
 	cam->pix_format = mcam_def_pix_format;
 	cam->mbus_code = mcam_def_mbus_code;
 	INIT_LIST_HEAD(&cam->buffers);
+#ifndef CONFIG_VIDEO_MRVL_SOC_CAMERA
 	mcam_ctlr_init(cam);
 
 	/*
@@ -1809,10 +2567,10 @@ out:
 	return ret;
 out_unregister:
 	v4l2_device_unregister(&cam->v4l2_dev);
+#endif
 	return ret;
 }
 
-
 void mccic_shutdown(struct mcam_camera *cam)
 {
 	/*
@@ -1828,8 +2586,10 @@ void mccic_shutdown(struct mcam_camera *cam)
 	vb2_queue_release(&cam->vb_queue);
 	if (cam->buffer_mode == B_vmalloc)
 		mcam_free_dma_bufs(cam);
+#ifndef CONFIG_VIDEO_MRVL_SOC_CAMERA
 	video_unregister_device(&cam->vdev);
 	v4l2_device_unregister(&cam->v4l2_dev);
+#endif
 }
 
 /*
diff --git a/drivers/media/platform/marvell-ccic/mcam-core.h b/drivers/media/platform/marvell-ccic/mcam-core.h
index bd6acba..b7d8b17 100755
--- a/drivers/media/platform/marvell-ccic/mcam-core.h
+++ b/drivers/media/platform/marvell-ccic/mcam-core.h
@@ -2,6 +2,12 @@
  * Marvell camera core structures.
  *
  * Copyright 2011 Jonathan Corbet corbet@xxxxxxx
+ *
+ * History:
+ * Support Soc Camera
+ * Support MIPI interface and Dual CCICs in Soc Camera mode
+ * Sep-2012: Libin Yang <lbyang@xxxxxxxxxxx>
+ *           Albert Wang <twang13@xxxxxxxxxxx>
  */
 #ifndef _MCAM_CORE_H
 #define _MCAM_CORE_H
@@ -18,7 +24,6 @@
 #if defined(CONFIG_VIDEOBUF2_VMALLOC) || defined(CONFIG_VIDEOBUF2_VMALLOC_MODULE)
 #define MCAM_MODE_VMALLOC 1
 #endif
-
 #if defined(CONFIG_VIDEOBUF2_DMA_CONTIG) || defined(CONFIG_VIDEOBUF2_DMA_CONTIG_MODULE)
 #define MCAM_MODE_DMA_CONTIG 1
 #endif
@@ -32,7 +37,6 @@
 #error One of the videobuf buffer modes must be selected in the config
 #endif
 
-
 enum mcam_state {
 	S_NOTREADY,	/* Not yet initialized */
 	S_IDLE,		/* Just hanging around */
@@ -40,6 +44,7 @@ enum mcam_state {
 	S_STREAMING,	/* Streaming data */
 	S_BUFWAIT	/* streaming requested but no buffers yet */
 };
+
 #define MAX_DMA_BUFS 3
 
 /*
@@ -73,6 +78,35 @@ static inline int mcam_buffer_mode_supported(enum mcam_buffer_mode mode)
 	}
 }
 
+struct yuv_pointer_t {
+	dma_addr_t y;
+	dma_addr_t u;
+	dma_addr_t v;
+};
+
+/*
+ * Our buffer type for working with videobuf2.  Note that the vb2
+ * developers have decreed that struct vb2_buffer must be at the
+ * beginning of this structure.
+ */
+struct mcam_vb_buffer {
+	struct vb2_buffer vb_buf;
+	struct list_head queue;
+	struct mcam_dma_desc *dma_desc;	/* Descriptor virtual address */
+	dma_addr_t dma_desc_pa;		/* Descriptor physical address */
+	int dma_desc_nent;		/* Number of mapped descriptors */
+	struct yuv_pointer_t yuv_p;
+	int list_init_flag;
+};
+
+/*
+ * Basic frame states
+ */
+struct mmp_frame_state {
+	unsigned int frames;
+	unsigned int singles;
+	unsigned int delivered;
+};
 
 /*
  * A description of one of our devices.
@@ -81,10 +115,15 @@ static inline int mcam_buffer_mode_supported(enum mcam_buffer_mode mode)
  *          dev_lock is also required for access to device registers.
  */
 struct mcam_camera {
+#ifdef CONFIG_VIDEO_MRVL_SOC_CAMERA
+	struct soc_camera_host soc_host;
+	struct soc_camera_device *icd;
+#endif
 	/*
 	 * These fields should be set by the platform code prior to
 	 * calling mcam_register().
 	 */
+	spinlock_t list_lock;
 	struct i2c_adapter *i2c_adapter;
 	unsigned char __iomem *regs;
 	spinlock_t dev_lock;
@@ -93,11 +132,17 @@ struct mcam_camera {
 	short int clock_speed;	/* Sensor clock speed, default 30 */
 	short int use_smbus;	/* SMBUS or straight I2c? */
 	enum mcam_buffer_mode buffer_mode;
-	/*
-	 * Callbacks from the core to the platform code.
-	 */
-	void (*plat_power_up) (struct mcam_camera *cam);
-	void (*plat_power_down) (struct mcam_camera *cam);
+
+	int bus_type;
+	int ccic_id;
+	int (*dphy)[3];
+	int burst;
+	int mclk_min;
+	int mclk_src;
+	int mclk_div;
+	int mipi_enabled;
+	int lane;
+	char *card_name;
 
 	/*
 	 * Everything below here is private to the mcam core and
@@ -108,12 +153,24 @@ struct mcam_camera {
 	unsigned long flags;		/* Buffer status, mainly (dev_lock) */
 	int users;			/* How many open FDs */
 
+	int frame_rate;
+	struct mmp_frame_state frame_state;	/* Frame state counter */
+#ifndef CONFIG_VIDEO_MRVL_SOC_CAMERA
 	/*
 	 * Subsystem structures.
 	 */
 	struct video_device vdev;
 	struct v4l2_subdev *sensor;
 	unsigned short sensor_addr;
+	u32 sensor_type;		/* Currently ov7670 only */
+#endif
+	/*
+	 * Callbacks from the core to the platform code.
+	 */
+	void (*plat_power_up) (struct mcam_camera *cam);
+	void (*plat_power_down) (struct mcam_camera *cam);
+	void (*calc_dphy)(struct mcam_camera *cam,
+			struct v4l2_subdev_frame_interval *inter);
 
 	/* Videobuf2 stuff */
 	struct vb2_queue vb_queue;
@@ -141,7 +198,6 @@ struct mcam_camera {
 	void (*frame_complete)(struct mcam_camera *cam, int frame);
 
 	/* Current operating parameters */
-	u32 sensor_type;		/* Currently ov7670 only */
 	struct v4l2_pix_format pix_format;
 	enum v4l2_mbus_pixelcode mbus_code;
 
@@ -149,7 +205,6 @@ struct mcam_camera {
 	struct mutex s_mutex; /* Access to this structure */
 };
 
-
 /*
  * Register I/O functions.  These are here because the platform code
  * may legitimately need to mess with the register space.
@@ -169,7 +224,6 @@ static inline unsigned int mcam_reg_read(struct mcam_camera *cam,
 	return ioread32(cam->regs + reg);
 }
 
-
 static inline void mcam_reg_write_mask(struct mcam_camera *cam, unsigned int reg,
 		unsigned int val, unsigned int mask)
 {
@@ -201,6 +255,9 @@ void mccic_shutdown(struct mcam_camera *cam);
 void mccic_suspend(struct mcam_camera *cam);
 int mccic_resume(struct mcam_camera *cam);
 #endif
+#ifdef CONFIG_VIDEO_MRVL_SOC_CAMERA
+int mcam_soc_camera_host_register(struct mcam_camera *mcam);
+#endif
 
 /*
  * Register definitions for the m88alp01 camera interface.  Offsets in bytes
@@ -209,14 +266,31 @@ int mccic_resume(struct mcam_camera *cam);
 #define REG_Y0BAR	0x00
 #define REG_Y1BAR	0x04
 #define REG_Y2BAR	0x08
-/* ... */
+#define REG_U0BAR	0x0c
+#define REG_U1BAR	0x10
+#define REG_U2BAR	0x14
+#define REG_V0BAR	0x18
+#define REG_V1BAR	0x1C
+#define REG_V2BAR	0x20
+
+/*
+ * MIPI enable
+ */
+#define REG_CSI2_CTRL0	0x100
+#define REG_CSI2_DPHY3  0x12c
+#define REG_CSI2_DPHY5  0x134
+#define REG_CSI2_DPHY6  0x138
 
+/* ... */
 #define REG_IMGPITCH	0x24	/* Image pitch register */
 #define   IMGP_YP_SHFT	  2		/* Y pitch params */
 #define   IMGP_YP_MASK	  0x00003ffc	/* Y pitch field */
 #define	  IMGP_UVP_SHFT	  18		/* UV pitch (planar) */
 #define   IMGP_UVP_MASK   0x3ffc0000
+
 #define REG_IRQSTATRAW	0x28	/* RAW IRQ Status */
+#define REG_IRQMASK	0x2c	/* IRQ mask - same bits as IRQSTAT */
+#define REG_IRQSTAT	0x30	/* IRQ status / clear */
 #define   IRQ_EOF0	  0x00000001	/* End of frame 0 */
 #define   IRQ_EOF1	  0x00000002	/* End of frame 1 */
 #define   IRQ_EOF2	  0x00000004	/* End of frame 2 */
@@ -224,14 +298,10 @@ int mccic_resume(struct mcam_camera *cam);
 #define   IRQ_SOF1	  0x00000010	/* Start of frame 1 */
 #define   IRQ_SOF2	  0x00000020	/* Start of frame 2 */
 #define   IRQ_OVERFLOW	  0x00000040	/* FIFO overflow */
-#define   IRQ_TWSIW	  0x00010000	/* TWSI (smbus) write */
-#define   IRQ_TWSIR	  0x00020000	/* TWSI read */
-#define   IRQ_TWSIE	  0x00040000	/* TWSI error */
-#define   TWSIIRQS (IRQ_TWSIW|IRQ_TWSIR|IRQ_TWSIE)
-#define   FRAMEIRQS (IRQ_EOF0|IRQ_EOF1|IRQ_EOF2|IRQ_SOF0|IRQ_SOF1|IRQ_SOF2)
-#define   ALLIRQS (TWSIIRQS|FRAMEIRQS|IRQ_OVERFLOW)
-#define REG_IRQMASK	0x2c	/* IRQ mask - same bits as IRQSTAT */
-#define REG_IRQSTAT	0x30	/* IRQ status / clear */
+#define   FRAMEIRQS_EOF   (IRQ_EOF0 | IRQ_EOF1 | IRQ_EOF2)
+#define   FRAMEIRQS_SOF   (IRQ_SOF0 | IRQ_SOF1 | IRQ_SOF2)
+#define   FRAMEIRQS	  (FRAMEIRQS_EOF | FRAMEIRQS_SOF)
+#define   ALLIRQS	  (TWSIIRQS|FRAMEIRQS|IRQ_OVERFLOW)
 
 #define REG_IMGSIZE	0x34	/* Image size */
 #define  IMGSZ_V_MASK	  0x1fff0000
@@ -241,10 +311,8 @@ int mccic_resume(struct mcam_camera *cam);
 
 #define REG_CTRL0	0x3c	/* Control 0 */
 #define   C0_ENABLE	  0x00000001	/* Makes the whole thing go */
-
 /* Mask for all the format bits */
 #define   C0_DF_MASK	  0x00fffffc    /* Bits 2-23 */
-
 /* RGB ordering */
 #define	  C0_RGB4_RGBX	  0x00000000
 #define	  C0_RGB4_XRGB	  0x00000004
@@ -254,7 +322,6 @@ int mccic_resume(struct mcam_camera *cam);
 #define	  C0_RGB5_GRBG	  0x00000004
 #define	  C0_RGB5_GBRG	  0x00000008
 #define	  C0_RGB5_BGGR	  0x0000000c
-
 /* Spec has two fields for DIN and DOUT, but they must match, so
    combine them here. */
 #define	  C0_DF_YUV	  0x00000000	/* Data is YUV	    */
@@ -283,21 +350,28 @@ int mccic_resume(struct mcam_camera *cam);
 #define	  C0_DOWNSCALE	  0x08000000	/* Enable downscaler */
 #define	  C0_SIFM_MASK	  0xc0000000	/* SIF mode bits */
 #define	  C0_SIF_HVSYNC	  0x00000000	/* Use H/VSYNC */
-#define	  CO_SOF_NOSYNC	  0x40000000	/* Use inband active signaling */
+#define	  C0_SOF_NOSYNC	  0x40000000	/* Use inband active signaling */
+#define   C0_EOF_VSYNC	  0x00400000	/* Generate EOF by VSYNC */
+#define   C0_VEDGE_CTRL   0x00800000	/* Detecting falling edge of VSYNC */
 
 /* Bits below C1_444ALPHA are not present in Cafe */
 #define REG_CTRL1	0x40	/* Control 1 */
+#define   C1_RESERVED	  0x0000003c	/* Reserved and shouldn't be changed */
+#define   C1_444ALPHA	  0x00f00000	/* Alpha field in RGB444 */
 #define	  C1_CLKGATE	  0x00000001	/* Sensor clock gate */
 #define   C1_DESC_ENA	  0x00000100	/* DMA descriptor enable */
 #define   C1_DESC_3WORD   0x00000200	/* Three-word descriptors used */
 #define	  C1_444ALPHA	  0x00f00000	/* Alpha field in RGB444 */
 #define	  C1_ALPHA_SHFT	  20
-#define	  C1_DMAB32	  0x00000000	/* 32-byte DMA burst */
-#define	  C1_DMAB16	  0x02000000	/* 16-byte DMA burst */
-#define	  C1_DMAB64	  0x04000000	/* 64-byte DMA burst */
+#define	  C1_DMAB64	  0x00000000	/* 64-byte DMA burst */
+#define	  C1_DMAB128	  0x02000000	/* 128-byte DMA burst */
+#define	  C1_DMAB256	  0x04000000	/* 256-byte DMA burst */
 #define	  C1_DMAB_MASK	  0x06000000
 #define	  C1_TWOBUFS	  0x08000000	/* Use only two DMA buffers */
 #define	  C1_PWRDWN	  0x10000000	/* Power down */
+#define   C1_DMAPOSTED	  0x40000000	/* DMA Posted Select */
+
+#define REG_CTRL3	0x1ec	/* CCIC parallel mode */
 
 #define REG_CLKCTRL	0x88	/* Clock control */
 #define	  CLK_DIV_MASK	  0x0000ffff	/* Upper bits RW "reserved" */
-- 
1.7.0.4

--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Input]     [Video for Linux]     [Gstreamer Embedded]     [Mplayer Users]     [Linux USB Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]
  Powered by Linux