[media] blackfin: add error frame support
authorScott Jiang <scott.jiang.linux@gmail.com>
Fri, 18 Jan 2013 20:09:48 +0000 (17:09 -0300)
committerMauro Carvalho Chehab <mchehab@redhat.com>
Wed, 6 Feb 2013 11:16:58 +0000 (09:16 -0200)
Mark current frame as error frame when ppi error interrupt
report fifo error. Member next_frm in struct bcap_device can
be optimized out.

Signed-off-by: Scott Jiang <scott.jiang.linux@gmail.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
drivers/media/platform/blackfin/bfin_capture.c
drivers/media/platform/blackfin/ppi.c
include/media/blackfin/ppi.h

index 12e0faf534035b7ca12475a401d0335ad37506cb..5f209d5810dc9f43bfa3b225f76b9d914030803f 100644 (file)
@@ -91,8 +91,6 @@ struct bcap_device {
        int num_sensor_formats;
        /* pointing to current video buffer */
        struct bcap_buffer *cur_frm;
-       /* pointing to next video buffer */
-       struct bcap_buffer *next_frm;
        /* buffer queue used in videobuf2 */
        struct vb2_queue buffer_queue;
        /* allocator-specific contexts for each plane */
@@ -455,10 +453,10 @@ static int bcap_stop_streaming(struct vb2_queue *vq)
 
        /* release all active buffers */
        while (!list_empty(&bcap_dev->dma_queue)) {
-               bcap_dev->next_frm = list_entry(bcap_dev->dma_queue.next,
+               bcap_dev->cur_frm = list_entry(bcap_dev->dma_queue.next,
                                                struct bcap_buffer, list);
-               list_del(&bcap_dev->next_frm->list);
-               vb2_buffer_done(&bcap_dev->next_frm->vb, VB2_BUF_STATE_ERROR);
+               list_del(&bcap_dev->cur_frm->list);
+               vb2_buffer_done(&bcap_dev->cur_frm->vb, VB2_BUF_STATE_ERROR);
        }
        return 0;
 }
@@ -535,10 +533,21 @@ static irqreturn_t bcap_isr(int irq, void *dev_id)
 
        spin_lock(&bcap_dev->lock);
 
-       if (bcap_dev->cur_frm != bcap_dev->next_frm) {
+       if (!list_empty(&bcap_dev->dma_queue)) {
                v4l2_get_timestamp(&vb->v4l2_buf.timestamp);
-               vb2_buffer_done(vb, VB2_BUF_STATE_DONE);
-               bcap_dev->cur_frm = bcap_dev->next_frm;
+               if (ppi->err) {
+                       vb2_buffer_done(vb, VB2_BUF_STATE_ERROR);
+                       ppi->err = false;
+               } else {
+                       vb2_buffer_done(vb, VB2_BUF_STATE_DONE);
+               }
+               bcap_dev->cur_frm = list_entry(bcap_dev->dma_queue.next,
+                               struct bcap_buffer, list);
+               list_del(&bcap_dev->cur_frm->list);
+       } else {
+               /* clear error flag, we will get a new frame */
+               if (ppi->err)
+                       ppi->err = false;
        }
 
        ppi->ops->stop(ppi);
@@ -546,13 +555,8 @@ static irqreturn_t bcap_isr(int irq, void *dev_id)
        if (bcap_dev->stop) {
                complete(&bcap_dev->comp);
        } else {
-               if (!list_empty(&bcap_dev->dma_queue)) {
-                       bcap_dev->next_frm = list_entry(bcap_dev->dma_queue.next,
-                                               struct bcap_buffer, list);
-                       list_del(&bcap_dev->next_frm->list);
-                       addr = vb2_dma_contig_plane_dma_addr(&bcap_dev->next_frm->vb, 0);
-                       ppi->ops->update_addr(ppi, (unsigned long)addr);
-               }
+               addr = vb2_dma_contig_plane_dma_addr(&bcap_dev->cur_frm->vb, 0);
+               ppi->ops->update_addr(ppi, (unsigned long)addr);
                ppi->ops->start(ppi);
        }
 
@@ -586,9 +590,8 @@ static int bcap_streamon(struct file *file, void *priv,
        }
 
        /* get the next frame from the dma queue */
-       bcap_dev->next_frm = list_entry(bcap_dev->dma_queue.next,
+       bcap_dev->cur_frm = list_entry(bcap_dev->dma_queue.next,
                                        struct bcap_buffer, list);
-       bcap_dev->cur_frm = bcap_dev->next_frm;
        /* remove buffer from the dma queue */
        list_del(&bcap_dev->cur_frm->list);
        addr = vb2_dma_contig_plane_dma_addr(&bcap_dev->cur_frm->vb, 0);
index 1e24584605f28a63aa1231b0085bab6779a7a0b0..01b5b501347eebdb5a540863acead54dba2a56db 100644 (file)
@@ -59,19 +59,30 @@ static irqreturn_t ppi_irq_err(int irq, void *dev_id)
                 * others are W1C
                 */
                status = bfin_read16(&reg->status);
+               if (status & 0x3000)
+                       ppi->err = true;
                bfin_write16(&reg->status, 0xff00);
                break;
        }
        case PPI_TYPE_EPPI:
        {
                struct bfin_eppi_regs *reg = info->base;
+               unsigned short status;
+
+               status = bfin_read16(&reg->status);
+               if (status & 0x2)
+                       ppi->err = true;
                bfin_write16(&reg->status, 0xffff);
                break;
        }
        case PPI_TYPE_EPPI3:
        {
                struct bfin_eppi3_regs *reg = info->base;
+               unsigned long stat;
 
+               stat = bfin_read32(&reg->stat);
+               if (stat & 0x2)
+                       ppi->err = true;
                bfin_write32(&reg->stat, 0xc0ff);
                break;
        }
index 65c467576b31e12ca70bc4191b717aedc41480d5..d0697f4edf87e4a336ddf1cb5a1263fd75931667 100644 (file)
@@ -86,7 +86,8 @@ struct ppi_if {
        unsigned long ppi_control;
        const struct ppi_ops *ops;
        const struct ppi_info *info;
-       bool err_int;
+       bool err_int; /* if we need request error interrupt */
+       bool err; /* if ppi has fifo error */
        void *priv;
 };