aboutsummaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/rockchip/rockchip_drm_drv.c')
-rw-r--r--drivers/gpu/drm/rockchip/rockchip_drm_drv.c96
1 files changed, 61 insertions, 35 deletions
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
index 4eaeb430c83a..67d38f53d3e5 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,25 +145,25 @@ 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 = drm_vblank_init(drm_dev, drm_dev->mode_config.num_crtc);
+ 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_iommu_cleanup;
+
drm_mode_config_reset(drm_dev);
/* init kms poll for handling hpd */
@@ -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;
@@ -237,6 +245,39 @@ static struct platform_driver *rockchip_sub_drivers[MAX_ROCKCHIP_SUB_DRIVERS];
static int num_rockchip_sub_drivers;
/*
+ * Get the endpoint id of the remote endpoint of the given encoder. This
+ * information is used by the VOP2 driver to identify the encoder.
+ *
+ * @rkencoder: The encoder to get the remote endpoint id from
+ * @np: The encoder device node
+ * @port: The number of the port leading to the VOP2
+ * @reg: The endpoint number leading to the VOP2
+ */
+int rockchip_drm_encoder_set_crtc_endpoint_id(struct rockchip_encoder *rkencoder,
+ struct device_node *np, int port, int reg)
+{
+ struct of_endpoint ep;
+ struct device_node *en, *ren;
+ int ret;
+
+ en = of_graph_get_endpoint_by_regs(np, port, reg);
+ if (!en)
+ return -ENOENT;
+
+ ren = of_graph_get_remote_endpoint(en);
+ if (!ren)
+ return -ENOENT;
+
+ ret = of_graph_parse_endpoint(ren, &ep);
+ if (ret)
+ return ret;
+
+ rkencoder->crtc_endpoint_id = ep.id;
+
+ return 0;
+}
+
+/*
* Check if a vop endpoint is leading to a rockchip subdriver or bridge.
* Should be called from the component bind stage of the drivers
* to ensure that all subdrivers are probed.
@@ -342,8 +383,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 +392,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);
}
@@ -456,7 +481,8 @@ static int __init rockchip_drm_init(void)
return -ENODEV;
num_rockchip_sub_drivers = 0;
- ADD_ROCKCHIP_SUB_DRIVER(vop_platform_driver, CONFIG_DRM_ROCKCHIP);
+ ADD_ROCKCHIP_SUB_DRIVER(vop_platform_driver, CONFIG_ROCKCHIP_VOP);
+ ADD_ROCKCHIP_SUB_DRIVER(vop2_platform_driver, CONFIG_ROCKCHIP_VOP2);
ADD_ROCKCHIP_SUB_DRIVER(rockchip_lvds_driver,
CONFIG_ROCKCHIP_LVDS);
ADD_ROCKCHIP_SUB_DRIVER(rockchip_dp_driver,