On Sat, 14 Mar 2009, Robert Jarzmik wrote: > The last buffer queued will often overrun, as the DMA chain > is finished, and the time the dma irq handler is activated, > the QIF 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@xxxxxxx> > --- > drivers/media/video/pxa_camera.c | 25 ++++++++++++++++++++----- > 1 files changed, 20 insertions(+), 5 deletions(-) > > diff --git a/drivers/media/video/pxa_camera.c b/drivers/media/video/pxa_camera.c > index a0ca982..35e54fc 100644 > --- a/drivers/media/video/pxa_camera.c > +++ b/drivers/media/video/pxa_camera.c > @@ -623,6 +623,7 @@ static void pxa_camera_stop_capture(struct pxa_camera_dev *pcdev) > cicr0 = __raw_readl(pcdev->base + CICR0) & ~CICR0_ENB; > __raw_writel(cicr0, pcdev->base + CICR0); > > + pcdev->active = NULL; > dev_dbg(pcdev->dev, "%s\n", __func__); > } > > @@ -696,7 +697,6 @@ static void pxa_camera_wakeup(struct pxa_camera_dev *pcdev, > > if (list_empty(&pcdev->capture)) { > pxa_camera_stop_capture(pcdev); > - pcdev->active = NULL; > for (i = 0; i < pcdev->channels; i++) > pcdev->sg_tail[i] = NULL; > return; > @@ -764,10 +764,20 @@ static void pxa_camera_dma_irq(int channel, struct pxa_camera_dev *pcdev, > goto out; > } > > - if (!pcdev->active) { > - dev_err(pcdev->dev, "DMA End IRQ with no active buffer!\n"); > + /* > + * pcdev->active should not be NULL in DMA irq handler. > + * > + * But there is one corner case : if capture was stopped due to an > + * overrun of channel 1, and at that same channel 2 was completed. > + * > + * When handling the overrun in DMA irq for channel 1, we'll stop the > + * capture and restart it (and thus set pcdev->active to NULL). But the > + * DMA irq handler will already be pending for channel 2. So on entering > + * the DMA irq handler for channel 2 there will be no active buffer, yet > + * that is normal. > + */ > + if (!pcdev->active) > goto out; > - } > > vb = &pcdev->active->vb; > buf = container_of(vb, struct pxa_buffer, vb); > @@ -778,7 +788,12 @@ static void pxa_camera_dma_irq(int channel, struct pxa_camera_dev *pcdev, > status & DCSR_ENDINTR ? "EOF " : "", vb, DDADR(channel)); > > if (status & DCSR_ENDINTR) { > - if (camera_status & overrun) { > + /* > + * It's normal if the last frame creates an overrun, as there > + * are no more DMA descriptors to fetch from QIF fifos > + */ > + if (camera_status & overrun > + && !list_is_last(pcdev->capture.next, &pcdev->capture)) { > dev_dbg(pcdev->dev, "FIFO overrun! CISR: %x\n", Please, put "&&" on the first line:-) > camera_status); > pxa_camera_stop_capture(pcdev); > -- > 1.5.6.5 Thanks Guennadi --- Guennadi Liakhovetski, Ph.D. Freelance Open-Source Software Developer -- To unsubscribe from this list: send the line "unsubscribe linux-media" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html