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@xxxxxxxxxxx> Signed-off-by: Kyungmin Park <kyungmin.park@xxxxxxxxxxx> --- 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 | 104 +++++++++++++++++++++++++++ 5 files changed, 123 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..7b920a8 --- /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 -- To unsubscribe from this list: send the line "unsubscribe linux-media" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html