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 <[email protected]>
> ---
>  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 [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to