From 53f1e0620b9b67f786b23c7e7fee96323bf2aa45 Mon Sep 17 00:00:00 2001 From: Souptick Joarder Date: Wed, 1 Aug 2018 01:37:05 +0530 Subject: [PATCH 01/10] drm/tegra: Convert drm_atomic_helper_suspend/resume() convert drm_atomic_helper_suspend/resume() to use drm_mode_config_helper_suspend/resume(). With this conversion, tegra_drm_fb_suspend() and tegra_drm_fb_resume() will not be used anymore. Both of these functions can be removed. Also, in tegra_drm struct's member state will not be used anymore. So this can be removed forever. Fixed one sparse warning. Signed-off-by: Souptick Joarder Signed-off-by: Ajit Negi Signed-off-by: Thierry Reding --- drivers/gpu/drm/tegra/drm.c | 20 ++------------------ drivers/gpu/drm/tegra/drm.h | 4 ---- drivers/gpu/drm/tegra/fb.c | 24 +----------------------- 3 files changed, 3 insertions(+), 45 deletions(-) diff --git a/drivers/gpu/drm/tegra/drm.c b/drivers/gpu/drm/tegra/drm.c index a2bd5876c633..9a0efcea217a 100644 --- a/drivers/gpu/drm/tegra/drm.c +++ b/drivers/gpu/drm/tegra/drm.c @@ -1212,31 +1212,15 @@ static int host1x_drm_remove(struct host1x_device *dev) static int host1x_drm_suspend(struct device *dev) { struct drm_device *drm = dev_get_drvdata(dev); - struct tegra_drm *tegra = drm->dev_private; - drm_kms_helper_poll_disable(drm); - tegra_drm_fb_suspend(drm); - - tegra->state = drm_atomic_helper_suspend(drm); - if (IS_ERR(tegra->state)) { - tegra_drm_fb_resume(drm); - drm_kms_helper_poll_enable(drm); - return PTR_ERR(tegra->state); - } - - return 0; + return drm_mode_config_helper_suspend(drm); } static int host1x_drm_resume(struct device *dev) { struct drm_device *drm = dev_get_drvdata(dev); - struct tegra_drm *tegra = drm->dev_private; - drm_atomic_helper_resume(drm, tegra->state); - tegra_drm_fb_resume(drm); - drm_kms_helper_poll_enable(drm); - - return 0; + return drm_mode_config_helper_resume(drm); } #endif diff --git a/drivers/gpu/drm/tegra/drm.h b/drivers/gpu/drm/tegra/drm.h index 92d248784396..1012335bb489 100644 --- a/drivers/gpu/drm/tegra/drm.h +++ b/drivers/gpu/drm/tegra/drm.h @@ -60,8 +60,6 @@ struct tegra_drm { unsigned int pitch_align; struct tegra_display_hub *hub; - - struct drm_atomic_state *state; }; struct tegra_drm_client; @@ -186,8 +184,6 @@ int tegra_drm_fb_prepare(struct drm_device *drm); void tegra_drm_fb_free(struct drm_device *drm); int tegra_drm_fb_init(struct drm_device *drm); void tegra_drm_fb_exit(struct drm_device *drm); -void tegra_drm_fb_suspend(struct drm_device *drm); -void tegra_drm_fb_resume(struct drm_device *drm); extern struct platform_driver tegra_display_hub_driver; extern struct platform_driver tegra_dc_driver; diff --git a/drivers/gpu/drm/tegra/fb.c b/drivers/gpu/drm/tegra/fb.c index 4c22cdded3c2..b947e82bbeb1 100644 --- a/drivers/gpu/drm/tegra/fb.c +++ b/drivers/gpu/drm/tegra/fb.c @@ -356,7 +356,7 @@ static void tegra_fbdev_exit(struct tegra_fbdev *fbdev) /* Undo the special mapping we made in fbdev probe. */ if (bo && bo->pages) { vunmap(bo->vaddr); - bo->vaddr = 0; + bo->vaddr = NULL; } drm_framebuffer_remove(fbdev->fb); @@ -412,25 +412,3 @@ void tegra_drm_fb_exit(struct drm_device *drm) tegra_fbdev_exit(tegra->fbdev); #endif } - -void tegra_drm_fb_suspend(struct drm_device *drm) -{ -#ifdef CONFIG_DRM_FBDEV_EMULATION - struct tegra_drm *tegra = drm->dev_private; - - console_lock(); - drm_fb_helper_set_suspend(&tegra->fbdev->base, 1); - console_unlock(); -#endif -} - -void tegra_drm_fb_resume(struct drm_device *drm) -{ -#ifdef CONFIG_DRM_FBDEV_EMULATION - struct tegra_drm *tegra = drm->dev_private; - - console_lock(); - drm_fb_helper_set_suspend(&tegra->fbdev->base, 0); - console_unlock(); -#endif -} From 47022003f94d1eecf49b9b7a7804814faaea9f08 Mon Sep 17 00:00:00 2001 From: Dmitry Osipenko Date: Fri, 21 Sep 2018 14:42:41 +0300 Subject: [PATCH 02/10] drm/tegra: dpaux: Use the correct definition for pad modes Some of definitions in the code changed the meaning, unfortunately one place missed the change. Signed-off-by: Dmitry Osipenko Acked-by: Jon Hunter Signed-off-by: Thierry Reding --- drivers/gpu/drm/tegra/dpaux.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/tegra/dpaux.c b/drivers/gpu/drm/tegra/dpaux.c index d84e81ff36ad..ba5681fab73b 100644 --- a/drivers/gpu/drm/tegra/dpaux.c +++ b/drivers/gpu/drm/tegra/dpaux.c @@ -521,7 +521,7 @@ static int tegra_dpaux_probe(struct platform_device *pdev) * is no possibility to perform the I2C mode configuration in the * HDMI path. */ - err = tegra_dpaux_pad_config(dpaux, DPAUX_HYBRID_PADCTL_MODE_I2C); + err = tegra_dpaux_pad_config(dpaux, DPAUX_PADCTL_FUNC_I2C); if (err < 0) return err; From 759d706f7cb4adbec1c222f7550dc8fa2683c089 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Fri, 21 Sep 2018 12:27:42 +0200 Subject: [PATCH 03/10] drm/tegra: dc: Do not register DC without primary plane Tegra194 contains a fourth display controller that does not own any windows. Therefore, we cannot currently assign a primary plane to it which causes KMS to eventually crash. Do not register the display controller if it owns no windows to work around this. Note that we still have to enable and probe the display controller because for some reason all display controllers need to be powered (and/or clocked) before any registers can be accessed in any of the display controllers. Signed-off-by: Thierry Reding --- drivers/gpu/drm/tegra/dc.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c index 965088afcfad..7e36ca204cbb 100644 --- a/drivers/gpu/drm/tegra/dc.c +++ b/drivers/gpu/drm/tegra/dc.c @@ -1988,6 +1988,28 @@ static int tegra_dc_init(struct host1x_client *client) struct drm_plane *cursor = NULL; int err; + /* + * XXX do not register DCs with no window groups because we cannot + * assign a primary plane to them, which in turn will cause KMS to + * crash. + */ + if (dc->soc->wgrps) { + bool has_wgrps = false; + unsigned int i; + + for (i = 0; i < dc->soc->num_wgrps; i++) { + const struct tegra_windowgroup_soc *wgrp = &dc->soc->wgrps[i]; + + if (wgrp->dc == dc->pipe && wgrp->num_windows > 0) { + has_wgrps = true; + break; + } + } + + if (!has_wgrps) + return 0; + } + dc->syncpt = host1x_syncpt_request(client, flags); if (!dc->syncpt) dev_warn(dc->dev, "failed to allocate syncpoint\n"); From 5725daaab55ca023c87ff0f1b2dbf6bf9b38376d Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Fri, 21 Sep 2018 12:27:43 +0200 Subject: [PATCH 04/10] drm/tegra: hub: Add Tegra194 support The display hub integrated into Tegra194 is almost identical to the one found on Tegra186. However, it doesn't support DSC (display stream compression) so it isn't fully compatible. Signed-off-by: Thierry Reding --- drivers/gpu/drm/tegra/drm.c | 1 + drivers/gpu/drm/tegra/hub.c | 19 +++++++++++++++---- drivers/gpu/drm/tegra/hub.h | 1 + 3 files changed, 17 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/tegra/drm.c b/drivers/gpu/drm/tegra/drm.c index 9a0efcea217a..4e40ffd2b32e 100644 --- a/drivers/gpu/drm/tegra/drm.c +++ b/drivers/gpu/drm/tegra/drm.c @@ -1255,6 +1255,7 @@ static const struct of_device_id host1x_drm_subdevs[] = { { .compatible = "nvidia,tegra186-sor", }, { .compatible = "nvidia,tegra186-sor1", }, { .compatible = "nvidia,tegra186-vic", }, + { .compatible = "nvidia,tegra194-display", }, { /* sentinel */ } }; diff --git a/drivers/gpu/drm/tegra/hub.c b/drivers/gpu/drm/tegra/hub.c index 8f4fcbb515fb..6112d9042979 100644 --- a/drivers/gpu/drm/tegra/hub.c +++ b/drivers/gpu/drm/tegra/hub.c @@ -758,10 +758,12 @@ static int tegra_display_hub_probe(struct platform_device *pdev) return err; } - hub->clk_dsc = devm_clk_get(&pdev->dev, "dsc"); - if (IS_ERR(hub->clk_dsc)) { - err = PTR_ERR(hub->clk_dsc); - return err; + if (hub->soc->supports_dsc) { + hub->clk_dsc = devm_clk_get(&pdev->dev, "dsc"); + if (IS_ERR(hub->clk_dsc)) { + err = PTR_ERR(hub->clk_dsc); + return err; + } } hub->clk_hub = devm_clk_get(&pdev->dev, "hub"); @@ -890,10 +892,19 @@ static const struct dev_pm_ops tegra_display_hub_pm_ops = { static const struct tegra_display_hub_soc tegra186_display_hub = { .num_wgrps = 6, + .supports_dsc = true, +}; + +static const struct tegra_display_hub_soc tegra194_display_hub = { + .num_wgrps = 6, + .supports_dsc = false, }; static const struct of_device_id tegra_display_hub_of_match[] = { { + .compatible = "nvidia,tegra194-display", + .data = &tegra194_display_hub + }, { .compatible = "nvidia,tegra186-display", .data = &tegra186_display_hub }, { diff --git a/drivers/gpu/drm/tegra/hub.h b/drivers/gpu/drm/tegra/hub.h index 85b8bf41a395..6696a85fc1f2 100644 --- a/drivers/gpu/drm/tegra/hub.h +++ b/drivers/gpu/drm/tegra/hub.h @@ -38,6 +38,7 @@ to_tegra_shared_plane(struct drm_plane *plane) struct tegra_display_hub_soc { unsigned int num_wgrps; + bool supports_dsc; }; struct tegra_display_hub { From 474431968507d437d340de35b709aa3b41f8c996 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Fri, 21 Sep 2018 12:27:44 +0200 Subject: [PATCH 05/10] drm/tegra: dc: Add Tegra194 support The display controllers found on Tegra194 are almost identical to those found on Tegra186. Signed-off-by: Thierry Reding --- drivers/gpu/drm/tegra/dc.c | 51 +++++++++++++++++++++++++++++++++++++ drivers/gpu/drm/tegra/dc.h | 2 +- drivers/gpu/drm/tegra/drm.c | 1 + 3 files changed, 53 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c index 7e36ca204cbb..f80e82e16475 100644 --- a/drivers/gpu/drm/tegra/dc.c +++ b/drivers/gpu/drm/tegra/dc.c @@ -2256,8 +2256,59 @@ static const struct tegra_dc_soc_info tegra186_dc_soc_info = { .num_wgrps = ARRAY_SIZE(tegra186_dc_wgrps), }; +static const struct tegra_windowgroup_soc tegra194_dc_wgrps[] = { + { + .index = 0, + .dc = 0, + .windows = (const unsigned int[]) { 0 }, + .num_windows = 1, + }, { + .index = 1, + .dc = 1, + .windows = (const unsigned int[]) { 1 }, + .num_windows = 1, + }, { + .index = 2, + .dc = 1, + .windows = (const unsigned int[]) { 2 }, + .num_windows = 1, + }, { + .index = 3, + .dc = 2, + .windows = (const unsigned int[]) { 3 }, + .num_windows = 1, + }, { + .index = 4, + .dc = 2, + .windows = (const unsigned int[]) { 4 }, + .num_windows = 1, + }, { + .index = 5, + .dc = 2, + .windows = (const unsigned int[]) { 5 }, + .num_windows = 1, + }, +}; + +static const struct tegra_dc_soc_info tegra194_dc_soc_info = { + .supports_background_color = true, + .supports_interlacing = true, + .supports_cursor = true, + .supports_block_linear = true, + .has_legacy_blending = false, + .pitch_align = 64, + .has_powergate = false, + .coupled_pm = false, + .has_nvdisplay = true, + .wgrps = tegra194_dc_wgrps, + .num_wgrps = ARRAY_SIZE(tegra194_dc_wgrps), +}; + static const struct of_device_id tegra_dc_of_match[] = { { + .compatible = "nvidia,tegra194-dc", + .data = &tegra194_dc_soc_info, + }, { .compatible = "nvidia,tegra186-dc", .data = &tegra186_dc_soc_info, }, { diff --git a/drivers/gpu/drm/tegra/dc.h b/drivers/gpu/drm/tegra/dc.h index e96f582ca692..1256dfb6b2f5 100644 --- a/drivers/gpu/drm/tegra/dc.h +++ b/drivers/gpu/drm/tegra/dc.h @@ -300,7 +300,7 @@ int tegra_dc_rgb_exit(struct tegra_dc *dc); #define SOR1_TIMING_CYA (1 << 27) #define CURSOR_ENABLE (1 << 16) -#define SOR_ENABLE(x) (1 << (25 + (x))) +#define SOR_ENABLE(x) (1 << (25 + (((x) > 1) ? ((x) + 1) : (x)))) #define DC_DISP_DISP_MEM_HIGH_PRIORITY 0x403 #define CURSOR_THRESHOLD(x) (((x) & 0x03) << 24) diff --git a/drivers/gpu/drm/tegra/drm.c b/drivers/gpu/drm/tegra/drm.c index 4e40ffd2b32e..0ed6fa8ac446 100644 --- a/drivers/gpu/drm/tegra/drm.c +++ b/drivers/gpu/drm/tegra/drm.c @@ -1256,6 +1256,7 @@ static const struct of_device_id host1x_drm_subdevs[] = { { .compatible = "nvidia,tegra186-sor1", }, { .compatible = "nvidia,tegra186-vic", }, { .compatible = "nvidia,tegra194-display", }, + { .compatible = "nvidia,tegra194-dc", }, { /* sentinel */ } }; From 30f11cfd6a707868b49cdc9a72e4bfbf798be5a7 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Fri, 21 Sep 2018 12:27:45 +0200 Subject: [PATCH 06/10] drm/tegra: dpaux: Add Tegra194 support The DPAUX controller found on Tegra194 is almost identical to its predecessor from Tegra186. Signed-off-by: Thierry Reding --- drivers/gpu/drm/tegra/dpaux.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/tegra/dpaux.c b/drivers/gpu/drm/tegra/dpaux.c index ba5681fab73b..ee4180d8db14 100644 --- a/drivers/gpu/drm/tegra/dpaux.c +++ b/drivers/gpu/drm/tegra/dpaux.c @@ -639,6 +639,7 @@ static const struct dev_pm_ops tegra_dpaux_pm_ops = { }; static const struct of_device_id tegra_dpaux_of_match[] = { + { .compatible = "nvidia,tegra194-dpaux", }, { .compatible = "nvidia,tegra186-dpaux", }, { .compatible = "nvidia,tegra210-dpaux", }, { .compatible = "nvidia,tegra124-dpaux", }, From 9b6c14b8aa469e47fdf51d2e6cf6dd59975b8d02 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Fri, 21 Sep 2018 12:27:46 +0200 Subject: [PATCH 07/10] drm/tegra: sor: Add Tegra194 support The SOR implemented in Tegra194 is subtly different from its predecessor found in Tegra186. Most notably some registers have been moved around so it is no longer compatible. Signed-off-by: Thierry Reding --- drivers/gpu/drm/tegra/drm.c | 1 + drivers/gpu/drm/tegra/sor.c | 110 ++++++++++++++++++++++++++++++++++++ 2 files changed, 111 insertions(+) diff --git a/drivers/gpu/drm/tegra/drm.c b/drivers/gpu/drm/tegra/drm.c index 0ed6fa8ac446..0ee924e3d0a1 100644 --- a/drivers/gpu/drm/tegra/drm.c +++ b/drivers/gpu/drm/tegra/drm.c @@ -1257,6 +1257,7 @@ static const struct of_device_id host1x_drm_subdevs[] = { { .compatible = "nvidia,tegra186-vic", }, { .compatible = "nvidia,tegra194-display", }, { .compatible = "nvidia,tegra194-dc", }, + { .compatible = "nvidia,tegra194-sor", }, { /* sentinel */ } }; diff --git a/drivers/gpu/drm/tegra/sor.c b/drivers/gpu/drm/tegra/sor.c index d7fe9f15def1..b129da2e5afd 100644 --- a/drivers/gpu/drm/tegra/sor.c +++ b/drivers/gpu/drm/tegra/sor.c @@ -282,6 +282,85 @@ static const struct tegra_sor_hdmi_settings tegra186_sor_hdmi_defaults[] = { } }; +static const struct tegra_sor_hdmi_settings tegra194_sor_hdmi_defaults[] = { + { + .frequency = 54000000, + .vcocap = 0, + .filter = 5, + .ichpmp = 5, + .loadadj = 3, + .tmds_termadj = 0xf, + .tx_pu_value = 0, + .bg_temp_coef = 3, + .bg_vref_level = 8, + .avdd10_level = 4, + .avdd14_level = 4, + .sparepll = 0x54, + .drive_current = { 0x3a, 0x3a, 0x3a, 0x33 }, + .preemphasis = { 0x00, 0x00, 0x00, 0x00 }, + }, { + .frequency = 75000000, + .vcocap = 1, + .filter = 5, + .ichpmp = 5, + .loadadj = 3, + .tmds_termadj = 0xf, + .tx_pu_value = 0, + .bg_temp_coef = 3, + .bg_vref_level = 8, + .avdd10_level = 4, + .avdd14_level = 4, + .sparepll = 0x44, + .drive_current = { 0x3a, 0x3a, 0x3a, 0x33 }, + .preemphasis = { 0x00, 0x00, 0x00, 0x00 }, + }, { + .frequency = 150000000, + .vcocap = 3, + .filter = 5, + .ichpmp = 5, + .loadadj = 3, + .tmds_termadj = 15, + .tx_pu_value = 0x66 /* 0 */, + .bg_temp_coef = 3, + .bg_vref_level = 8, + .avdd10_level = 4, + .avdd14_level = 4, + .sparepll = 0x00, /* 0x34 */ + .drive_current = { 0x3a, 0x3a, 0x3a, 0x37 }, + .preemphasis = { 0x00, 0x00, 0x00, 0x00 }, + }, { + .frequency = 300000000, + .vcocap = 3, + .filter = 5, + .ichpmp = 5, + .loadadj = 3, + .tmds_termadj = 15, + .tx_pu_value = 64, + .bg_temp_coef = 3, + .bg_vref_level = 8, + .avdd10_level = 4, + .avdd14_level = 4, + .sparepll = 0x34, + .drive_current = { 0x3d, 0x3d, 0x3d, 0x33 }, + .preemphasis = { 0x00, 0x00, 0x00, 0x00 }, + }, { + .frequency = 600000000, + .vcocap = 3, + .filter = 5, + .ichpmp = 5, + .loadadj = 3, + .tmds_termadj = 12, + .tx_pu_value = 96, + .bg_temp_coef = 3, + .bg_vref_level = 8, + .avdd10_level = 4, + .avdd14_level = 4, + .sparepll = 0x34, + .drive_current = { 0x3d, 0x3d, 0x3d, 0x33 }, + .preemphasis = { 0x00, 0x00, 0x00, 0x00 }, + } +}; + struct tegra_sor_regs { unsigned int head_state0; unsigned int head_state1; @@ -2894,7 +2973,38 @@ static const struct tegra_sor_soc tegra186_sor1 = { .xbar_cfg = tegra124_sor_xbar_cfg, }; +static const struct tegra_sor_regs tegra194_sor_regs = { + .head_state0 = 0x151, + .head_state1 = 0x155, + .head_state2 = 0x159, + .head_state3 = 0x15d, + .head_state4 = 0x161, + .head_state5 = 0x165, + .pll0 = 0x169, + .pll1 = 0x16a, + .pll2 = 0x16b, + .pll3 = 0x16c, + .dp_padctl0 = 0x16e, + .dp_padctl2 = 0x16f, +}; + +static const struct tegra_sor_soc tegra194_sor = { + .supports_edp = true, + .supports_lvds = false, + .supports_hdmi = true, + .supports_dp = true, + + .regs = &tegra194_sor_regs, + .has_nvdisplay = true, + + .num_settings = ARRAY_SIZE(tegra194_sor_hdmi_defaults), + .settings = tegra194_sor_hdmi_defaults, + + .xbar_cfg = tegra210_sor_xbar_cfg, +}; + static const struct of_device_id tegra_sor_of_match[] = { + { .compatible = "nvidia,tegra194-sor", .data = &tegra194_sor }, { .compatible = "nvidia,tegra186-sor1", .data = &tegra186_sor1 }, { .compatible = "nvidia,tegra186-sor", .data = &tegra186_sor }, { .compatible = "nvidia,tegra210-sor1", .data = &tegra210_sor1 }, From 50bac83c80dd20e6c6b80afccadf5c70cbbc816e Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Wed, 26 Sep 2018 16:09:46 +0200 Subject: [PATCH 08/10] gpu: host1x: Remove spurious tab All other assignments have a single space around the = sign, so remove the spurious tab for consistency. Signed-off-by: Thierry Reding --- drivers/gpu/host1x/bus.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/host1x/bus.c b/drivers/gpu/host1x/bus.c index 815bdb42e3f0..b4c385d4a6af 100644 --- a/drivers/gpu/host1x/bus.c +++ b/drivers/gpu/host1x/bus.c @@ -331,7 +331,7 @@ static const struct dev_pm_ops host1x_device_pm_ops = { struct bus_type host1x_bus_type = { .name = "host1x", .match = host1x_device_match, - .dma_configure = host1x_dma_configure, + .dma_configure = host1x_dma_configure, .pm = &host1x_device_pm_ops, }; From e31c8ea5aff8670275e4e451fdc3bca5fbc8a528 Mon Sep 17 00:00:00 2001 From: Dmitry Osipenko Date: Thu, 30 Aug 2018 03:12:47 +0300 Subject: [PATCH 09/10] gpu: host1x: Detach Host1x from IOMMU DMA domain on arm32 Host1x is getting attached to an implicit IOMMU DMA domain if CONFIG_ARM_DMA_USE_IOMMU=y. Since Host1x driver manages IOMMU by itself, Host1x device must be detached from the implicit domain using arch-specific IOMMU-API. Signed-off-by: Dmitry Osipenko Signed-off-by: Thierry Reding --- drivers/gpu/host1x/dev.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/host1x/dev.c b/drivers/gpu/host1x/dev.c index d88073e7d22d..de6bc4e7fa23 100644 --- a/drivers/gpu/host1x/dev.c +++ b/drivers/gpu/host1x/dev.c @@ -29,6 +29,10 @@ #include #undef CREATE_TRACE_POINTS +#if IS_ENABLED(CONFIG_ARM_DMA_USE_IOMMU) +#include +#endif + #include "bus.h" #include "channel.h" #include "debug.h" @@ -217,7 +221,14 @@ static int host1x_probe(struct platform_device *pdev) dev_err(&pdev->dev, "failed to get reset: %d\n", err); return err; } - +#if IS_ENABLED(CONFIG_ARM_DMA_USE_IOMMU) + if (host->dev->archdata.mapping) { + struct dma_iommu_mapping *mapping = + to_dma_iommu_mapping(host->dev); + arm_iommu_detach_device(host->dev); + arm_iommu_release_mapping(mapping); + } +#endif if (IS_ENABLED(CONFIG_TEGRA_HOST1X_FIREWALL)) goto skip_iommu; From 5ac93f81096a2065adb99defdb8f04ae2c19cc11 Mon Sep 17 00:00:00 2001 From: Dmitry Osipenko Date: Sun, 19 Aug 2018 17:24:20 +0300 Subject: [PATCH 10/10] drm/tegra: Detach devices from IOMMU DMA domain on arm32 All Tegra DRM devices are getting attached to an implicit IOMMU DMA domain if CONFIG_ARM_DMA_USE_IOMMU=y. Since Tegra DRM driver manages IOMMU by itself, the devices must be detached from the implicit domain using arch-specific IOMMU-API. Note that this works only for arm32 and not for arm64, which will remain broken if CONFIG_IOMMU_DMA is enabled. Signed-off-by: Dmitry Osipenko Signed-off-by: Thierry Reding --- drivers/gpu/drm/tegra/drm.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/drivers/gpu/drm/tegra/drm.c b/drivers/gpu/drm/tegra/drm.c index 0ee924e3d0a1..552046062ec8 100644 --- a/drivers/gpu/drm/tegra/drm.c +++ b/drivers/gpu/drm/tegra/drm.c @@ -15,6 +15,10 @@ #include #include +#if IS_ENABLED(CONFIG_ARM_DMA_USE_IOMMU) +#include +#endif + #include "drm.h" #include "gem.h" @@ -1068,6 +1072,14 @@ struct iommu_group *host1x_client_iommu_attach(struct host1x_client *client, } if (!shared || (shared && (group != tegra->group))) { +#if IS_ENABLED(CONFIG_ARM_DMA_USE_IOMMU) + if (client->dev->archdata.mapping) { + struct dma_iommu_mapping *mapping = + to_dma_iommu_mapping(client->dev); + arm_iommu_detach_device(client->dev); + arm_iommu_release_mapping(mapping); + } +#endif err = iommu_attach_group(tegra->domain, group); if (err < 0) { iommu_group_put(group);