[PATCH v6 03/15] drm/exynos: add drm_iommu_attach_device_if_possible()

Hyungwon Hwang human.hwang at samsung.com
Fri Jun 12 05:58:58 PDT 2015


Every CRTC drivers in Exynos DRM implements the code which checks
whether IOMMU is supported or not, and if supported enable it.
Making new helper for it generalize each CRTC drivers.

Signed-off-by: Hyungwon Hwang <human.hwang at samsung.com>
---
Changes for v6:
- New
 drivers/gpu/drm/exynos/exynos7_drm_decon.c | 25 +++++++---------------
 drivers/gpu/drm/exynos/exynos_drm_drv.h    |  1 +
 drivers/gpu/drm/exynos/exynos_drm_fimd.c   | 34 +++++++-----------------------
 drivers/gpu/drm/exynos/exynos_drm_iommu.c  | 14 ++++++++++++
 drivers/gpu/drm/exynos/exynos_drm_iommu.h  | 11 ++++++++++
 drivers/gpu/drm/exynos/exynos_mixer.c      |  8 ++++---
 6 files changed, 47 insertions(+), 46 deletions(-)

diff --git a/drivers/gpu/drm/exynos/exynos7_drm_decon.c b/drivers/gpu/drm/exynos/exynos7_drm_decon.c
index 7d0955d..b0261dd 100644
--- a/drivers/gpu/drm/exynos/exynos7_drm_decon.c
+++ b/drivers/gpu/drm/exynos/exynos7_drm_decon.c
@@ -89,8 +89,9 @@ static void decon_wait_for_vblank(struct exynos_drm_crtc *crtc)
 		DRM_DEBUG_KMS("vblank wait timed out.\n");
 }

