drm/exynos: add drm_iommu_attach_device_if_possible()
authorHyungwon Hwang <human.hwang@samsung.com>
Mon, 22 Jun 2015 10:05:04 +0000 (19:05 +0900)
committerInki Dae <inki.dae@samsung.com>
Mon, 22 Jun 2015 10:05:46 +0000 (19:05 +0900)
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@samsung.com>
Signed-off-by: Inki Dae <inki.dae@samsung.com>
drivers/gpu/drm/exynos/exynos7_drm_decon.c
drivers/gpu/drm/exynos/exynos_drm_drv.h
drivers/gpu/drm/exynos/exynos_drm_fimd.c
drivers/gpu/drm/exynos/exynos_drm_iommu.c
drivers/gpu/drm/exynos/exynos_drm_iommu.h
drivers/gpu/drm/exynos/exynos_mixer.c

index 2b9221cc811f9448583c521d5b583977e87bfd9f..362532afd1a527e90df579fce5a4b3225419761b 100644 (file)
@@ -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)
@@ -633,6 +623,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,
 };
 
 
index a3845693c63452519fb1a334f4d6a6239ce7d7bd..61a9a9ed37f0a5c7b23f823b13890d07ea076a76 100644 (file)
@@ -177,6 +177,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);
 };
 
 /*
index 1e3bb72184d28f789fd5a5a2fd36cffac4d0f75a..794e56c8798e797fbc5d5b72944a9f12ed4a34a4 100644 (file)
@@ -298,8 +298,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__);
@@ -347,30 +348,6 @@ static void fimd_clear_channel(struct fimd_context *ctx)
        pm_runtime_put(ctx->dev);
 }
 
-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. */
@@ -917,6 +894,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)
@@ -986,7 +964,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,
index 34596da7be33b3df7a4581b21b35041ba143b540..d4ec7465e9ccdcaa7ebf633d44e3e213a192d356 100644 (file)
@@ -144,3 +144,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;
+}
index 35d25889b476ebe281439e0c3363e61dd7b2ab5f..8341c7a475b4e4eaa60e464eb4e2a9306995b83b 100644 (file)
@@ -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
index f57068781a3715c0861cdd7a380b4ae8cd762089..cae98db3306205e2628b2090b731cf6cfdf79d4f 100644 (file)
@@ -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)