This patch adds support of 3 frame buffers in DMA-contiguous mode.

In current DMA_CONTIG mode, only 2 frame buffers can be supported.
Actually, Marvell CCIC can support at most 3 frame buffers.

Currently 2 frame buffers mode will be used by default.
To use 3 frame buffers mode, can do:
  define MAX_FRAME_BUFS 3
in mcam-core.h

Signed-off-by: Albert Wang <twan...@marvell.com>
---
 drivers/media/platform/marvell-ccic/mcam-core.c |   87 
++++++++++++++++++--------
 drivers/media/platform/marvell-ccic/mcam-core.h |   15 ++++-
 2 files changed, 74 insertions(+), 28 deletions(-)

diff --git a/drivers/media/platform/marvell-ccic/mcam-core.c 
b/drivers/media/platform/marvell-ccic/mcam-core.c
index 4adb1ca..a805246 100755
--- a/drivers/media/platform/marvell-ccic/mcam-core.c
+++ b/drivers/media/platform/marvell-ccic/mcam-core.c
@@ -228,7 +228,7 @@ static inline struct mcam_vb_buffer *vb_to_mvb(struct 
vb2_buffer *vb)
 /*
  * Hand a completed buffer back to user space.
  */
-static void mcam_buffer_done(struct mcam_camera *cam, int frame,
+static void mcam_buffer_done(struct mcam_camera *cam, unsigned int frame,
                struct vb2_buffer *vbuf)
 {
        vbuf->v4l2_buf.bytesused = cam->pix_format.sizeimage;
@@ -255,7 +255,7 @@ static void mcam_buffer_done(struct mcam_camera *cam, int 
frame,
  */
 static void mcam_reset_buffers(struct mcam_camera *cam)
 {
-       int i;
+       unsigned int i;
 
        cam->next_buf = -1;
        for (i = 0; i < cam->nbufs; i++) {
@@ -306,7 +306,7 @@ static void mcam_ctlr_stop(struct mcam_camera *cam)
  */
 static int mcam_alloc_dma_bufs(struct mcam_camera *cam, int loadtime)
 {
-       int i;
+       unsigned int i;
 
        mcam_set_config_needed(cam, 1);
        if (loadtime)
@@ -347,7 +347,7 @@ static int mcam_alloc_dma_bufs(struct mcam_camera *cam, int 
loadtime)
 
 static void mcam_free_dma_bufs(struct mcam_camera *cam)
 {
-       int i;
+       unsigned int i;
 
        for (i = 0; i < cam->nbufs; i++) {
                dma_free_coherent(cam->dev, cam->dma_buf_size,
@@ -386,7 +386,7 @@ static void mcam_ctlr_dma_vmalloc(struct mcam_camera *cam)
 static void mcam_frame_tasklet(unsigned long data)
 {
        struct mcam_camera *cam = (struct mcam_camera *) data;
-       int i;
+       unsigned int i;
        unsigned long flags;
        struct mcam_vb_buffer *buf;
 
@@ -434,7 +434,7 @@ static int mcam_check_dma_buffers(struct mcam_camera *cam)
        return 0;
 }
 
-static void mcam_vmalloc_done(struct mcam_camera *cam, int frame)
+static void mcam_vmalloc_done(struct mcam_camera *cam, unsigned int frame)
 {
        tasklet_schedule(&cam->s_tasklet);
 }
@@ -471,20 +471,39 @@ static inline int mcam_check_dma_buffers(struct 
mcam_camera *cam)
  * space.  In this way, we always have a buffer to DMA to and don't
  * have to try to play games stopping and restarting the controller.
  */
-static void mcam_set_contig_buffer(struct mcam_camera *cam, int frame)
+static void mcam_set_contig_buffer(struct mcam_camera *cam, unsigned 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];
-               set_bit(CF_SINGLE_BUFFER, &cam->flags);
-               cam->frame_state.singles++;
+               /*
+                * If there are no available buffers
+                * go into single buffer mode
+                *
+                * If CCIC use Two Buffers mode
+                * will use another remaining frame buffer
+                * frame 0 -> buf 1
+                * frame 1 -> buf 0
+                *
+                * If CCIC use Three Buffers mode
+                * will use the 2rd remaining frame buffer
+                * frame 0 -> buf 2
+                * frame 1 -> buf 0
+                * frame 2 -> buf 1
+                */
+               buf = cam->vb_bufs[(frame + (MAX_FRAME_BUFS - 1))
+                                               % MAX_FRAME_BUFS];
+               if (cam->frame_state.tribufs == 0)
+                       cam->frame_state.tribufs++;
+               else {
+                       set_bit(CF_SINGLE_BUFFER, &cam->flags);
+                       cam->frame_state.singles++;
+                       if (cam->frame_state.tribufs < 2)
+                               cam->frame_state.tribufs++;
+               }
        } else {
                /*
                 * OK, we have a buffer we can use.
@@ -493,17 +512,16 @@ static void mcam_set_contig_buffer(struct mcam_camera 
*cam, int frame)
                                        queue);
                list_del_init(&buf->queue);
                clear_bit(CF_SINGLE_BUFFER, &cam->flags);
+               if (cam->frame_state.tribufs != (3 - MAX_FRAME_BUFS))
+                       cam->frame_state.tribufs--;
        }
        cam->vb_bufs[frame] = buf;
-       mcam_reg_write(cam, frame == 0 ?
-                       REG_Y0BAR : REG_Y1BAR, buf->yuv_p.y);
+       mcam_reg_write(cam, REG_Y0BAR + (frame << 2), 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);
+               mcam_reg_write(cam, REG_U0BAR + (frame << 2), buf->yuv_p.u);
+               mcam_reg_write(cam, REG_V0BAR + (frame << 2), buf->yuv_p.v);
        }
        spin_unlock_irqrestore(&cam->list_lock, flags);
 }
@@ -513,16 +531,20 @@ static void mcam_set_contig_buffer(struct mcam_camera 
*cam, int frame)
  */
 static void mcam_ctlr_dma_contig(struct mcam_camera *cam)
 {
-       cam->nbufs = 2;
-       mcam_set_contig_buffer(cam, 0);
-       mcam_set_contig_buffer(cam, 1);
-       mcam_reg_set_bit(cam, REG_CTRL1, C1_TWOBUFS);
+       unsigned int frame;
+
+       cam->nbufs = MAX_FRAME_BUFS;
+       for (frame = 0; frame < cam->nbufs; frame++)
+               mcam_set_contig_buffer(cam, frame);
+
+       if (cam->nbufs == 2)
+               mcam_reg_set_bit(cam, REG_CTRL1, C1_TWOBUFS);
 }
 
 /*
  * Frame completion handling.
  */
-static void mcam_dma_contig_done(struct mcam_camera *cam, int frame)
+static void mcam_dma_contig_done(struct mcam_camera *cam, unsigned int frame)
 {
        struct mcam_vb_buffer *buf = cam->vb_bufs[frame];
        unsigned long flags = 0;
@@ -600,7 +622,7 @@ static void mcam_ctlr_dma_sg(struct mcam_camera *cam)
  * safely change the DMA descriptor array here and restart things
  * (assuming there's another buffer waiting to go).
  */
-static void mcam_dma_sg_done(struct mcam_camera *cam, int frame)
+static void mcam_dma_sg_done(struct mcam_camera *cam, unsigned int frame)
 {
        struct mcam_vb_buffer *buf = cam->vb_bufs[0];
 
@@ -1077,6 +1099,13 @@ static int mcam_vb_start_streaming(struct vb2_queue *vq, 
unsigned int count)
                cam->state = S_BUFWAIT;
                return 0;
        }
+
+       /*
+        *  If CCIC use Two Buffers mode, init tribufs == 1
+        *  If CCIC use Three Buffers mode, init tribufs == 0
+        */
+       cam->frame_state.tribufs = 3 - MAX_FRAME_BUFS;
+
        return mcam_read_setup(cam);
 }
 
@@ -1977,6 +2006,12 @@ static int mcam_start_streaming(struct vb2_queue *vq, 
unsigned int count)
        }
        spin_unlock_irqrestore(&mcam->list_lock, flags);
 
+       /*
+        *  If CCIC use Two Buffers mode, init tribufs == 1
+        *  If CCIC use Three Buffers mode, init tribufs == 0
+        */
+       mcam->frame_state.tribufs = 3 - MAX_FRAME_BUFS;
+
        ret = mcam_read_setup(mcam);
 out_unlock:
        mutex_unlock(&mcam->s_mutex);
@@ -2393,7 +2428,7 @@ int mcam_soc_camera_host_register(struct mcam_camera 
*mcam)
 /*
  * Interrupt handler stuff
  */
-static void mcam_frame_complete(struct mcam_camera *cam, int frame)
+static void mcam_frame_complete(struct mcam_camera *cam, unsigned int frame)
 {
        /*
         * Basic frame housekeeping.
diff --git a/drivers/media/platform/marvell-ccic/mcam-core.h 
b/drivers/media/platform/marvell-ccic/mcam-core.h
index b7d8b17..f15d10d 100755
--- a/drivers/media/platform/marvell-ccic/mcam-core.h
+++ b/drivers/media/platform/marvell-ccic/mcam-core.h
@@ -48,6 +48,13 @@ enum mcam_state {
 #define MAX_DMA_BUFS 3
 
 /*
+ * CCIC can support at most 3 frame buffers in DMA_CONTIG buffer mode
+ * 2 - Use Two Buffers mode
+ * 3 - Use Three Buffers mode
+ */
+#define MAX_FRAME_BUFS 2 /* Current marvell-ccic used Two Buffers mode */
+
+/*
  * Different platforms work best with different buffer modes, so we
  * let the platform pick.
  */
@@ -106,6 +113,10 @@ struct mmp_frame_state {
        unsigned int frames;
        unsigned int singles;
        unsigned int delivered;
+       /*
+        * Only tribufs == 2 can enter single buffer mode
+        */
+       unsigned int tribufs;
 };
 
 /*
@@ -153,7 +164,7 @@ struct mcam_camera {
        unsigned long flags;            /* Buffer status, mainly (dev_lock) */
        int users;                      /* How many open FDs */
 
-       int frame_rate;
+       unsigned int frame_rate;
        struct mmp_frame_state frame_state;     /* Frame state counter */
 #ifndef CONFIG_VIDEO_MRVL_SOC_CAMERA
        /*
@@ -195,7 +206,7 @@ struct mcam_camera {
 
        /* Mode-specific ops, set at open time */
        void (*dma_setup)(struct mcam_camera *cam);
-       void (*frame_complete)(struct mcam_camera *cam, int frame);
+       void (*frame_complete)(struct mcam_camera *cam, unsigned int frame);
 
        /* Current operating parameters */
        struct v4l2_pix_format pix_format;
-- 
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