[v2,2/3] V4L2: OMAP: VOUT: dma map and unmap v4l2 buffers in qbuf and dqbuf
Commit Message
Add support to map the buffer using dma_map_single during qbuf which inturn
calls cache flush and unmap the same during dqbuf. This is done to prevent
the artifacts seen because of cache-coherency issues on OMAP4
Signed-off-by: Amber Jain <amber@ti.com>
---
Changes from v1:
- Changed the definition of address variables to be u32 instead of int.
- Removed extra typedef for size variable.
drivers/media/video/omap/omap_vout.c | 29 +++++++++++++++++++++++++++--
1 files changed, 27 insertions(+), 2 deletions(-)
Comments
> -----Original Message-----
> From: JAIN, AMBER
> Sent: Thursday, July 07, 2011 5:51 PM
> To: linux-media@vger.kernel.org
> Cc: Hiremath, Vaibhav; JAIN, AMBER
> Subject: [PATCH v2 2/3] V4L2: OMAP: VOUT: dma map and unmap v4l2 buffers
> in qbuf and dqbuf
>
> Add support to map the buffer using dma_map_single during qbuf which
> inturn
> calls cache flush and unmap the same during dqbuf. This is done to prevent
> the artifacts seen because of cache-coherency issues on OMAP4
>
> Signed-off-by: Amber Jain <amber@ti.com>
> ---
> Changes from v1:
> - Changed the definition of address variables to be u32 instead of int.
> - Removed extra typedef for size variable.
>
> drivers/media/video/omap/omap_vout.c | 29 +++++++++++++++++++++++++++--
> 1 files changed, 27 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/media/video/omap/omap_vout.c
> b/drivers/media/video/omap/omap_vout.c
> index 6cd3622..7d3410a 100644
> --- a/drivers/media/video/omap/omap_vout.c
> +++ b/drivers/media/video/omap/omap_vout.c
> @@ -37,6 +37,7 @@
> #include <linux/platform_device.h>
> #include <linux/irq.h>
> #include <linux/videodev2.h>
> +#include <linux/dma-mapping.h>
>
> #include <media/videobuf-dma-contig.h>
> #include <media/v4l2-device.h>
> @@ -778,6 +779,17 @@ static int omap_vout_buffer_prepare(struct
> videobuf_queue *q,
> vout->queued_buf_addr[vb->i] = (u8 *)
> omap_vout_uservirt_to_phys(vb->baddr);
> } else {
> + u32 addr, dma_addr;
> + unsigned long size;
> +
> + addr = (unsigned long) vout->buf_virt_addr[vb->i];
> + size = (unsigned long) vb->size;
> +
> + dma_addr = dma_map_single(vout->vid_dev->v4l2_dev.dev, (void
> *) addr,
> + size, DMA_TO_DEVICE);
> + if (dma_mapping_error(vout->vid_dev->v4l2_dev.dev, dma_addr))
> + v4l2_err(&vout->vid_dev->v4l2_dev, "dma_map_single
> failed\n");
> +
> vout->queued_buf_addr[vb->i] = (u8 *)vout->buf_phy_addr[vb-
> >i];
> }
>
> @@ -1567,15 +1579,28 @@ static int vidioc_dqbuf(struct file *file, void
> *fh, struct v4l2_buffer *b)
> struct omap_vout_device *vout = fh;
> struct videobuf_queue *q = &vout->vbq;
>
> + int ret;
> + u32 addr;
> + unsigned long size;
> + struct videobuf_buffer *vb;
> +
> + vb = q->bufs[b->index];
> +
> if (!vout->streaming)
> return -EINVAL;
>
> if (file->f_flags & O_NONBLOCK)
> /* Call videobuf_dqbuf for non blocking mode */
> - return videobuf_dqbuf(q, (struct v4l2_buffer *)b, 1);
> + ret = videobuf_dqbuf(q, (struct v4l2_buffer *)b, 1);
> else
> /* Call videobuf_dqbuf for blocking mode */
> - return videobuf_dqbuf(q, (struct v4l2_buffer *)b, 0);
> + ret = videobuf_dqbuf(q, (struct v4l2_buffer *)b, 0);
> +
> + addr = (unsigned long) vout->buf_phy_addr[vb->i];
> + size = (unsigned long) vb->size;
> + dma_unmap_single(vout->vid_dev->v4l2_dev.dev, addr,
> + size, DMA_TO_DEVICE);
> + return ret;
> }
>
> static int vidioc_streamon(struct file *file, void *fh, enum
> v4l2_buf_type i)
[Hiremath, Vaibhav] Acked-By: Vaibhav Hiremath <hvaibhav@ti.com>
Thanks,
Vaibhav
> --
> 1.7.1
--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
@@ -37,6 +37,7 @@
#include <linux/platform_device.h>
#include <linux/irq.h>
#include <linux/videodev2.h>
+#include <linux/dma-mapping.h>
#include <media/videobuf-dma-contig.h>
#include <media/v4l2-device.h>
@@ -778,6 +779,17 @@ static int omap_vout_buffer_prepare(struct videobuf_queue *q,
vout->queued_buf_addr[vb->i] = (u8 *)
omap_vout_uservirt_to_phys(vb->baddr);
} else {
+ u32 addr, dma_addr;
+ unsigned long size;
+
+ addr = (unsigned long) vout->buf_virt_addr[vb->i];
+ size = (unsigned long) vb->size;
+
+ dma_addr = dma_map_single(vout->vid_dev->v4l2_dev.dev, (void *) addr,
+ size, DMA_TO_DEVICE);
+ if (dma_mapping_error(vout->vid_dev->v4l2_dev.dev, dma_addr))
+ v4l2_err(&vout->vid_dev->v4l2_dev, "dma_map_single failed\n");
+
vout->queued_buf_addr[vb->i] = (u8 *)vout->buf_phy_addr[vb->i];
}
@@ -1567,15 +1579,28 @@ static int vidioc_dqbuf(struct file *file, void *fh, struct v4l2_buffer *b)
struct omap_vout_device *vout = fh;
struct videobuf_queue *q = &vout->vbq;
+ int ret;
+ u32 addr;
+ unsigned long size;
+ struct videobuf_buffer *vb;
+
+ vb = q->bufs[b->index];
+
if (!vout->streaming)
return -EINVAL;
if (file->f_flags & O_NONBLOCK)
/* Call videobuf_dqbuf for non blocking mode */
- return videobuf_dqbuf(q, (struct v4l2_buffer *)b, 1);
+ ret = videobuf_dqbuf(q, (struct v4l2_buffer *)b, 1);
else
/* Call videobuf_dqbuf for blocking mode */
- return videobuf_dqbuf(q, (struct v4l2_buffer *)b, 0);
+ ret = videobuf_dqbuf(q, (struct v4l2_buffer *)b, 0);
+
+ addr = (unsigned long) vout->buf_phy_addr[vb->i];
+ size = (unsigned long) vb->size;
+ dma_unmap_single(vout->vid_dev->v4l2_dev.dev, addr,
+ size, DMA_TO_DEVICE);
+ return ret;
}
static int vidioc_streamon(struct file *file, void *fh, enum v4l2_buf_type i)