#include "s5p_mfc_opr.h"
#include "s5p_mfc_cmd.h"
#include "s5p_mfc_pm.h"
+#ifdef CONFIG_EXYNOS_IOMMU
+#include <mach/sysmmu.h>
+#include <linux/of_platform.h>
+#endif
#define S5P_MFC_NAME "s5p-mfc"
#define S5P_MFC_DEC_NAME "s5p-mfc-dec"
.mmap = s5p_mfc_mmap,
};
-static int match_child(struct device *dev, void *data)
+#ifdef CONFIG_EXYNOS_IOMMU
+static int iommu_init(struct platform_device *pdev,
+ struct device *mfc_l,
+ struct device *mfc_r)
{
- if (!dev_name(dev))
- return 0;
- return !strcmp(dev_name(dev), (char *)data);
+ struct platform_device *pds;
+ struct dma_iommu_mapping *mapping;
+
+ pds = find_sysmmu_dt(pdev, "sysmmu_l");
+ if (pds == NULL) {
+ printk(KERN_ERR "no sysmmu_l found\n");
+ return -1;
+ }
+ platform_set_sysmmu(&pds->dev, mfc_l);
+ mapping = s5p_create_iommu_mapping(mfc_l, 0x20000000,
+ SZ_128M, 4, NULL);
+ if (mapping == NULL) {
+ printk(KERN_ERR "IOMMU mapping failed\n");
+ return -1;
+ }
+
+ pds = find_sysmmu_dt(pdev, "sysmmu_r");
+ if (pds == NULL) {
+ printk(KERN_ERR "no sysmmu_r found\n");
+ return -1;
+ }
+ platform_set_sysmmu(&pds->dev, mfc_r);
+ if (!s5p_create_iommu_mapping(mfc_r, 0x20000000,
+ SZ_128M, 4, mapping)) {
+ printk(KERN_ERR "IOMMU mapping failed\n");
+ return -1;
+ }
+
+ return 0;
}
+#endif
/* MFC probe function */
static int s5p_mfc_probe(struct platform_device *pdev)
goto err_res;
}
- dev->mem_dev_l = device_find_child(&dev->plat_dev->dev, "s5p-mfc-l",
- match_child);
+ dev->mem_dev_l = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL);
if (!dev->mem_dev_l) {
- mfc_err("Mem child (L) device get failed\n");
- ret = -ENODEV;
+ dev_err(&pdev->dev,
+ "Not enough memory for MFC left memory bank device\n");
+ ret = -ENOMEM;
goto err_res;
}
-
- dev->mem_dev_r = device_find_child(&dev->plat_dev->dev, "s5p-mfc-r",
- match_child);
+ dev->mem_dev_r = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL);
if (!dev->mem_dev_r) {
- mfc_err("Mem child (R) device get failed\n");
- ret = -ENODEV;
+ dev_err(&pdev->dev,
+ "Not enough memory for MFC right memory bank device\n");
+ ret = -ENOMEM;
goto err_res;
}
-
+#ifdef CONFIG_EXYNOS_IOMMU
+ dev->mem_dev_l->init_name = "mfc_l";
+ dev->mem_dev_r->init_name = "mfc_r";
+ if (iommu_init(pdev, dev->mem_dev_r, dev->mem_dev_l)) {
+ v4l2_err(&dev->v4l2_dev, "failed to initialize IOMMU\n");
+ goto err_iommu_init;
+ }
+#endif
dev->alloc_ctx[0] = vb2_dma_contig_init_ctx(dev->mem_dev_l);
if (IS_ERR_OR_NULL(dev->alloc_ctx[0])) {
ret = PTR_ERR(dev->alloc_ctx[0]);
vb2_dma_contig_cleanup_ctx(dev->alloc_ctx[1]);
err_mem_init_ctx_1:
vb2_dma_contig_cleanup_ctx(dev->alloc_ctx[0]);
+err_iommu_init:
err_res:
s5p_mfc_final_pm(dev);