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 |   59 +++++++++++++++++------
 drivers/media/platform/marvell-ccic/mcam-core.h |   11 +++++
 2 files changed, 55 insertions(+), 15 deletions(-)

diff --git a/drivers/media/platform/marvell-ccic/mcam-core.c 
b/drivers/media/platform/marvell-ccic/mcam-core.c
index 2d200d6..3b75594 100755
--- a/drivers/media/platform/marvell-ccic/mcam-core.c
+++ b/drivers/media/platform/marvell-ccic/mcam-core.c
@@ -401,13 +401,32 @@ 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;
 
-       /*
-        * 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.
@@ -416,15 +435,15 @@ static void mcam_set_contig_buffer(struct mcam_camera 
*cam, unsigned 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 (mcam_fmt_is_planar(fmt->pixelformat)) {
-               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);
        }
 }
 
@@ -433,10 +452,14 @@ static void mcam_set_contig_buffer(struct mcam_camera 
*cam, unsigned int frame)
  */
 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);
+       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);
 }
 
 /*
@@ -1043,6 +1066,12 @@ static int mcam_vb_start_streaming(struct vb2_queue *vq, 
unsigned int count)
        for (frame = 0; frame < cam->nbufs; frame++)
                clear_bit(CF_FRAME_SOF0 + frame, &cam->flags);
 
+       /*
+        *  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);
 }
 
diff --git a/drivers/media/platform/marvell-ccic/mcam-core.h 
b/drivers/media/platform/marvell-ccic/mcam-core.h
index 5b2cf6e..6420754 100755
--- a/drivers/media/platform/marvell-ccic/mcam-core.h
+++ b/drivers/media/platform/marvell-ccic/mcam-core.h
@@ -68,6 +68,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.
  */
@@ -105,6 +112,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;
 };
 
 /*
-- 
1.7.9.5

--
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