summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorQuinn Jensen <quinn.jensen@freescale.com>2007-10-24 21:25:35 -0600
committerQuinn Jensen <quinn.jensen@freescale.com>2007-10-24 21:25:35 -0600
commitff6800822de641075a54e2ca84363708e172e282 (patch)
tree2ad414554ea394e2bef7ce010a8ed4d0096c2490
parent4465015d95c5e6b53cd5366597e9a34610641168 (diff)
CR ENGR00039921 v4l2: support L1 writeback cached buffers
Patch for CR ENGR00039921 v4l2: support L1 writeback cached buffers This patch makes MXC V4L2 output buffers L1 writeback cacheable. The L1 cache is flushed for each QBUF ioctl call if the buffer is mmapped. Applies to linux 2.6.22 kernel on MX3 platforms. http://www.bitshrine.org/gpp/linux-2.6.22-mx-CR-ENGR00039921-v4l2-support-L1-writeback-.patch
-rw-r--r--drivers/media/video/mxc/output/mxc_v4l2_output.c28
-rw-r--r--include/asm-arm/pgtable.h4
2 files changed, 26 insertions, 6 deletions
diff --git a/drivers/media/video/mxc/output/mxc_v4l2_output.c b/drivers/media/video/mxc/output/mxc_v4l2_output.c
index 1078ad26caaf..309700bb9d1f 100644
--- a/drivers/media/video/mxc/output/mxc_v4l2_output.c
+++ b/drivers/media/video/mxc/output/mxc_v4l2_output.c
@@ -26,6 +26,7 @@
#include <linux/fs.h>
#include <linux/delay.h>
#include <linux/platform_device.h>
+#include <asm/cacheflush.h>
#include <asm/io.h>
#include <asm/semaphore.h>
#include <linux/dma-mapping.h>
@@ -1194,13 +1195,19 @@ mxc_v4l2out_do_ioctl(struct inode *inode, struct file *file,
unsigned long lock_flags;
if ((buf->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) ||
- (index >= vout->buffer_cnt) || (buf->flags != 0)) {
+ (index >= vout->buffer_cnt)) {
retval = -EINVAL;
break;
}
dev_dbg(vdev->dev, "VIDIOC_QBUF: %d\n", buf->index);
+ /* mmapped buffers are L1 WB cached,
+ * so we need to clean them */
+ if (buf->flags & V4L2_BUF_FLAG_MAPPED) {
+ flush_cache_all();
+ }
+
spin_lock_irqsave(&g_lock, lock_flags);
memcpy(&(vout->v4l2_bufs[index]), buf, sizeof(*buf));
@@ -1473,6 +1480,7 @@ static int mxc_v4l2out_mmap(struct file *file, struct vm_area_struct *vma)
struct video_device *vdev = video_devdata(file);
unsigned long size = vma->vm_end - vma->vm_start;
int res = 0;
+ int i;
vout_data *vout = video_get_drvdata(vdev);
dev_dbg(vdev->dev, "pgoff=0x%lx, start=0x%lx, end=0x%lx\n",
@@ -1482,9 +1490,21 @@ static int mxc_v4l2out_mmap(struct file *file, struct vm_area_struct *vma)
if (down_interruptible(&vout->busy_lock))
return -EINTR;
- /* make buffers write-thru cacheable */
- vma->vm_page_prot = __pgprot(pgprot_val(vma->vm_page_prot) &
- ~L_PTE_BUFFERABLE);
+ for (i = 0; i < vout->buffer_cnt; i++) {
+ if ((vout->v4l2_bufs[i].m.offset ==
+ (vma->vm_pgoff << PAGE_SHIFT)) &&
+ (vout->v4l2_bufs[i].length >= size)) {
+ vout->v4l2_bufs[i].flags |= V4L2_BUF_FLAG_MAPPED;
+ break;
+ }
+ }
+ if (i == vout->buffer_cnt) {
+ res = -ENOBUFS;
+ goto mxc_mmap_exit;
+ }
+
+ /* make buffers inner write-back, outer write-thru cacheable */
+ vma->vm_page_prot = pgprot_outer_wrthru(vma->vm_page_prot);
if (remap_pfn_range(vma, vma->vm_start,
vma->vm_pgoff, size, vma->vm_page_prot)) {
diff --git a/include/asm-arm/pgtable.h b/include/asm-arm/pgtable.h
index e3af9215f959..feeb5486b525 100644
--- a/include/asm-arm/pgtable.h
+++ b/include/asm-arm/pgtable.h
@@ -298,8 +298,8 @@ PTE_BIT_FUNC(mkyoung, |= L_PTE_YOUNG);
/* Extended config for non-shared device attributes */
#define pgprot_nonshareddev(prot) __pgprot(pgprot_val(prot) | L_PTE_EXTENDED)
/* Extended configurations for inner writeback cacheable */
-#define pgprot_writealloc(prot) __pgprot(pgprot_val(prot) | L_PTE_EXTENDED & ~L_PTE_CACHEABLE)
-#define pgprot_outer_wrthru(prot) __pgprot(pgprot_val(prot) | L_PTE_EXTENDED & ~L_PTE_BUFFERABLE)
+#define pgprot_writealloc(prot) __pgprot((pgprot_val(prot) | L_PTE_EXTENDED) & ~L_PTE_CACHEABLE)
+#define pgprot_outer_wrthru(prot) __pgprot((pgprot_val(prot) | L_PTE_EXTENDED) & ~L_PTE_BUFFERABLE)
#define pgprot_outer_noncached(prot) __pgprot(pgprot_val(prot) | L_PTE_EXTENDED & ~(L_PTE_CACHEABLE | L_PTE_BUFFERABLE))