diff options
author | Quinn Jensen <quinn.jensen@freescale.com> | 2007-10-24 21:25:35 -0600 |
---|---|---|
committer | Quinn Jensen <quinn.jensen@freescale.com> | 2007-10-24 21:25:35 -0600 |
commit | ff6800822de641075a54e2ca84363708e172e282 (patch) | |
tree | 2ad414554ea394e2bef7ce010a8ed4d0096c2490 | |
parent | 4465015d95c5e6b53cd5366597e9a34610641168 (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.c | 28 | ||||
-rw-r--r-- | include/asm-arm/pgtable.h | 4 |
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)) |