diff options
author | Inki Dae <inki.dae@samsung.com> | 2012-10-19 04:37:35 -0400 |
---|---|---|
committer | Inki Dae <inki.dae@samsung.com> | 2012-12-04 00:45:53 -0500 |
commit | 1055b39facd1bf8f84031a07385f84b46a20540f (patch) | |
tree | d139201e9880349f39f6435d6cc24cafdbea7a3c /drivers | |
parent | bcc5cd1c5fad9b4471aafff0d74d9d0fcde1c27d (diff) |
drm/exynos: add iommu support for hdmi driver
Changelog v2:
move iommu support feature to mixer side.
And below is Prathyush's comment.
According to the new IOMMU framework for exynos sysmmus,
the owner of the sysmmu-tv is mixer (which is the actual
device that does DMA) and not hdmi.
The mmu-master in sysmmu-tv node is set as below in exynos5250.dtsi
sysmmu-tv {
-
mmu-master = <&mixer>;
};
Changelog v1:
The iommu will be enabled when hdmi sub driver is probed and
will be disabled when removed.
Signed-off-by: Inki Dae <inki.dae@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/gpu/drm/exynos/exynos_drm_hdmi.c | 15 | ||||
-rw-r--r-- | drivers/gpu/drm/exynos/exynos_drm_hdmi.h | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/exynos/exynos_hdmi.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/exynos/exynos_mixer.c | 23 |
4 files changed, 40 insertions, 1 deletions
diff --git a/drivers/gpu/drm/exynos/exynos_drm_hdmi.c b/drivers/gpu/drm/exynos/exynos_drm_hdmi.c index c3b9e2b45185..2d11e70b601a 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_hdmi.c +++ b/drivers/gpu/drm/exynos/exynos_drm_hdmi.c | |||
@@ -346,9 +346,23 @@ static int hdmi_subdrv_probe(struct drm_device *drm_dev, | |||
346 | ctx->hdmi_ctx->drm_dev = drm_dev; | 346 | ctx->hdmi_ctx->drm_dev = drm_dev; |
347 | ctx->mixer_ctx->drm_dev = drm_dev; | 347 | ctx->mixer_ctx->drm_dev = drm_dev; |
348 | 348 | ||
349 | if (mixer_ops->iommu_on) | ||
350 | mixer_ops->iommu_on(ctx->mixer_ctx->ctx, true); | ||
351 | |||
349 | return 0; | 352 | return 0; |
350 | } | 353 | } |
351 | 354 | ||
355 | static void hdmi_subdrv_remove(struct drm_device *drm_dev, struct device *dev) | ||
356 | { | ||
357 | struct drm_hdmi_context *ctx; | ||
358 | struct exynos_drm_subdrv *subdrv = to_subdrv(dev); | ||
359 | |||
360 | ctx = get_ctx_from_subdrv(subdrv); | ||
361 | |||
362 | if (mixer_ops->iommu_on) | ||
363 | mixer_ops->iommu_on(ctx->mixer_ctx->ctx, false); | ||
364 | } | ||
365 | |||
352 | static int __devinit exynos_drm_hdmi_probe(struct platform_device *pdev) | 366 | static int __devinit exynos_drm_hdmi_probe(struct platform_device *pdev) |
353 | { | 367 | { |
354 | struct device *dev = &pdev->dev; | 368 | struct device *dev = &pdev->dev; |
@@ -368,6 +382,7 @@ static int __devinit exynos_drm_hdmi_probe(struct platform_device *pdev) | |||
368 | subdrv->dev = dev; | 382 | subdrv->dev = dev; |
369 | subdrv->manager = &hdmi_manager; | 383 | subdrv->manager = &hdmi_manager; |
370 | subdrv->probe = hdmi_subdrv_probe; | 384 | subdrv->probe = hdmi_subdrv_probe; |
385 | subdrv->remove = hdmi_subdrv_remove; | ||
371 | 386 | ||
372 | platform_set_drvdata(pdev, subdrv); | 387 | platform_set_drvdata(pdev, subdrv); |
373 | 388 | ||
diff --git a/drivers/gpu/drm/exynos/exynos_drm_hdmi.h b/drivers/gpu/drm/exynos/exynos_drm_hdmi.h index 2da5ffd3a059..54b522353e48 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_hdmi.h +++ b/drivers/gpu/drm/exynos/exynos_drm_hdmi.h | |||
@@ -62,6 +62,7 @@ struct exynos_hdmi_ops { | |||
62 | 62 | ||
63 | struct exynos_mixer_ops { | 63 | struct exynos_mixer_ops { |
64 | /* manager */ | 64 | /* manager */ |
65 | int (*iommu_on)(void *ctx, bool enable); | ||
65 | int (*enable_vblank)(void *ctx, int pipe); | 66 | int (*enable_vblank)(void *ctx, int pipe); |
66 | void (*disable_vblank)(void *ctx); | 67 | void (*disable_vblank)(void *ctx); |
67 | void (*dpms)(void *ctx, int mode); | 68 | void (*dpms)(void *ctx, int mode); |
diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c b/drivers/gpu/drm/exynos/exynos_hdmi.c index 2c115f8a62a3..c73f43874944 100644 --- a/drivers/gpu/drm/exynos/exynos_hdmi.c +++ b/drivers/gpu/drm/exynos/exynos_hdmi.c | |||
@@ -74,6 +74,7 @@ struct hdmi_context { | |||
74 | struct mutex hdmi_mutex; | 74 | struct mutex hdmi_mutex; |
75 | 75 | ||
76 | void __iomem *regs; | 76 | void __iomem *regs; |
77 | void *parent_ctx; | ||
77 | int external_irq; | 78 | int external_irq; |
78 | int internal_irq; | 79 | int internal_irq; |
79 | 80 | ||
@@ -84,7 +85,6 @@ struct hdmi_context { | |||
84 | int cur_conf; | 85 | int cur_conf; |
85 | 86 | ||
86 | struct hdmi_resources res; | 87 | struct hdmi_resources res; |
87 | void *parent_ctx; | ||
88 | 88 | ||
89 | int hpd_gpio; | 89 | int hpd_gpio; |
90 | 90 | ||
diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c b/drivers/gpu/drm/exynos/exynos_mixer.c index 0d3ed282376c..50100cfddf4e 100644 --- a/drivers/gpu/drm/exynos/exynos_mixer.c +++ b/drivers/gpu/drm/exynos/exynos_mixer.c | |||
@@ -36,6 +36,7 @@ | |||
36 | 36 | ||
37 | #include "exynos_drm_drv.h" | 37 | #include "exynos_drm_drv.h" |
38 | #include "exynos_drm_hdmi.h" | 38 | #include "exynos_drm_hdmi.h" |
39 | #include "exynos_drm_iommu.h" | ||
39 | 40 | ||
40 | #define get_mixer_context(dev) platform_get_drvdata(to_platform_device(dev)) | 41 | #define get_mixer_context(dev) platform_get_drvdata(to_platform_device(dev)) |
41 | 42 | ||
@@ -80,6 +81,7 @@ enum mixer_version_id { | |||
80 | 81 | ||
81 | struct mixer_context { | 82 | struct mixer_context { |
82 | struct device *dev; | 83 | struct device *dev; |
84 | struct drm_device *drm_dev; | ||
83 | int pipe; | 85 | int pipe; |
84 | bool interlace; | 86 | bool interlace; |
85 | bool powered; | 87 | bool powered; |
@@ -90,6 +92,7 @@ struct mixer_context { | |||
90 | struct mixer_resources mixer_res; | 92 | struct mixer_resources mixer_res; |
91 | struct hdmi_win_data win_data[MIXER_WIN_NR]; | 93 | struct hdmi_win_data win_data[MIXER_WIN_NR]; |
92 | enum mixer_version_id mxr_ver; | 94 | enum mixer_version_id mxr_ver; |
95 | void *parent_ctx; | ||
93 | }; | 96 | }; |
94 | 97 | ||
95 | struct mixer_drv_data { | 98 | struct mixer_drv_data { |
@@ -665,6 +668,24 @@ static void mixer_win_reset(struct mixer_context *ctx) | |||
665 | spin_unlock_irqrestore(&res->reg_slock, flags); | 668 | spin_unlock_irqrestore(&res->reg_slock, flags); |
666 | } | 669 | } |
667 | 670 | ||
671 | static int mixer_iommu_on(void *ctx, bool enable) | ||
672 | { | ||
673 | struct exynos_drm_hdmi_context *drm_hdmi_ctx; | ||
674 | struct mixer_context *mdata = ctx; | ||
675 | struct drm_device *drm_dev; | ||
676 | |||
677 | drm_hdmi_ctx = mdata->parent_ctx; | ||
678 | drm_dev = drm_hdmi_ctx->drm_dev; | ||
679 | |||
680 | if (is_drm_iommu_supported(drm_dev)) { | ||
681 | if (enable) | ||
682 | return drm_iommu_attach_device(drm_dev, mdata->dev); | ||
683 | |||
684 | drm_iommu_detach_device(drm_dev, mdata->dev); | ||
685 | } | ||
686 | return 0; | ||
687 | } | ||
688 | |||
668 | static void mixer_poweron(struct mixer_context *ctx) | 689 | static void mixer_poweron(struct mixer_context *ctx) |
669 | { | 690 | { |
670 | struct mixer_resources *res = &ctx->mixer_res; | 691 | struct mixer_resources *res = &ctx->mixer_res; |
@@ -866,6 +887,7 @@ static void mixer_win_disable(void *ctx, int win) | |||
866 | 887 | ||
867 | static struct exynos_mixer_ops mixer_ops = { | 888 | static struct exynos_mixer_ops mixer_ops = { |
868 | /* manager */ | 889 | /* manager */ |
890 | .iommu_on = mixer_iommu_on, | ||
869 | .enable_vblank = mixer_enable_vblank, | 891 | .enable_vblank = mixer_enable_vblank, |
870 | .disable_vblank = mixer_disable_vblank, | 892 | .disable_vblank = mixer_disable_vblank, |
871 | .dpms = mixer_dpms, | 893 | .dpms = mixer_dpms, |
@@ -1140,6 +1162,7 @@ static int __devinit mixer_probe(struct platform_device *pdev) | |||
1140 | } | 1162 | } |
1141 | 1163 | ||
1142 | ctx->dev = &pdev->dev; | 1164 | ctx->dev = &pdev->dev; |
1165 | ctx->parent_ctx = (void *)drm_hdmi_ctx; | ||
1143 | drm_hdmi_ctx->ctx = (void *)ctx; | 1166 | drm_hdmi_ctx->ctx = (void *)ctx; |
1144 | ctx->vp_enabled = drv->is_vp_enabled; | 1167 | ctx->vp_enabled = drv->is_vp_enabled; |
1145 | ctx->mxr_ver = drv->version; | 1168 | ctx->mxr_ver = drv->version; |