aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMark Yao <mark.yao@rock-chips.com>2016-04-18 22:13:27 -0400
committerMark Yao <mark.yao@rock-chips.com>2016-05-03 02:11:23 -0400
commit2d90d477430d3a20df74f2d11c21378e64e1d508 (patch)
treec1769bb7a9662bee510f53f382737235c194def1
parent4e257d9eee23582e36637ce7ea6b14f6f56b1839 (diff)
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: Mark Yao <mark.yao@rock-chips.com>
-rw-r--r--drivers/gpu/drm/rockchip/rockchip_drm_drv.c66
1 files changed, 47 insertions, 19 deletions
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
index 1e2d88bdd9f7..399adf3c4224 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
@@ -36,6 +36,8 @@
36#define DRIVER_MAJOR 1 36#define DRIVER_MAJOR 1
37#define DRIVER_MINOR 0 37#define DRIVER_MINOR 0
38 38
39static bool is_support_iommu = true;
40
39/* 41/*
40 * Attach a (component) device to the shared drm dma mapping from master drm 42 * Attach a (component) device to the shared drm dma mapping from master drm
41 * device. This is used by the VOPs to map GEM buffers to a common DMA 43 * 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,
47 struct dma_iommu_mapping *mapping = drm_dev->dev->archdata.mapping; 49 struct dma_iommu_mapping *mapping = drm_dev->dev->archdata.mapping;
48 int ret; 50 int ret;
49 51
52 if (!is_support_iommu)
53 return 0;
54
50 ret = dma_set_coherent_mask(dev, DMA_BIT_MASK(32)); 55 ret = dma_set_coherent_mask(dev, DMA_BIT_MASK(32));
51 if (ret) 56 if (ret)
52 return ret; 57 return ret;
@@ -59,6 +64,9 @@ int rockchip_drm_dma_attach_device(struct drm_device *drm_dev,
59void rockchip_drm_dma_detach_device(struct drm_device *drm_dev, 64void rockchip_drm_dma_detach_device(struct drm_device *drm_dev,
60 struct device *dev) 65 struct device *dev)
61{ 66{
67 if (!is_support_iommu)
68 return;
69
62 arm_iommu_detach_device(dev); 70 arm_iommu_detach_device(dev);
63} 71}
64 72
@@ -127,7 +135,7 @@ static void rockchip_drm_crtc_disable_vblank(struct drm_device *dev,
127static int rockchip_drm_load(struct drm_device *drm_dev, unsigned long flags) 135static int rockchip_drm_load(struct drm_device *drm_dev, unsigned long flags)
128{ 136{
129 struct rockchip_drm_private *private; 137 struct rockchip_drm_private *private;
130 struct dma_iommu_mapping *mapping; 138 struct dma_iommu_mapping *mapping = NULL;
131 struct device *dev = drm_dev->dev; 139 struct device *dev = drm_dev->dev;
132 struct drm_connector *connector; 140 struct drm_connector *connector;
133 int ret; 141 int ret;
@@ -152,23 +160,26 @@ static int rockchip_drm_load(struct drm_device *drm_dev, unsigned long flags)
152 goto err_config_cleanup; 160 goto err_config_cleanup;
153 } 161 }
154 162
155 /* TODO(djkurtz): fetch the mapping start/size from somewhere */ 163 if (is_support_iommu) {
156 mapping = arm_iommu_create_mapping(&platform_bus_type, 0x00000000, 164 /* TODO(djkurtz): fetch the mapping start/size from somewhere */
157 SZ_2G); 165 mapping = arm_iommu_create_mapping(&platform_bus_type,
158 if (IS_ERR(mapping)) { 166 0x00000000,
159 ret = PTR_ERR(mapping); 167 SZ_2G);
160 goto err_config_cleanup; 168 if (IS_ERR(mapping)) {
161 } 169 ret = PTR_ERR(mapping);
170 goto err_config_cleanup;
171 }
162 172
163 ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32)); 173 ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32));
164 if (ret) 174 if (ret)
165 goto err_release_mapping; 175 goto err_release_mapping;
166 176
167 dma_set_max_seg_size(dev, DMA_BIT_MASK(32)); 177 dma_set_max_seg_size(dev, DMA_BIT_MASK(32));
168 178
169 ret = arm_iommu_attach_device(dev, mapping); 179 ret = arm_iommu_attach_device(dev, mapping);
170 if (ret) 180 if (ret)
171 goto err_release_mapping; 181 goto err_release_mapping;
182 }
172 183
173 /* Try to bind all sub drivers. */ 184 /* Try to bind all sub drivers. */
174 ret = component_bind_all(dev, drm_dev); 185 ret = component_bind_all(dev, drm_dev);
@@ -218,7 +229,8 @@ static int rockchip_drm_load(struct drm_device *drm_dev, unsigned long flags)
218 if (ret) 229 if (ret)
219 goto err_vblank_cleanup; 230 goto err_vblank_cleanup;
220 231
221 arm_iommu_release_mapping(mapping); 232 if (is_support_iommu)
233 arm_iommu_release_mapping(mapping);
222 return 0; 234 return 0;
223err_vblank_cleanup: 235err_vblank_cleanup:
224 drm_vblank_cleanup(drm_dev); 236 drm_vblank_cleanup(drm_dev);
@@ -227,9 +239,11 @@ err_kms_helper_poll_fini:
227err_unbind: 239err_unbind:
228 component_unbind_all(dev, drm_dev); 240 component_unbind_all(dev, drm_dev);
229err_detach_device: 241err_detach_device:
230 arm_iommu_detach_device(dev); 242 if (is_support_iommu)
243 arm_iommu_detach_device(dev);
231err_release_mapping: 244err_release_mapping:
232 arm_iommu_release_mapping(mapping); 245 if (is_support_iommu)
246 arm_iommu_release_mapping(mapping);
233err_config_cleanup: 247err_config_cleanup:
234 drm_mode_config_cleanup(drm_dev); 248 drm_mode_config_cleanup(drm_dev);
235 drm_dev->dev_private = NULL; 249 drm_dev->dev_private = NULL;
@@ -244,7 +258,8 @@ static int rockchip_drm_unload(struct drm_device *drm_dev)
244 drm_vblank_cleanup(drm_dev); 258 drm_vblank_cleanup(drm_dev);
245 drm_kms_helper_poll_fini(drm_dev); 259 drm_kms_helper_poll_fini(drm_dev);
246 component_unbind_all(dev, drm_dev); 260 component_unbind_all(dev, drm_dev);
247 arm_iommu_detach_device(dev); 261 if (is_support_iommu)
262 arm_iommu_detach_device(dev);
248 drm_mode_config_cleanup(drm_dev); 263 drm_mode_config_cleanup(drm_dev);
249 drm_dev->dev_private = NULL; 264 drm_dev->dev_private = NULL;
250 265
@@ -488,6 +503,8 @@ static int rockchip_drm_platform_probe(struct platform_device *pdev)
488 * works as expected. 503 * works as expected.
489 */ 504 */
490 for (i = 0;; i++) { 505 for (i = 0;; i++) {
506 struct device_node *iommu;
507
491 port = of_parse_phandle(np, "ports", i); 508 port = of_parse_phandle(np, "ports", i);
492 if (!port) 509 if (!port)
493 break; 510 break;
@@ -497,6 +514,17 @@ static int rockchip_drm_platform_probe(struct platform_device *pdev)
497 continue; 514 continue;
498 } 515 }
499 516
517 iommu = of_parse_phandle(port->parent, "iommus", 0);
518 if (!iommu || !of_device_is_available(iommu->parent)) {
519 dev_dbg(dev, "no iommu attached for %s, using non-iommu buffers\n",
520 port->parent->full_name);
521 /*
522 * if there is a crtc not support iommu, force set all
523 * crtc use non-iommu buffer.
524 */
525 is_support_iommu = false;
526 }
527
500 component_match_add(dev, &match, compare_of, port->parent); 528 component_match_add(dev, &match, compare_of, port->parent);
501 of_node_put(port); 529 of_node_put(port);
502 } 530 }