All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 4/4] [media] marvell-ccic: core: add 3 frame buffers support in DMA_CONTIG mode
@ 2012-09-28 13:47 Albert Wang
  2012-09-29 19:51 ` Jonathan Corbet
  0 siblings, 1 reply; 3+ messages in thread
From: Albert Wang @ 2012-09-28 13:47 UTC (permalink / raw)
  To: corbet, g.liakhovetski; +Cc: linux-media, Albert Wang

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


^ permalink raw reply related	[flat|nested] 3+ messages in thread

* Re: [PATCH 4/4] [media] marvell-ccic: core: add 3 frame buffers support in DMA_CONTIG mode
  2012-09-28 13:47 [PATCH 4/4] [media] marvell-ccic: core: add 3 frame buffers support in DMA_CONTIG mode Albert Wang
@ 2012-09-29 19:51 ` Jonathan Corbet
  2012-10-05 13:18   ` Albert Wang
  0 siblings, 1 reply; 3+ messages in thread
From: Jonathan Corbet @ 2012-09-29 19:51 UTC (permalink / raw)
  To: Albert Wang; +Cc: g.liakhovetski, linux-media

On Fri, 28 Sep 2012 21:47:39 +0800
Albert Wang <twang13@marvell.com> wrote:

> 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

I have no problem with the concept.  I honestly don't remember why I
only used the two-buffer mode for dma-contig; perhaps it's because
getting even two buffers can be a bit of a challenge on a lot of
systems, maybe.  The application really needs to be able to get at
least four buffers for the three-buffer mode to be worthwhile
(otherwise you're always in a situation where the driver owns less than
three and has to juggle things).  But we can certainly add it.

I wish this were two patches, though:
	1) Change lots of int variables to unsigned int (with reasoning
	   as to why we want to do that).
	2) Add three-buffer mode.

The mode should be runtime-selectable, as it is with the vmalloc mode.

Otherwise seems OK.

Thanks,

jon

^ permalink raw reply	[flat|nested] 3+ messages in thread

* RE: [PATCH 4/4] [media] marvell-ccic: core: add 3 frame buffers support in DMA_CONTIG mode
  2012-09-29 19:51 ` Jonathan Corbet
@ 2012-10-05 13:18   ` Albert Wang
  0 siblings, 0 replies; 3+ messages in thread
From: Albert Wang @ 2012-10-05 13:18 UTC (permalink / raw)
  To: Jonathan Corbet; +Cc: g.liakhovetski, linux-media, Libin Yang

>From: Jonathan Corbet [mailto:corbet@lwn.net]
>Sent: Sunday, 30 September, 2012 03:51
>To: Albert Wang
>Cc: g.liakhovetski@gmx.de; linux-media@vger.kernel.org
>Subject: Re: [PATCH 4/4] [media] marvell-ccic: core: add 3 frame buffers support in
>DMA_CONTIG mode
>
>On Fri, 28 Sep 2012 21:47:39 +0800
>Albert Wang <twang13@marvell.com> wrote:
>
>> 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
>
>I have no problem with the concept.  I honestly don't remember why I only used the two-
>buffer mode for dma-contig; perhaps it's because getting even two buffers can be a bit
>of a challenge on a lot of systems, maybe.  The application really needs to be able to
>get at least four buffers for the three-buffer mode to be worthwhile (otherwise you're
>always in a situation where the driver owns less than three and has to juggle things).  But
>we can certainly add it.
>
Thank you for your review!
Sorry for late response.

>I wish this were two patches, though:
>	1) Change lots of int variables to unsigned int (with reasoning
>	   as to why we want to do that).
>	2) Add three-buffer mode.
>
OK. Your suggestion is reasonable.
We can do that in Version 2 of patches.

>The mode should be runtime-selectable, as it is with the vmalloc mode.
>
>Otherwise seems OK.
>
>Thanks,
>
>jon

Thanks
Albert Wang
86-21-61092656

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2012-10-05 13:56 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-09-28 13:47 [PATCH 4/4] [media] marvell-ccic: core: add 3 frame buffers support in DMA_CONTIG mode Albert Wang
2012-09-29 19:51 ` Jonathan Corbet
2012-10-05 13:18   ` Albert Wang

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.