Commit d78a4882 authored by Scott Jiang's avatar Scott Jiang Committed by Mauro Carvalho Chehab

[media] blackfin: add error frame support

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: default avatarScott Jiang <scott.jiang.linux@gmail.com>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent 1e204377
...@@ -91,8 +91,6 @@ struct bcap_device { ...@@ -91,8 +91,6 @@ struct bcap_device {
int num_sensor_formats; int num_sensor_formats;
/* pointing to current video buffer */ /* pointing to current video buffer */
struct bcap_buffer *cur_frm; struct bcap_buffer *cur_frm;
/* pointing to next video buffer */
struct bcap_buffer *next_frm;
/* buffer queue used in videobuf2 */ /* buffer queue used in videobuf2 */
struct vb2_queue buffer_queue; struct vb2_queue buffer_queue;
/* allocator-specific contexts for each plane */ /* allocator-specific contexts for each plane */
...@@ -455,10 +453,10 @@ static int bcap_stop_streaming(struct vb2_queue *vq) ...@@ -455,10 +453,10 @@ static int bcap_stop_streaming(struct vb2_queue *vq)
/* release all active buffers */ /* release all active buffers */
while (!list_empty(&bcap_dev->dma_queue)) { 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); struct bcap_buffer, list);
list_del(&bcap_dev->next_frm->list); list_del(&bcap_dev->cur_frm->list);
vb2_buffer_done(&bcap_dev->next_frm->vb, VB2_BUF_STATE_ERROR); vb2_buffer_done(&bcap_dev->cur_frm->vb, VB2_BUF_STATE_ERROR);
} }
return 0; return 0;
} }
...@@ -535,10 +533,21 @@ static irqreturn_t bcap_isr(int irq, void *dev_id) ...@@ -535,10 +533,21 @@ static irqreturn_t bcap_isr(int irq, void *dev_id)
spin_lock(&bcap_dev->lock); 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); v4l2_get_timestamp(&vb->v4l2_buf.timestamp);
if (ppi->err) {
vb2_buffer_done(vb, VB2_BUF_STATE_ERROR);
ppi->err = false;
} else {
vb2_buffer_done(vb, VB2_BUF_STATE_DONE); vb2_buffer_done(vb, VB2_BUF_STATE_DONE);
bcap_dev->cur_frm = bcap_dev->next_frm; }
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); ppi->ops->stop(ppi);
...@@ -546,13 +555,8 @@ static irqreturn_t bcap_isr(int irq, void *dev_id) ...@@ -546,13 +555,8 @@ static irqreturn_t bcap_isr(int irq, void *dev_id)
if (bcap_dev->stop) { if (bcap_dev->stop) {
complete(&bcap_dev->comp); complete(&bcap_dev->comp);
} else { } else {
if (!list_empty(&bcap_dev->dma_queue)) { addr = vb2_dma_contig_plane_dma_addr(&bcap_dev->cur_frm->vb, 0);
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); ppi->ops->update_addr(ppi, (unsigned long)addr);
}
ppi->ops->start(ppi); ppi->ops->start(ppi);
} }
...@@ -586,9 +590,8 @@ static int bcap_streamon(struct file *file, void *priv, ...@@ -586,9 +590,8 @@ static int bcap_streamon(struct file *file, void *priv,
} }
/* get the next frame from the dma queue */ /* 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); struct bcap_buffer, list);
bcap_dev->cur_frm = bcap_dev->next_frm;
/* remove buffer from the dma queue */ /* remove buffer from the dma queue */
list_del(&bcap_dev->cur_frm->list); list_del(&bcap_dev->cur_frm->list);
addr = vb2_dma_contig_plane_dma_addr(&bcap_dev->cur_frm->vb, 0); addr = vb2_dma_contig_plane_dma_addr(&bcap_dev->cur_frm->vb, 0);
......
...@@ -59,19 +59,30 @@ static irqreturn_t ppi_irq_err(int irq, void *dev_id) ...@@ -59,19 +59,30 @@ static irqreturn_t ppi_irq_err(int irq, void *dev_id)
* others are W1C * others are W1C
*/ */
status = bfin_read16(&reg->status); status = bfin_read16(&reg->status);
if (status & 0x3000)
ppi->err = true;
bfin_write16(&reg->status, 0xff00); bfin_write16(&reg->status, 0xff00);
break; break;
} }
case PPI_TYPE_EPPI: case PPI_TYPE_EPPI:
{ {
struct bfin_eppi_regs *reg = info->base; 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); bfin_write16(&reg->status, 0xffff);
break; break;
} }
case PPI_TYPE_EPPI3: case PPI_TYPE_EPPI3:
{ {
struct bfin_eppi3_regs *reg = info->base; 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); bfin_write32(&reg->stat, 0xc0ff);
break; break;
} }
......
...@@ -86,7 +86,8 @@ struct ppi_if { ...@@ -86,7 +86,8 @@ struct ppi_if {
unsigned long ppi_control; unsigned long ppi_control;
const struct ppi_ops *ops; const struct ppi_ops *ops;
const struct ppi_info *info; 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; void *priv;
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment