From: Libin Yang <lby...@marvell.com>

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 <twan...@marvell.com>
Signed-off-by: Libin Yang <lby...@marvell.com>
---
 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 cor...@lwn.net
+ *
+ * History:
+ * Support Soc Camera
+ * Support MIPI interface and Dual CCICs in Soc Camera mode
+ * Sep-2012: Libin Yang <lby...@marvell.com>
+ *           Albert Wang <twan...@marvell.com>
  */
 #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 cor...@lwn.net
+ *
+ * History:
+ * Support Soc Camera
+ * Support MIPI interface and Dual CCICs in Soc Camera mode
+ * Sep-2012: Libin Yang <lby...@marvell.com>
+ *           Albert Wang <twan...@marvell.com>
  */
 #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 majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to