Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2d90d477 authored by Mark Yao's avatar Mark Yao
Browse files

drm/rockchip: support non-iommu buffer path



Some rockchip vop not support iommu, need use non-iommu
buffer for it. And if we get iommu issues, we can compare
the issues with non-iommu path, that would help the debug.

Signed-off-by: default avatarMark Yao <mark.yao@rock-chips.com>
parent 4e257d9e
Loading
Loading
Loading
Loading
+47 −19
Original line number Original line Diff line number Diff line
@@ -36,6 +36,8 @@
#define DRIVER_MAJOR	1
#define DRIVER_MAJOR	1
#define DRIVER_MINOR	0
#define DRIVER_MINOR	0


static bool is_support_iommu = true;

/*
/*
 * Attach a (component) device to the shared drm dma mapping from master drm
 * Attach a (component) device to the shared drm dma mapping from master drm
 * device.  This is used by the VOPs to map GEM buffers to a common DMA
 * device.  This is used by the VOPs to map GEM buffers to a common DMA
@@ -47,6 +49,9 @@ int rockchip_drm_dma_attach_device(struct drm_device *drm_dev,
	struct dma_iommu_mapping *mapping = drm_dev->dev->archdata.mapping;
	struct dma_iommu_mapping *mapping = drm_dev->dev->archdata.mapping;
	int ret;
	int ret;


	if (!is_support_iommu)
		return 0;

	ret = dma_set_coherent_mask(dev, DMA_BIT_MASK(32));
	ret = dma_set_coherent_mask(dev, DMA_BIT_MASK(32));
	if (ret)
	if (ret)
		return ret;
		return ret;
@@ -59,6 +64,9 @@ int rockchip_drm_dma_attach_device(struct drm_device *drm_dev,
void rockchip_drm_dma_detach_device(struct drm_device *drm_dev,
void rockchip_drm_dma_detach_device(struct drm_device *drm_dev,
				    struct device *dev)
				    struct device *dev)
{
{
	if (!is_support_iommu)
		return;

	arm_iommu_detach_device(dev);
	arm_iommu_detach_device(dev);
}
}


@@ -127,7 +135,7 @@ static void rockchip_drm_crtc_disable_vblank(struct drm_device *dev,
static int rockchip_drm_load(struct drm_device *drm_dev, unsigned long flags)
static int rockchip_drm_load(struct drm_device *drm_dev, unsigned long flags)
{
{
	struct rockchip_drm_private *private;
	struct rockchip_drm_private *private;
	struct dma_iommu_mapping *mapping;
	struct dma_iommu_mapping *mapping = NULL;
	struct device *dev = drm_dev->dev;
	struct device *dev = drm_dev->dev;
	struct drm_connector *connector;
	struct drm_connector *connector;
	int ret;
	int ret;
@@ -152,8 +160,10 @@ static int rockchip_drm_load(struct drm_device *drm_dev, unsigned long flags)
		goto err_config_cleanup;
		goto err_config_cleanup;
	}
	}


	if (is_support_iommu) {
		/* TODO(djkurtz): fetch the mapping start/size from somewhere */
		/* TODO(djkurtz): fetch the mapping start/size from somewhere */
	mapping = arm_iommu_create_mapping(&platform_bus_type, 0x00000000,
		mapping = arm_iommu_create_mapping(&platform_bus_type,
						   0x00000000,
						   SZ_2G);
						   SZ_2G);
		if (IS_ERR(mapping)) {
		if (IS_ERR(mapping)) {
			ret = PTR_ERR(mapping);
			ret = PTR_ERR(mapping);
@@ -169,6 +179,7 @@ static int rockchip_drm_load(struct drm_device *drm_dev, unsigned long flags)
		ret = arm_iommu_attach_device(dev, mapping);
		ret = arm_iommu_attach_device(dev, mapping);
		if (ret)
		if (ret)
			goto err_release_mapping;
			goto err_release_mapping;
	}


	/* Try to bind all sub drivers. */
	/* Try to bind all sub drivers. */
	ret = component_bind_all(dev, drm_dev);
	ret = component_bind_all(dev, drm_dev);
@@ -218,6 +229,7 @@ static int rockchip_drm_load(struct drm_device *drm_dev, unsigned long flags)
	if (ret)
	if (ret)
		goto err_vblank_cleanup;
		goto err_vblank_cleanup;


	if (is_support_iommu)
		arm_iommu_release_mapping(mapping);
		arm_iommu_release_mapping(mapping);
	return 0;
	return 0;
err_vblank_cleanup:
err_vblank_cleanup:
@@ -227,8 +239,10 @@ static int rockchip_drm_load(struct drm_device *drm_dev, unsigned long flags)
err_unbind:
err_unbind:
	component_unbind_all(dev, drm_dev);
	component_unbind_all(dev, drm_dev);
err_detach_device:
err_detach_device:
	if (is_support_iommu)
		arm_iommu_detach_device(dev);
		arm_iommu_detach_device(dev);
err_release_mapping:
err_release_mapping:
	if (is_support_iommu)
		arm_iommu_release_mapping(mapping);
		arm_iommu_release_mapping(mapping);
err_config_cleanup:
err_config_cleanup:
	drm_mode_config_cleanup(drm_dev);
	drm_mode_config_cleanup(drm_dev);
@@ -244,6 +258,7 @@ static int rockchip_drm_unload(struct drm_device *drm_dev)
	drm_vblank_cleanup(drm_dev);
	drm_vblank_cleanup(drm_dev);
	drm_kms_helper_poll_fini(drm_dev);
	drm_kms_helper_poll_fini(drm_dev);
	component_unbind_all(dev, drm_dev);
	component_unbind_all(dev, drm_dev);
	if (is_support_iommu)
		arm_iommu_detach_device(dev);
		arm_iommu_detach_device(dev);
	drm_mode_config_cleanup(drm_dev);
	drm_mode_config_cleanup(drm_dev);
	drm_dev->dev_private = NULL;
	drm_dev->dev_private = NULL;
@@ -488,6 +503,8 @@ static int rockchip_drm_platform_probe(struct platform_device *pdev)
	 * works as expected.
	 * works as expected.
	 */
	 */
	for (i = 0;; i++) {
	for (i = 0;; i++) {
		struct device_node *iommu;

		port = of_parse_phandle(np, "ports", i);
		port = of_parse_phandle(np, "ports", i);
		if (!port)
		if (!port)
			break;
			break;
@@ -497,6 +514,17 @@ static int rockchip_drm_platform_probe(struct platform_device *pdev)
			continue;
			continue;
		}
		}


		iommu = of_parse_phandle(port->parent, "iommus", 0);
		if (!iommu || !of_device_is_available(iommu->parent)) {
			dev_dbg(dev, "no iommu attached for %s, using non-iommu buffers\n",
				port->parent->full_name);
			/*
			 * if there is a crtc not support iommu, force set all
			 * crtc use non-iommu buffer.
			 */
			is_support_iommu = false;
		}

		component_match_add(dev, &match, compare_of, port->parent);
		component_match_add(dev, &match, compare_of, port->parent);
		of_node_put(port);
		of_node_put(port);
	}
	}