summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/gpu/drm/exynos/exynos7_drm_decon.c25
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_drv.h1
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_fimd.c34
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_iommu.c14
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_iommu.h11
-rw-r--r--drivers/gpu/drm/exynos/exynos_mixer.c8
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 2b9221cc811f..362532afd1a5 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)
@@ -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,
};
diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.h b/drivers/gpu/drm/exynos/exynos_drm_drv.h
index a3845693c634..61a9a9ed37f0 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_drv.h
+++ b/drivers/gpu/drm/exynos/exynos_drm_drv.h
@@ -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);
};
/*
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
index 1e3bb72184d2..794e56c8798e 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
@@ -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,
diff --git a/drivers/gpu/drm/exynos/exynos_drm_iommu.c b/drivers/gpu/drm/exynos/exynos_drm_iommu.c
index 34596da7be33..d4ec7465e9cc 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_iommu.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_iommu.c
@@ -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;
+}
diff --git a/drivers/gpu/drm/exynos/exynos_drm_iommu.h b/drivers/gpu/drm/exynos/exynos_drm_iommu.h
index 35d25889b476..8341c7a475b4 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 f57068781a37..cae98db33062 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)