media i.MX27 camera: Fix field_count handling.
Commit Message
To properly detect frame loss the driver must keep
track of a frame_count.
Furthermore, field_count use was erroneous because
in progressive format this must be incremented twice.
Signed-off-by: Javier Martin <javier.martin@vista-silicon.com>
---
drivers/media/video/mx2_camera.c | 5 ++++-
drivers/media/video/mx2_emmaprp.c | 29 ++++++++++-------------------
2 files changed, 14 insertions(+), 20 deletions(-)
Comments
Argh,
sorry, there is a file here that souldn't be included.
I'll resend it again.
On 22 December 2011 16:05, Javier Martin
<javier.martin@vista-silicon.com> wrote:
> To properly detect frame loss the driver must keep
> track of a frame_count.
>
> Furthermore, field_count use was erroneous because
> in progressive format this must be incremented twice.
>
> Signed-off-by: Javier Martin <javier.martin@vista-silicon.com>
> ---
> drivers/media/video/mx2_camera.c | 5 ++++-
> drivers/media/video/mx2_emmaprp.c | 29 ++++++++++-------------------
> 2 files changed, 14 insertions(+), 20 deletions(-)
>
> diff --git a/drivers/media/video/mx2_camera.c b/drivers/media/video/mx2_camera.c
> index ea1f4dc..ca76dd2 100644
> --- a/drivers/media/video/mx2_camera.c
> +++ b/drivers/media/video/mx2_camera.c
> @@ -255,6 +255,7 @@ struct mx2_camera_dev {
> dma_addr_t discard_buffer_dma;
> size_t discard_size;
> struct mx2_fmt_cfg *emma_prp;
> + u32 frame_count;
> };
>
> /* buffer for one video frame */
> @@ -368,6 +369,7 @@ static int mx2_camera_add_device(struct soc_camera_device *icd)
> writel(pcdev->csicr1, pcdev->base_csi + CSICR1);
>
> pcdev->icd = icd;
> + pcdev->frame_count = 0;
>
> dev_info(icd->parent, "Camera driver attached to camera %d\n",
> icd->devnum);
> @@ -1211,7 +1213,8 @@ static void mx27_camera_frame_done_emma(struct mx2_camera_dev *pcdev,
> list_del(&vb->queue);
> vb->state = state;
> do_gettimeofday(&vb->ts);
> - vb->field_count++;
> + vb->field_count = pcdev->frame_count * 2;
> + pcdev->frame_count++;
>
> wake_up(&vb->done);
> }
> diff --git a/drivers/media/video/mx2_emmaprp.c b/drivers/media/video/mx2_emmaprp.c
> index 607b73f..fb87665 100644
> --- a/drivers/media/video/mx2_emmaprp.c
> +++ b/drivers/media/video/mx2_emmaprp.c
> @@ -16,6 +16,7 @@
> * Free Software Foundation; either version 2 of the
> * License, or (at your option) any later version
> */
> +
> #include <linux/module.h>
> #include <linux/clk.h>
> #include <linux/slab.h>
> @@ -35,7 +36,7 @@ MODULE_AUTHOR("Javier Martin <javier.martin@vista-silicon.com");
> MODULE_LICENSE("GPL");
> MODULE_VERSION("0.0.1");
>
> -static bool debug;
> +static bool debug = true;
> module_param(debug, bool, 0644);
>
> #define MIN_W 32
> @@ -250,10 +251,11 @@ static int emmaprp_job_ready(void *priv)
> {
> struct emmaprp_ctx *ctx = priv;
> struct emmaprp_dev *pcdev = ctx->dev;
> + struct dma_chan *chan = pcdev->dma_chan;
>
> if ((v4l2_m2m_num_src_bufs_ready(ctx->m2m_ctx) > 0)
> && (v4l2_m2m_num_dst_bufs_ready(ctx->m2m_ctx) > 0)
> - && (atomic_read(&pcdev->busy) == 0))
> + && (dma_async_memcpy_complete(chan, ctx->cookie, NULL, NULL) == 0))
> return 1;
>
> dprintk(pcdev, "Task not ready to run\n");
> @@ -290,10 +292,8 @@ static void emmaprp_unlock(void *priv)
> static void emmaprp_dma_callback(void *data)
> {
> struct emmaprp_dev *pcdev = (struct emmaprp_dev *)data;
> - struct dma_chan *chan = pcdev->dma_chan;
> struct vb2_buffer *src_vb, *dst_vb;
> struct emmaprp_ctx *curr_ctx;
> - enum dma_status status;
> unsigned long flags;
>
> curr_ctx = v4l2_m2m_get_curr_priv(pcdev->m2m_dev);
> @@ -306,26 +306,18 @@ static void emmaprp_dma_callback(void *data)
> if (curr_ctx->aborting)
> goto irq_ok;
>
> - status = dma_async_memcpy_complete(chan, curr_ctx->cookie, NULL, NULL);
> - if (status != DMA_SUCCESS) {
> - v4l2_warn(&pcdev->v4l2_dev,
> - "DMA got completion callback but status is \'%s\'\n",
> - status == DMA_ERROR ? "error" : "in progress");
> - goto irq_ok;
> - }
> -
> src_vb = v4l2_m2m_src_buf_remove(curr_ctx->m2m_ctx);
> dst_vb = v4l2_m2m_dst_buf_remove(curr_ctx->m2m_ctx);
> dst_vb->v4l2_buf.sequence = src_vb->v4l2_buf.sequence;
> -
> +printk("%s: dstbuf sequence =%d, srcbuf sequence = %d\n", __func__, dst_vb->v4l2_buf.sequence, src_vb->v4l2_buf.sequence);
> spin_lock_irqsave(&pcdev->irqlock, flags);
> v4l2_m2m_buf_done(src_vb, VB2_BUF_STATE_DONE);
> v4l2_m2m_buf_done(dst_vb, VB2_BUF_STATE_DONE);
> spin_unlock_irqrestore(&pcdev->irqlock, flags);
>
> irq_ok:
> - atomic_set(&pcdev->busy, 0);
> v4l2_m2m_job_finish(pcdev->m2m_dev, curr_ctx->m2m_ctx);
> +printk("DMA IRQ\n");
> }
>
> static void emmaprp_device_run(void *priv)
> @@ -342,7 +334,6 @@ static void emmaprp_device_run(void *priv)
> unsigned int d_size, s_size;
> dma_addr_t p_in, p_out;
> enum dma_ctrl_flags flags;
> - dma_cookie_t cookie;
>
> atomic_set(&ctx->dev->busy, 1);
>
> @@ -382,12 +373,12 @@ static void emmaprp_device_run(void *priv)
> }
> tx->callback = emmaprp_dma_callback;
> tx->callback_param = pcdev;
> - cookie = tx->tx_submit(tx);
> - ctx->cookie = cookie;
> - if (dma_submit_error(cookie)) {
> + ctx->cookie = tx->tx_submit(tx);
> +
> + if (dma_submit_error(ctx->cookie)) {
> v4l2_warn(&pcdev->v4l2_dev,
> "DMA submit error %d with src=0x%x dst=0x%x len=0x%x\n",
> - cookie, p_in, p_out, s_size * 3/2);
> + ctx->cookie, p_in, p_out, s_size * 3/2);
> return;
> }
> dma_async_issue_pending(chan);
> --
> 1.7.0.4
>
@@ -255,6 +255,7 @@ struct mx2_camera_dev {
dma_addr_t discard_buffer_dma;
size_t discard_size;
struct mx2_fmt_cfg *emma_prp;
+ u32 frame_count;
};
/* buffer for one video frame */
@@ -368,6 +369,7 @@ static int mx2_camera_add_device(struct soc_camera_device *icd)
writel(pcdev->csicr1, pcdev->base_csi + CSICR1);
pcdev->icd = icd;
+ pcdev->frame_count = 0;
dev_info(icd->parent, "Camera driver attached to camera %d\n",
icd->devnum);
@@ -1211,7 +1213,8 @@ static void mx27_camera_frame_done_emma(struct mx2_camera_dev *pcdev,
list_del(&vb->queue);
vb->state = state;
do_gettimeofday(&vb->ts);
- vb->field_count++;
+ vb->field_count = pcdev->frame_count * 2;
+ pcdev->frame_count++;
wake_up(&vb->done);
}
@@ -16,6 +16,7 @@
* Free Software Foundation; either version 2 of the
* License, or (at your option) any later version
*/
+
#include <linux/module.h>
#include <linux/clk.h>
#include <linux/slab.h>
@@ -35,7 +36,7 @@ MODULE_AUTHOR("Javier Martin <javier.martin@vista-silicon.com");
MODULE_LICENSE("GPL");
MODULE_VERSION("0.0.1");
-static bool debug;
+static bool debug = true;
module_param(debug, bool, 0644);
#define MIN_W 32
@@ -250,10 +251,11 @@ static int emmaprp_job_ready(void *priv)
{
struct emmaprp_ctx *ctx = priv;
struct emmaprp_dev *pcdev = ctx->dev;
+ struct dma_chan *chan = pcdev->dma_chan;
if ((v4l2_m2m_num_src_bufs_ready(ctx->m2m_ctx) > 0)
&& (v4l2_m2m_num_dst_bufs_ready(ctx->m2m_ctx) > 0)
- && (atomic_read(&pcdev->busy) == 0))
+ && (dma_async_memcpy_complete(chan, ctx->cookie, NULL, NULL) == 0))
return 1;
dprintk(pcdev, "Task not ready to run\n");
@@ -290,10 +292,8 @@ static void emmaprp_unlock(void *priv)
static void emmaprp_dma_callback(void *data)
{
struct emmaprp_dev *pcdev = (struct emmaprp_dev *)data;
- struct dma_chan *chan = pcdev->dma_chan;
struct vb2_buffer *src_vb, *dst_vb;
struct emmaprp_ctx *curr_ctx;
- enum dma_status status;
unsigned long flags;
curr_ctx = v4l2_m2m_get_curr_priv(pcdev->m2m_dev);
@@ -306,26 +306,18 @@ static void emmaprp_dma_callback(void *data)
if (curr_ctx->aborting)
goto irq_ok;
- status = dma_async_memcpy_complete(chan, curr_ctx->cookie, NULL, NULL);
- if (status != DMA_SUCCESS) {
- v4l2_warn(&pcdev->v4l2_dev,
- "DMA got completion callback but status is \'%s\'\n",
- status == DMA_ERROR ? "error" : "in progress");
- goto irq_ok;
- }
-
src_vb = v4l2_m2m_src_buf_remove(curr_ctx->m2m_ctx);
dst_vb = v4l2_m2m_dst_buf_remove(curr_ctx->m2m_ctx);
dst_vb->v4l2_buf.sequence = src_vb->v4l2_buf.sequence;
-
+printk("%s: dstbuf sequence =%d, srcbuf sequence = %d\n", __func__, dst_vb->v4l2_buf.sequence, src_vb->v4l2_buf.sequence);
spin_lock_irqsave(&pcdev->irqlock, flags);
v4l2_m2m_buf_done(src_vb, VB2_BUF_STATE_DONE);
v4l2_m2m_buf_done(dst_vb, VB2_BUF_STATE_DONE);
spin_unlock_irqrestore(&pcdev->irqlock, flags);
irq_ok:
- atomic_set(&pcdev->busy, 0);
v4l2_m2m_job_finish(pcdev->m2m_dev, curr_ctx->m2m_ctx);
+printk("DMA IRQ\n");
}
static void emmaprp_device_run(void *priv)
@@ -342,7 +334,6 @@ static void emmaprp_device_run(void *priv)
unsigned int d_size, s_size;
dma_addr_t p_in, p_out;
enum dma_ctrl_flags flags;
- dma_cookie_t cookie;
atomic_set(&ctx->dev->busy, 1);
@@ -382,12 +373,12 @@ static void emmaprp_device_run(void *priv)
}
tx->callback = emmaprp_dma_callback;
tx->callback_param = pcdev;
- cookie = tx->tx_submit(tx);
- ctx->cookie = cookie;
- if (dma_submit_error(cookie)) {
+ ctx->cookie = tx->tx_submit(tx);
+
+ if (dma_submit_error(ctx->cookie)) {
v4l2_warn(&pcdev->v4l2_dev,
"DMA submit error %d with src=0x%x dst=0x%x len=0x%x\n",
- cookie, p_in, p_out, s_size * 3/2);
+ ctx->cookie, p_in, p_out, s_size * 3/2);
return;
}
dma_async_issue_pending(chan);