188 lines
5.3 KiB
Diff
188 lines
5.3 KiB
Diff
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
|
|
index 4eaeb430c83a..7efd12312354 100644
|
|
--- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
|
|
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
|
|
@@ -7,7 +7,6 @@
|
|
*/
|
|
|
|
#include <linux/dma-mapping.h>
|
|
-#include <linux/dma-iommu.h>
|
|
#include <linux/pm_runtime.h>
|
|
#include <linux/module.h>
|
|
#include <linux/of_graph.h>
|
|
@@ -34,7 +33,6 @@
|
|
#define DRIVER_MAJOR 1
|
|
#define DRIVER_MINOR 0
|
|
|
|
-static bool is_support_iommu = true;
|
|
static const struct drm_driver rockchip_drm_driver;
|
|
|
|
/*
|
|
@@ -48,7 +46,7 @@ int rockchip_drm_dma_attach_device(struct drm_device *drm_dev,
|
|
struct rockchip_drm_private *private = drm_dev->dev_private;
|
|
int ret;
|
|
|
|
- if (!is_support_iommu)
|
|
+ if (!private->domain)
|
|
return 0;
|
|
|
|
ret = iommu_attach_device(private->domain, dev);
|
|
@@ -64,12 +62,22 @@ void rockchip_drm_dma_detach_device(struct drm_device *drm_dev,
|
|
struct device *dev)
|
|
{
|
|
struct rockchip_drm_private *private = drm_dev->dev_private;
|
|
- struct iommu_domain *domain = private->domain;
|
|
|
|
- if (!is_support_iommu)
|
|
+ if (!private->domain)
|
|
return;
|
|
|
|
- iommu_detach_device(domain, dev);
|
|
+ iommu_detach_device(private->domain, dev);
|
|
+}
|
|
+
|
|
+void rockchip_drm_dma_init_device(struct drm_device *drm_dev,
|
|
+ struct device *dev)
|
|
+{
|
|
+ struct rockchip_drm_private *private = drm_dev->dev_private;
|
|
+
|
|
+ if (!device_iommu_mapped(dev))
|
|
+ private->iommu_dev = ERR_PTR(-ENODEV);
|
|
+ else if (!private->iommu_dev)
|
|
+ private->iommu_dev = dev;
|
|
}
|
|
|
|
static int rockchip_drm_init_iommu(struct drm_device *drm_dev)
|
|
@@ -78,10 +86,10 @@ static int rockchip_drm_init_iommu(struct drm_device *drm_dev)
|
|
struct iommu_domain_geometry *geometry;
|
|
u64 start, end;
|
|
|
|
- if (!is_support_iommu)
|
|
+ if (IS_ERR_OR_NULL(private->iommu_dev))
|
|
return 0;
|
|
|
|
- private->domain = iommu_domain_alloc(&platform_bus_type);
|
|
+ private->domain = iommu_domain_alloc(private->iommu_dev->bus);
|
|
if (!private->domain)
|
|
return -ENOMEM;
|
|
|
|
@@ -101,7 +109,7 @@ static void rockchip_iommu_cleanup(struct drm_device *drm_dev)
|
|
{
|
|
struct rockchip_drm_private *private = drm_dev->dev_private;
|
|
|
|
- if (!is_support_iommu)
|
|
+ if (!private->domain)
|
|
return;
|
|
|
|
drm_mm_takedown(&private->mm);
|
|
@@ -137,24 +145,24 @@ static int rockchip_drm_bind(struct device *dev)
|
|
|
|
drm_dev->dev_private = private;
|
|
|
|
- ret = rockchip_drm_init_iommu(drm_dev);
|
|
- if (ret)
|
|
- goto err_free;
|
|
-
|
|
ret = drmm_mode_config_init(drm_dev);
|
|
if (ret)
|
|
- goto err_iommu_cleanup;
|
|
+ goto err_free;
|
|
|
|
rockchip_drm_mode_config_init(drm_dev);
|
|
|
|
/* Try to bind all sub drivers. */
|
|
ret = component_bind_all(dev, drm_dev);
|
|
if (ret)
|
|
- goto err_iommu_cleanup;
|
|
+ goto err_free;
|
|
+
|
|
+ ret = rockchip_drm_init_iommu(drm_dev);
|
|
+ if (ret)
|
|
+ goto err_unbind_all;
|
|
|
|
ret = drm_vblank_init(drm_dev, drm_dev->mode_config.num_crtc);
|
|
if (ret)
|
|
- goto err_unbind_all;
|
|
+ goto err_iommu_cleanup;
|
|
|
|
drm_mode_config_reset(drm_dev);
|
|
|
|
@@ -170,10 +178,10 @@ static int rockchip_drm_bind(struct device *dev)
|
|
return 0;
|
|
err_kms_helper_poll_fini:
|
|
drm_kms_helper_poll_fini(drm_dev);
|
|
-err_unbind_all:
|
|
- component_unbind_all(dev, drm_dev);
|
|
err_iommu_cleanup:
|
|
rockchip_iommu_cleanup(drm_dev);
|
|
+err_unbind_all:
|
|
+ component_unbind_all(dev, drm_dev);
|
|
err_free:
|
|
drm_dev_put(drm_dev);
|
|
return ret;
|
|
@@ -342,8 +350,6 @@ static int rockchip_drm_platform_of_probe(struct device *dev)
|
|
return -ENODEV;
|
|
|
|
for (i = 0;; i++) {
|
|
- struct device_node *iommu;
|
|
-
|
|
port = of_parse_phandle(np, "ports", i);
|
|
if (!port)
|
|
break;
|
|
@@ -353,21 +359,7 @@ static int rockchip_drm_platform_of_probe(struct device *dev)
|
|
continue;
|
|
}
|
|
|
|
- iommu = of_parse_phandle(port->parent, "iommus", 0);
|
|
- if (!iommu || !of_device_is_available(iommu)) {
|
|
- DRM_DEV_DEBUG(dev,
|
|
- "no iommu attached for %pOF, using non-iommu buffers\n",
|
|
- port->parent);
|
|
- /*
|
|
- * if there is a crtc not support iommu, force set all
|
|
- * crtc use non-iommu buffer.
|
|
- */
|
|
- is_support_iommu = false;
|
|
- }
|
|
-
|
|
found = true;
|
|
-
|
|
- of_node_put(iommu);
|
|
of_node_put(port);
|
|
}
|
|
|
|
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
|
|
index 143a48330f84..008c44aef400 100644
|
|
--- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
|
|
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
|
|
@@ -44,6 +44,7 @@ struct rockchip_crtc_state {
|
|
*/
|
|
struct rockchip_drm_private {
|
|
struct iommu_domain *domain;
|
|
+ struct device *iommu_dev;
|
|
struct mutex mm_lock;
|
|
struct drm_mm mm;
|
|
};
|
|
@@ -52,6 +53,8 @@ int rockchip_drm_dma_attach_device(struct drm_device *drm_dev,
|
|
struct device *dev);
|
|
void rockchip_drm_dma_detach_device(struct drm_device *drm_dev,
|
|
struct device *dev);
|
|
+void rockchip_drm_dma_init_device(struct drm_device *drm_dev,
|
|
+ struct device *dev);
|
|
int rockchip_drm_wait_vact_end(struct drm_crtc *crtc, unsigned int mstimeout);
|
|
|
|
int rockchip_drm_endpoint_is_subdriver(struct device_node *ep);
|
|
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
|
|
index 3e8d9e2d1b67..4c38c53e9f65 100644
|
|
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
|
|
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
|
|
@@ -2175,6 +2175,8 @@ static int vop_bind(struct device *dev, struct device *master, void *data)
|
|
}
|
|
}
|
|
|
|
+ rockchip_drm_dma_init_device(drm_dev, dev);
|
|
+
|
|
return 0;
|
|
|
|
err_disable_pm_runtime:
|