aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media
diff options
context:
space:
mode:
authorRobert Jarzmik <robert.jarzmik@free.fr>2009-03-31 02:44:22 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2009-04-06 20:43:46 -0400
commit8c62e221c71a0240f16ea8aa29609f93a68c2ff9 (patch)
tree9cdca5f3c8d2e7eff020a1c50ef42419ad1cad40 /drivers/media
parent256b02332a0ba1d7382d736d776e605be63ded17 (diff)
V4L/DVB (11322): pxa_camera: Fix overrun condition on last buffer
The last buffer queued will often overrun, as the DMA chain is finished, and the time the dma irq handler is activated, the QCI fifos are filled by the sensor. The fix is to ignore the overrun condition on the last queued buffer, and restart the capture only on intermediate buffers of the chain. Moreover, a fix was added to the very unlikely condition where in YUV422P mode, one channel overruns while another completes at the very same time. The capture is restarted after the overrun as before, but the other channel completion is now ignored. Signed-off-by: Robert Jarzmik <robert.jarzmik@free.fr> Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media')
-rw-r--r--drivers/media/video/pxa_camera.c25
1 files changed, 20 insertions, 5 deletions
diff --git a/drivers/media/video/pxa_camera.c b/drivers/media/video/pxa_camera.c
index a2f98ec14d9a..cfa113cedd3e 100644
--- a/drivers/media/video/pxa_camera.c
+++ b/drivers/media/video/pxa_camera.c
@@ -624,6 +624,7 @@ static void pxa_camera_stop_capture(struct pxa_camera_dev *pcdev)
624 cicr0 = __raw_readl(pcdev->base + CICR0) & ~CICR0_ENB; 624 cicr0 = __raw_readl(pcdev->base + CICR0) & ~CICR0_ENB;
625 __raw_writel(cicr0, pcdev->base + CICR0); 625 __raw_writel(cicr0, pcdev->base + CICR0);
626 626
627 pcdev->active = NULL;
627 dev_dbg(pcdev->dev, "%s\n", __func__); 628 dev_dbg(pcdev->dev, "%s\n", __func__);
628} 629}
629 630
@@ -697,7 +698,6 @@ static void pxa_camera_wakeup(struct pxa_camera_dev *pcdev,
697 698
698 if (list_empty(&pcdev->capture)) { 699 if (list_empty(&pcdev->capture)) {
699 pxa_camera_stop_capture(pcdev); 700 pxa_camera_stop_capture(pcdev);
700 pcdev->active = NULL;
701 for (i = 0; i < pcdev->channels; i++) 701 for (i = 0; i < pcdev->channels; i++)
702 pcdev->sg_tail[i] = NULL; 702 pcdev->sg_tail[i] = NULL;
703 return; 703 return;
@@ -765,10 +765,20 @@ static void pxa_camera_dma_irq(int channel, struct pxa_camera_dev *pcdev,
765 goto out; 765 goto out;
766 } 766 }
767 767
768 if (!pcdev->active) { 768 /*
769 dev_err(pcdev->dev, "DMA End IRQ with no active buffer!\n"); 769 * pcdev->active should not be NULL in DMA irq handler.
770 *
771 * But there is one corner case : if capture was stopped due to an
772 * overrun of channel 1, and at that same channel 2 was completed.
773 *
774 * When handling the overrun in DMA irq for channel 1, we'll stop the
775 * capture and restart it (and thus set pcdev->active to NULL). But the
776 * DMA irq handler will already be pending for channel 2. So on entering
777 * the DMA irq handler for channel 2 there will be no active buffer, yet
778 * that is normal.
779 */
780 if (!pcdev->active)
770 goto out; 781 goto out;
771 }
772 782
773 vb = &pcdev->active->vb; 783 vb = &pcdev->active->vb;
774 buf = container_of(vb, struct pxa_buffer, vb); 784 buf = container_of(vb, struct pxa_buffer, vb);
@@ -779,7 +789,12 @@ static void pxa_camera_dma_irq(int channel, struct pxa_camera_dev *pcdev,
779 status & DCSR_ENDINTR ? "EOF " : "", vb, DDADR(channel)); 789 status & DCSR_ENDINTR ? "EOF " : "", vb, DDADR(channel));
780 790
781 if (status & DCSR_ENDINTR) { 791 if (status & DCSR_ENDINTR) {
782 if (camera_status & overrun) { 792 /*
793 * It's normal if the last frame creates an overrun, as there
794 * are no more DMA descriptors to fetch from QCI fifos
795 */
796 if (camera_status & overrun &&
797 !list_is_last(pcdev->capture.next, &pcdev->capture)) {
783 dev_dbg(pcdev->dev, "FIFO overrun! CISR: %x\n", 798 dev_dbg(pcdev->dev, "FIFO overrun! CISR: %x\n",
784 camera_status); 799 camera_status);
785 pxa_camera_stop_capture(pcdev); 800 pxa_camera_stop_capture(pcdev);