[PATCH 3/7] drm/exynos: add IOMMU support to drm fimd

Prathyush K prathyush.k at samsung.com
Wed Jul 11 02:39:59 PDT 2012


This patch adds device tree based IOMMU support to DRM FIMD. During
probe, the driver searches for a 'sysmmu' field in the device node. The
sysmmu field points to the corresponding sysmmu device of fimd.
This sysmmu device is retrieved and set as fimd's sysmmu. The common
IOMMU mapping created during DRM init is then attached to drm fimd.

Signed-off-by: Prathyush K <prathyush.k at samsung.com>
---
 drivers/gpu/drm/exynos/exynos_drm_fimd.c |   54 +++++++++++++++++++++++++++++-
 1 files changed, 53 insertions(+), 1 deletions(-)

diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
index 15b5286..6d4048a 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
@@ -19,7 +19,7 @@
 #include <linux/clk.h>
 #include <linux/pm_runtime.h>
 #include <linux/of.h>
-
+#include <linux/of_platform.h>
 #include <drm/exynos_drm.h>
 #include <plat/regs-fb-v4.h>
 
@@ -790,12 +790,56 @@ static int fimd_power_on(struct fimd_context *ctx, bool enable)
 }
 
 #ifdef CONFIG_OF
+
+#ifdef CONFIG_EXYNOS_IOMMU
+static int iommu_init(struct device *dev)
+{
+	struct platform_device *pds;
+	struct device_node *dn, *dns;
+	const __be32 *parp;
+	int ret;
+
+	dn = dev->of_node;
+	parp = of_get_property(dn, "sysmmu", NULL);
+	if (parp == NULL) {
+		dev_err(dev, "failed to find sysmmu property\n");
+		return -EINVAL;
+	}
+	dns = of_find_node_by_phandle(be32_to_cpup(parp));
+	if (dns == NULL) {
+		dev_err(dev, "failed to find sysmmu node\n");
+		return -EINVAL;
+	}
+	pds = of_find_device_by_node(dns);
+	if (pds == NULL) {
+		dev_err(dev, "failed to find sysmmu platform device\n");
+		return -EINVAL;
+	}
+
+	platform_set_sysmmu(&pds->dev, dev);
+	dev->dma_parms = kzalloc(sizeof(*dev->dma_parms), GFP_KERNEL);
+	if (!dev->dma_parms) {
+		dev_err(dev, "failed to allocate dma parms\n");
+		return -ENOMEM;
+	}
+	dma_set_max_seg_size(dev, 0xffffffffu);
+
+	ret = arm_iommu_attach_device(dev, exynos_drm_common_mapping);
+	if (ret) {
+		dev_err(dev, "failed to attach device\n");
+		return ret;
+	}
+	return 0;
+}
+#endif
+
 static struct exynos_drm_fimd_pdata *drm_fimd_dt_parse_pdata(struct device *dev)
 {
 	struct device_node *np = dev->of_node;
 	struct device_node *disp_np;
 	struct exynos_drm_fimd_pdata *pd;
 	u32 data[4];
+	int ret;
 
 	pd = kzalloc(sizeof(*pd), GFP_KERNEL);
 	if (!pd) {
@@ -803,6 +847,14 @@ static struct exynos_drm_fimd_pdata *drm_fimd_dt_parse_pdata(struct device *dev)
 		return ERR_PTR(-ENOMEM);
 	}
 
+#ifdef CONFIG_EXYNOS_IOMMU
+	ret = iommu_init(dev);
+	if (ret) {
+		dev_err(dev, "failed to initialize iommu\n");
+		return ERR_PTR(ret);
+	}
+#endif
+
 	if (of_get_property(np, "samsung,fimd-vidout-rgb", NULL))
 		pd->vidcon0 |= VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB;
 	if (of_get_property(np, "samsung,fimd-vidout-tv", NULL))
-- 
1.7.0.4



More information about the dri-devel mailing list