diff options
author | Javier Martin <javier.martin@vista-silicon.com> | 2012-02-22 07:34:36 -0300 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2012-03-08 09:42:31 -0300 |
commit | d84279e6d7266e11bef19de4f624849daa70bc48 (patch) | |
tree | e8ff885e18f680aae3492cbb42bfc482dd2bf123 | |
parent | cdc9d6f191d81aa1b1b34db9d3a33f779f5c5ec7 (diff) |
[media] media i.MX27 camera: handle overflows properly
Signed-off-by: Javier Martin <javier.martin@vista-silicon.com>
Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
-rw-r--r-- | drivers/media/video/mx2_camera.c | 38 |
1 files changed, 19 insertions, 19 deletions
diff --git a/drivers/media/video/mx2_camera.c b/drivers/media/video/mx2_camera.c index fc5ffe47c558..32a9d76d69c8 100644 --- a/drivers/media/video/mx2_camera.c +++ b/drivers/media/video/mx2_camera.c @@ -1198,7 +1198,7 @@ static struct soc_camera_host_ops mx2_soc_camera_host_ops = { }; static void mx27_camera_frame_done_emma(struct mx2_camera_dev *pcdev, - int bufnum) + int bufnum, bool err) { struct mx2_fmt_cfg *prp = pcdev->emma_prp; struct mx2_buffer *buf; @@ -1245,7 +1245,10 @@ static void mx27_camera_frame_done_emma(struct mx2_camera_dev *pcdev, list_del_init(&buf->queue); do_gettimeofday(&vb->v4l2_buf.timestamp); vb->v4l2_buf.sequence = pcdev->frame_count; - vb2_buffer_done(vb, VB2_BUF_STATE_DONE); + if (err) + vb2_buffer_done(vb, VB2_BUF_STATE_ERROR); + else + vb2_buffer_done(vb, VB2_BUF_STATE_DONE); } pcdev->frame_count++; @@ -1296,21 +1299,18 @@ static irqreturn_t mx27_camera_emma_irq(int irq_emma, void *data) } if (status & (1 << 7)) { /* overflow */ - u32 cntl; - /* - * We only disable channel 1 here since this is the only - * enabled channel - * - * FIXME: the correct DMA overflow handling should be resetting - * the buffer, returning an error frame, and continuing with - * the next one. - */ - cntl = readl(pcdev->base_emma + PRP_CNTL); + u32 cntl = readl(pcdev->base_emma + PRP_CNTL); writel(cntl & ~(PRP_CNTL_CH1EN | PRP_CNTL_CH2EN), pcdev->base_emma + PRP_CNTL); writel(cntl, pcdev->base_emma + PRP_CNTL); - } - if (((status & (3 << 5)) == (3 << 5)) || + + buf = list_entry(pcdev->active_bufs.next, + struct mx2_buffer, queue); + mx27_camera_frame_done_emma(pcdev, + buf->bufnum, true); + + status &= ~(1 << 7); + } else if (((status & (3 << 5)) == (3 << 5)) || ((status & (3 << 3)) == (3 << 3))) { /* * Both buffers have triggered, process the one we're expecting @@ -1318,13 +1318,13 @@ static irqreturn_t mx27_camera_emma_irq(int irq_emma, void *data) */ buf = list_entry(pcdev->active_bufs.next, struct mx2_buffer, queue); - mx27_camera_frame_done_emma(pcdev, buf->bufnum); + mx27_camera_frame_done_emma(pcdev, buf->bufnum, false); status &= ~(1 << (6 - buf->bufnum)); /* mark processed */ + } else if ((status & (1 << 6)) || (status & (1 << 4))) { + mx27_camera_frame_done_emma(pcdev, 0, false); + } else if ((status & (1 << 5)) || (status & (1 << 3))) { + mx27_camera_frame_done_emma(pcdev, 1, false); } - if ((status & (1 << 6)) || (status & (1 << 4))) - mx27_camera_frame_done_emma(pcdev, 0); - if ((status & (1 << 5)) || (status & (1 << 3))) - mx27_camera_frame_done_emma(pcdev, 1); irq_ok: spin_unlock_irqrestore(&pcdev->lock, flags); |