mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-07 19:30:30 +09:00
UPSTREAM: 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.
Conflicts:
drivers/gpu/drm/rockchip/rockchip_drm_drv.c
Change-Id: I843f087281300359b07faac1de156cd648325b45
Signed-off-by: Mark Yao <mark.yao@rock-chips.com>
(cherry picked from commit 2d90d47743)
This commit is contained in:
@@ -44,6 +44,8 @@
|
||||
#define DRIVER_MAJOR 1
|
||||
#define DRIVER_MINOR 0
|
||||
|
||||
static bool is_support_iommu = true;
|
||||
|
||||
static LIST_HEAD(rockchip_drm_subdrv_list);
|
||||
static DEFINE_MUTEX(subdrv_list_mutex);
|
||||
|
||||
@@ -617,6 +619,9 @@ int rockchip_drm_dma_attach_device(struct drm_device *drm_dev,
|
||||
struct dma_iommu_mapping *mapping = drm_dev->dev->archdata.mapping;
|
||||
int ret;
|
||||
|
||||
if (!is_support_iommu)
|
||||
return 0;
|
||||
|
||||
ret = dma_set_coherent_mask(dev, DMA_BIT_MASK(32));
|
||||
if (ret)
|
||||
return ret;
|
||||
@@ -629,6 +634,9 @@ int rockchip_drm_dma_attach_device(struct drm_device *drm_dev,
|
||||
void rockchip_drm_dma_detach_device(struct drm_device *drm_dev,
|
||||
struct device *dev)
|
||||
{
|
||||
if (!is_support_iommu)
|
||||
return;
|
||||
|
||||
arm_iommu_detach_device(dev);
|
||||
}
|
||||
|
||||
@@ -697,7 +705,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)
|
||||
{
|
||||
struct rockchip_drm_private *private;
|
||||
struct dma_iommu_mapping *mapping;
|
||||
struct dma_iommu_mapping *mapping = NULL;
|
||||
struct device *dev = drm_dev->dev;
|
||||
struct drm_connector *connector;
|
||||
int ret;
|
||||
@@ -727,24 +735,27 @@ static int rockchip_drm_load(struct drm_device *drm_dev, unsigned long flags)
|
||||
goto err_config_cleanup;
|
||||
}
|
||||
|
||||
/* TODO(djkurtz): fetch the mapping start/size from somewhere */
|
||||
mapping = arm_iommu_create_mapping(&platform_bus_type, 0x00000000,
|
||||
SZ_2G);
|
||||
if (IS_ERR(mapping)) {
|
||||
ret = PTR_ERR(mapping);
|
||||
goto err_config_cleanup;
|
||||
if (is_support_iommu) {
|
||||
/* TODO(djkurtz): fetch the mapping start/size from somewhere */
|
||||
mapping = arm_iommu_create_mapping(&platform_bus_type,
|
||||
0x00000000,
|
||||
SZ_2G);
|
||||
if (IS_ERR(mapping)) {
|
||||
ret = PTR_ERR(mapping);
|
||||
goto err_config_cleanup;
|
||||
}
|
||||
|
||||
ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32));
|
||||
if (ret)
|
||||
goto err_release_mapping;
|
||||
|
||||
dma_set_max_seg_size(dev, DMA_BIT_MASK(32));
|
||||
|
||||
ret = arm_iommu_attach_device(dev, mapping);
|
||||
if (ret)
|
||||
goto err_release_mapping;
|
||||
}
|
||||
|
||||
ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32));
|
||||
if (ret)
|
||||
goto err_release_mapping;
|
||||
|
||||
dma_set_max_seg_size(dev, DMA_BIT_MASK(32));
|
||||
|
||||
ret = arm_iommu_attach_device(dev, mapping);
|
||||
if (ret)
|
||||
goto err_release_mapping;
|
||||
|
||||
/* Try to bind all sub drivers. */
|
||||
ret = component_bind_all(dev, drm_dev);
|
||||
if (ret)
|
||||
@@ -797,7 +808,8 @@ static int rockchip_drm_load(struct drm_device *drm_dev, unsigned long flags)
|
||||
|
||||
drm_dev->mode_config.allow_fb_modifiers = true;
|
||||
|
||||
arm_iommu_release_mapping(mapping);
|
||||
if (is_support_iommu)
|
||||
arm_iommu_release_mapping(mapping);
|
||||
return 0;
|
||||
err_vblank_cleanup:
|
||||
drm_vblank_cleanup(drm_dev);
|
||||
@@ -806,9 +818,11 @@ err_kms_helper_poll_fini:
|
||||
err_unbind:
|
||||
component_unbind_all(dev, drm_dev);
|
||||
err_detach_device:
|
||||
arm_iommu_detach_device(dev);
|
||||
if (is_support_iommu)
|
||||
arm_iommu_detach_device(dev);
|
||||
err_release_mapping:
|
||||
arm_iommu_release_mapping(mapping);
|
||||
if (is_support_iommu)
|
||||
arm_iommu_release_mapping(mapping);
|
||||
err_config_cleanup:
|
||||
drm_mode_config_cleanup(drm_dev);
|
||||
drm_dev->dev_private = NULL;
|
||||
@@ -823,7 +837,8 @@ static int rockchip_drm_unload(struct drm_device *drm_dev)
|
||||
drm_vblank_cleanup(drm_dev);
|
||||
drm_kms_helper_poll_fini(drm_dev);
|
||||
component_unbind_all(dev, drm_dev);
|
||||
arm_iommu_detach_device(dev);
|
||||
if (is_support_iommu)
|
||||
arm_iommu_detach_device(dev);
|
||||
drm_mode_config_cleanup(drm_dev);
|
||||
drm_dev->dev_private = NULL;
|
||||
|
||||
@@ -1163,6 +1178,8 @@ static int rockchip_drm_platform_probe(struct platform_device *pdev)
|
||||
* works as expected.
|
||||
*/
|
||||
for (i = 0;; i++) {
|
||||
struct device_node *iommu;
|
||||
|
||||
port = of_parse_phandle(np, "ports", i);
|
||||
if (!port)
|
||||
break;
|
||||
@@ -1172,6 +1189,17 @@ static int rockchip_drm_platform_probe(struct platform_device *pdev)
|
||||
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);
|
||||
of_node_put(port);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user