-static void decon_clear_channel(struct decon_context *ctx)
+static void decon_clear_channels(struct exynos_drm_crtc *crtc)
 {
+	struct decon_context *ctx = crtc->ctx;
 	unsigned int win, ch_enabled = 0;

 	DRM_DEBUG_KMS("%s\n", __FILE__);
@@ -120,27 +121,16 @@ static int decon_ctx_initialize(struct decon_context *ctx,
 			struct drm_device *drm_dev)
 {
 	struct exynos_drm_private *priv = drm_dev->dev_private;
+	int ret;

 	ctx->drm_dev = drm_dev;
 	ctx->pipe = priv->pipe++;

-	/* attach this sub driver to iommu mapping if supported. */
-	if (is_drm_iommu_supported(ctx->drm_dev)) {
-		int ret;
-
-		/*
-		 * If any channel is already active, iommu will throw
-		 * a PAGE FAULT when enabled. So clear any channel if enabled.
-		 */
-		decon_clear_channel(ctx);
-		ret = drm_iommu_attach_device(ctx->drm_dev, ctx->dev);
-		if (ret) {
-			DRM_ERROR("drm_iommu_attach failed.\n");
-			return ret;
-		}
-	}
+	ret = drm_iommu_attach_device_if_possible(ctx->crtc, drm_dev, ctx->dev);
+	if (ret)
+		priv->pipe--;

-	return 0;
+	return ret;
 }

 static void decon_ctx_remove(struct decon_context *ctx)
@@ -684,6 +674,7 @@ static const struct exynos_drm_crtc_ops decon_crtc_ops = {
 	.wait_for_vblank = decon_wait_for_vblank,
 	.win_commit = decon_win_commit,
 	.win_disable = decon_win_disable,
+	.clear_channels = decon_clear_channels,
 };


diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.h b/drivers/gpu/drm/exynos/exynos_drm_drv.h
index 6b4958b..1ba34f1 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_drv.h
+++ b/drivers/gpu/drm/exynos/exynos_drm_drv.h
@@ -182,6 +182,7 @@ struct exynos_drm_crtc_ops {
 	void (*win_disable)(struct exynos_drm_crtc *crtc, unsigned int zpos);
 	void (*te_handler)(struct exynos_drm_crtc *crtc);
 	void (*clock_enable)(struct exynos_drm_crtc *crtc, bool enable);
+	void (*clear_channels)(struct exynos_drm_crtc *crtc);
 };

 /*
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
index 9cce2bc..ddf4c84 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
@@ -242,8 +242,9 @@ static void fimd_enable_shadow_channel_path(struct fimd_context *ctx,
 	writel(val, ctx->regs + SHADOWCON);
 }

-static void fimd_clear_channel(struct fimd_context *ctx)
+static void fimd_clear_channels(struct exynos_drm_crtc *crtc)
 {
+	struct fimd_context *ctx = crtc->ctx;
 	unsigned int win, ch_enabled = 0;

 	DRM_DEBUG_KMS("%s\n", __FILE__);
@@ -273,30 +274,6 @@ static void fimd_clear_channel(struct fimd_context *ctx)
 	}
 }

-static int fimd_iommu_attach_devices(struct fimd_context *ctx,
-			struct drm_device *drm_dev)
-{
-
-	/* attach this sub driver to iommu mapping if supported. */
-	if (is_drm_iommu_supported(ctx->drm_dev)) {
-		int ret;
-
-		/*
-		 * If any channel is already active, iommu will throw
-		 * a PAGE FAULT when enabled. So clear any channel if enabled.
-		 */
-		fimd_clear_channel(ctx);
-		ret = drm_iommu_attach_device(ctx->drm_dev, ctx->dev);
-		if (ret) {
-			DRM_ERROR("drm_iommu_attach failed.\n");
-			return ret;
-		}
-
-	}
-
-	return 0;
-}
-
 static void fimd_iommu_detach_devices(struct fimd_context *ctx)
 {
 	/* detach this sub driver from iommu mapping if supported. */
@@ -943,6 +920,7 @@ static const struct exynos_drm_crtc_ops fimd_crtc_ops = {
 	.win_disable = fimd_win_disable,
 	.te_handler = fimd_te_handler,
 	.clock_enable = fimd_dp_clock_enable,
+	.clear_channels = fimd_clear_channels,
 };

 static irqreturn_t fimd_irq_handler(int irq, void *dev_id)
@@ -1012,7 +990,11 @@ static int fimd_bind(struct device *dev, struct device *master, void *data)
 	if (ctx->display)
 		exynos_drm_create_enc_conn(drm_dev, ctx->display);

-	return fimd_iommu_attach_devices(ctx, drm_dev);
+	ret = drm_iommu_attach_device_if_possible(ctx->crtc, drm_dev, dev);
+	if (ret)
+		priv->pipe--;
+
+	return ret;
 }

 static void fimd_unbind(struct device *dev, struct device *master,
diff --git a/drivers/gpu/drm/exynos/exynos_drm_iommu.c b/drivers/gpu/drm/exynos/exynos_drm_iommu.c
index b32b291..6f07479 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_iommu.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_iommu.c
@@ -141,3 +141,17 @@ void drm_iommu_detach_device(struct drm_device *drm_dev,
 	iommu_detach_device(mapping->domain, subdrv_dev);
 	drm_release_iommu_mapping(drm_dev);
 }
+
+int drm_iommu_attach_device_if_possible(struct exynos_drm_crtc *exynos_crtc,
+			struct drm_device *drm_dev, struct device *subdrv_dev)
+{
+	int ret = 0;
+
+	if (is_drm_iommu_supported(drm_dev)) {
+		if (exynos_crtc->ops->clear_channels)
+			exynos_crtc->ops->clear_channels(exynos_crtc);
+		return drm_iommu_attach_device(drm_dev, subdrv_dev);
+	}
+
+	return ret;
+}
diff --git a/drivers/gpu/drm/exynos/exynos_drm_iommu.h b/drivers/gpu/drm/exynos/exynos_drm_iommu.h
index 35d2588..8341c7a 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_iommu.h
+++ b/drivers/gpu/drm/exynos/exynos_drm_iommu.h
@@ -38,6 +38,10 @@ static inline bool is_drm_iommu_supported(struct drm_device *drm_dev)
 #endif
 }

+int drm_iommu_attach_device_if_possible(
+		struct exynos_drm_crtc *exynos_crtc, struct drm_device *drm_dev,
+		struct device *subdrv_dev);
+
 #else

 static inline int drm_create_iommu_mapping(struct drm_device *drm_dev)
@@ -65,5 +69,12 @@ static inline bool is_drm_iommu_supported(struct drm_device *drm_dev)
 	return false;
 }

+static inline int drm_iommu_attach_device_if_possible(
+		struct exynos_drm_crtc *exynos_crtc, struct drm_device *drm_dev,
+		struct device *subdrv_dev)
+{
+	return 0;
+}
+
 #endif
 #endif
diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c b/drivers/gpu/drm/exynos/exynos_mixer.c
index 854b6d8..6a2ede4 100644
--- a/drivers/gpu/drm/exynos/exynos_mixer.c
+++ b/drivers/gpu/drm/exynos/exynos_mixer.c
@@ -882,10 +882,12 @@ static int mixer_initialize(struct mixer_context *mixer_ctx,
 		}
 	}

-	if (!is_drm_iommu_supported(mixer_ctx->drm_dev))
-		return 0;
+	ret = drm_iommu_attach_device_if_possible(mixer_ctx->crtc, drm_dev,
+								mixer_ctx->dev);
+	if (ret)
+		priv->pipe--;

-	return drm_iommu_attach_device(mixer_ctx->drm_dev, mixer_ctx->dev);
+	return ret;
 }

 static void mixer_ctx_remove(struct mixer_context *mixer_ctx)
--
1.9.1



More information about the dri-devel mailing list