[PATCH 6/7] v4l: s5p-fimc: Add support for vb2-dma-iommu allocator
Marek Szyprowski
m.szyprowski at samsung.com
Tue Apr 5 10:06:49 EDT 2011
This patch adds support for videobuf2-dma-iommu allocator to s5p-fimc
driver. This allocator is selected only on systems that contains support
for S5P SYSMMU module (like EXYNOS4 platform). Otherwise the standard
videobuf2-dma-contig is used.
Signed-off-by: Marek Szyprowski <m.szyprowski at samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park at samsung.com>
---
drivers/media/video/Kconfig | 3 +-
drivers/media/video/s5p-fimc/fimc-capture.c | 4 +-
drivers/media/video/s5p-fimc/fimc-core.c | 24 ++++---
drivers/media/video/s5p-fimc/fimc-core.h | 1 +
drivers/media/video/s5p-fimc/fimc-mem.h | 103 +++++++++++++++++++++++++++
5 files changed, 122 insertions(+), 13 deletions(-)
create mode 100644 drivers/media/video/s5p-fimc/fimc-mem.h
diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig
index 40d7bcc..bf2d55d 100644
--- a/drivers/media/video/Kconfig
+++ b/drivers/media/video/Kconfig
@@ -1031,7 +1031,8 @@ config VIDEO_MEM2MEM_TESTDEV
config VIDEO_SAMSUNG_S5P_FIMC
tristate "Samsung S5P FIMC (video postprocessor) driver"
depends on VIDEO_DEV && VIDEO_V4L2 && PLAT_S5P
- select VIDEOBUF2_DMA_CONTIG
+ select VIDEOBUF2_DMA_IOMMU if S5P_SYSTEM_MMU
+ select VIDEOBUF2_DMA_CONTIG if !S5P_SYSTEM_MMU
select V4L2_MEM2MEM_DEV
help
This is a v4l2 driver for the S5P camera interface
diff --git a/drivers/media/video/s5p-fimc/fimc-capture.c b/drivers/media/video/s5p-fimc/fimc-capture.c
index f697ed1..714f0df 100644
--- a/drivers/media/video/s5p-fimc/fimc-capture.c
+++ b/drivers/media/video/s5p-fimc/fimc-capture.c
@@ -29,9 +29,9 @@
#include <media/v4l2-ioctl.h>
#include <media/v4l2-mem2mem.h>
#include <media/videobuf2-core.h>
-#include <media/videobuf2-dma-contig.h>
#include "fimc-core.h"
+#include "fimc-mem.h"
static struct v4l2_subdev *fimc_subdev_register(struct fimc_dev *fimc,
struct s5p_fimc_isp_info *isp_info)
@@ -884,7 +884,7 @@ int fimc_register_capture_device(struct fimc_dev *fimc)
q->io_modes = VB2_MMAP | VB2_USERPTR;
q->drv_priv = fimc->vid_cap.ctx;
q->ops = &fimc_capture_qops;
- q->mem_ops = &vb2_dma_contig_memops;
+ q->mem_ops = &fimc_vb2_allocator_memops;
q->buf_struct_size = sizeof(struct fimc_vid_buffer);
vb2_queue_init(q);
diff --git a/drivers/media/video/s5p-fimc/fimc-core.c b/drivers/media/video/s5p-fimc/fimc-core.c
index ead5c0a..594c471 100644
--- a/drivers/media/video/s5p-fimc/fimc-core.c
+++ b/drivers/media/video/s5p-fimc/fimc-core.c
@@ -27,9 +27,9 @@
#include <linux/clk.h>
#include <media/v4l2-ioctl.h>
#include <media/videobuf2-core.h>
-#include <media/videobuf2-dma-contig.h>
#include "fimc-core.h"
+#include "fimc-mem.h"
static char *fimc_clocks[MAX_FIMC_CLOCKS] = {
"sclk_fimc", "fimc", "sclk_cam"
@@ -457,7 +457,7 @@ int fimc_prepare_addr(struct fimc_ctx *ctx, struct vb2_buffer *vb,
dbg("memplanes= %d, colplanes= %d, pix_size= %d",
frame->fmt->memplanes, frame->fmt->colplanes, pix_size);
- paddr->y = vb2_dma_contig_plane_paddr(vb, 0);
+ paddr->y = fimc_vb2_plane_addr(vb, 0);
if (frame->fmt->memplanes == 1) {
switch (frame->fmt->colplanes) {
@@ -485,10 +485,10 @@ int fimc_prepare_addr(struct fimc_ctx *ctx, struct vb2_buffer *vb,
}
} else {
if (frame->fmt->memplanes >= 2)
- paddr->cb = vb2_dma_contig_plane_paddr(vb, 1);
+ paddr->cb = fimc_vb2_plane_addr(vb, 1);
if (frame->fmt->memplanes == 3)
- paddr->cr = vb2_dma_contig_plane_paddr(vb, 2);
+ paddr->cr = fimc_vb2_plane_addr(vb, 2);
}
dbg("PHYS_ADDR: y= 0x%X cb= 0x%X cr= 0x%X ret= %d",
@@ -1378,7 +1378,7 @@ static int queue_init(void *priv, struct vb2_queue *src_vq,
src_vq->io_modes = VB2_MMAP | VB2_USERPTR;
src_vq->drv_priv = ctx;
src_vq->ops = &fimc_qops;
- src_vq->mem_ops = &vb2_dma_contig_memops;
+ src_vq->mem_ops = &fimc_vb2_allocator_memops;
src_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
ret = vb2_queue_init(src_vq);
@@ -1390,7 +1390,7 @@ static int queue_init(void *priv, struct vb2_queue *src_vq,
dst_vq->io_modes = VB2_MMAP | VB2_USERPTR;
dst_vq->drv_priv = ctx;
dst_vq->ops = &fimc_qops;
- dst_vq->mem_ops = &vb2_dma_contig_memops;
+ dst_vq->mem_ops = &fimc_vb2_allocator_memops;
dst_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
return vb2_queue_init(dst_vq);
@@ -1688,12 +1688,15 @@ static int fimc_probe(struct platform_device *pdev)
goto err_clk;
}
- /* Initialize contiguous memory allocator */
- fimc->alloc_ctx = vb2_dma_contig_init_ctx(&fimc->pdev->dev);
+ /* Initialize memory allocator */
+ fimc->alloc_ctx = fimc_vb2_allocator_init(pdev, fimc);
if (IS_ERR(fimc->alloc_ctx)) {
ret = PTR_ERR(fimc->alloc_ctx);
goto err_irq;
}
+ ret = fimc_vb2_allocator_enable(fimc->alloc_ctx);
+ if (ret)
+ goto err_irq;
ret = fimc_register_m2m_device(fimc);
if (ret)
@@ -1750,7 +1753,8 @@ static int __devexit fimc_remove(struct platform_device *pdev)
fimc_clk_release(fimc);
- vb2_dma_contig_cleanup_ctx(fimc->alloc_ctx);
+ fimc_vb2_allocator_disable(fimc->alloc_ctx);
+ fimc_vb2_allocator_cleanup(fimc->alloc_ctx, fimc);
pm_runtime_disable(&pdev->dev);
@@ -1907,7 +1911,7 @@ static struct platform_device_id fimc_driver_ids[] = {
.name = "s5pv210-fimc",
.driver_data = (unsigned long)&fimc_drvdata_s5pv210,
}, {
- .name = "s5pv310-fimc",
+ .name = "exynos4-fimc",
.driver_data = (unsigned long)&fimc_drvdata_s5pv310,
},
{},
diff --git a/drivers/media/video/s5p-fimc/fimc-core.h b/drivers/media/video/s5p-fimc/fimc-core.h
index 3beb1e5..0f23547 100644
--- a/drivers/media/video/s5p-fimc/fimc-core.h
+++ b/drivers/media/video/s5p-fimc/fimc-core.h
@@ -423,6 +423,7 @@ struct fimc_dev {
struct fimc_vid_cap vid_cap;
unsigned long state;
struct vb2_alloc_ctx *alloc_ctx;
+ struct device *iommu_dev;
};
/**
diff --git a/drivers/media/video/s5p-fimc/fimc-mem.h b/drivers/media/video/s5p-fimc/fimc-mem.h
new file mode 100644
index 0000000..ed5cbb6
--- /dev/null
+++ b/drivers/media/video/s5p-fimc/fimc-mem.h
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2011 Samsung Electronics
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef FIMC_MEM_H_
+#define FIMC_MEM_H_
+
+/*
+ * fimc-mem.h is the interface for videbuf2 allocator. It is a proxy
+ * to real allocator depending on system capabilities.
+ * 1. on S5PC100 & S5PV210/S5PC110 systems vb2-dma-contig is used
+ * 2. on EXYNOS4 systems vb2-dma-iommu allocator is selected.
+ *
+ */
+
+#ifdef CONFIG_S5P_SYSTEM_MMU
+
+#include <plat/sysmmu.h>
+#include <media/videobuf2-dma-iommu.h>
+
+#define fimc_vb2_allocator_memops vb2_dma_iommu_memops
+
+static inline void *fimc_vb2_allocator_init(struct platform_device *pdev,
+ struct fimc_dev *fimc)
+{
+ struct device *iommu_dev = s5p_sysmmu_get(S5P_SYSMMU_FIMC0 + pdev->id);
+ void *ret;
+
+ if (!iommu_dev) {
+ dev_err(&pdev->dev, "SYSMMU get failed\n");
+ return ERR_PTR(-ENODEV);
+ }
+
+ ret = vb2_dma_iommu_init(&pdev->dev, iommu_dev, NULL);
+ if (IS_ERR(ret)) {
+ s5p_sysmmu_put(iommu_dev);
+ return ret;
+ }
+ fimc->iommu_dev = iommu_dev;
+ return ret;
+}
+
+static inline void fimc_vb2_allocator_cleanup(void *alloc_ctx,
+ struct fimc_dev *fimc)
+{
+ vb2_dma_iommu_cleanup(alloc_ctx);
+ s5p_sysmmu_put(fimc->iommu_dev);
+}
+
+static inline unsigned long fimc_vb2_plane_addr(struct vb2_buffer *b, int n)
+{
+ return vb2_dma_iommu_plane_addr(b, n);
+}
+
+static inline int fimc_vb2_allocator_enable(void *alloc_ctx)
+{
+ return vb2_dma_iommu_enable(alloc_ctx);
+}
+
+static inline int fimc_vb2_allocator_disable(void *alloc_ctx)
+{
+ return vb2_dma_iommu_disable(alloc_ctx);
+}
+
+#else /* use vb2-dma-contig allocator */
+
+#include <media/videobuf2-dma-contig.h>
+
+#define fimc_vb2_allocator_memops vb2_dma_contig_memops
+
+static inline void *fimc_vb2_allocator_init(struct platform_device *pdev,
+ struct fimc_dev *fimc)
+{
+ return vb2_dma_contig_init_ctx(&pdev->dev);
+}
+
+static inline void fimc_vb2_allocator_cleanup(void *alloc_ctx,
+ struct fimc_dev *fimc)
+{
+ vb2_dma_contig_cleanup_ctx(alloc_ctx);
+}
+
+static inline unsigned long fimc_vb2_plane_addr(struct vb2_buffer *b, int n)
+{
+ return vb2_dma_contig_plane_paddr(b, n);
+}
+
+static inline int fimc_vb2_allocator_enable(void *alloc_ctx)
+{
+ return 0;
+}
+
+static inline int fimc_vb2_allocator_disable(void *alloc_ctx)
+{
+ return 0;
+}
+
+#endif
+
+#endif /* FIMC_CORE_H_ */
--
1.7.1.569.g6f426
More information about the linux-arm-kernel
mailing list