diff options
author | Mark Yao <mark.yao@rock-chips.com> | 2016-04-18 22:13:27 -0400 |
---|---|---|
committer | Mark Yao <mark.yao@rock-chips.com> | 2016-05-03 02:11:23 -0400 |
commit | 2d90d477430d3a20df74f2d11c21378e64e1d508 (patch) | |
tree | c1769bb7a9662bee510f53f382737235c194def1 | |
parent | 4e257d9eee23582e36637ce7ea6b14f6f56b1839 (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.c | 66 |
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 | ||
39 | static 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, | |||
59 | void rockchip_drm_dma_detach_device(struct drm_device *drm_dev, | 64 | void 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, | |||
127 | static int rockchip_drm_load(struct drm_device *drm_dev, unsigned long flags) | 135 | static 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; |
223 | err_vblank_cleanup: | 235 | err_vblank_cleanup: |
224 | drm_vblank_cleanup(drm_dev); | 236 | drm_vblank_cleanup(drm_dev); |
@@ -227,9 +239,11 @@ err_kms_helper_poll_fini: | |||
227 | err_unbind: | 239 | err_unbind: |
228 | component_unbind_all(dev, drm_dev); | 240 | component_unbind_all(dev, drm_dev); |
229 | err_detach_device: | 241 | err_detach_device: |
230 | arm_iommu_detach_device(dev); | 242 | if (is_support_iommu) |
243 | arm_iommu_detach_device(dev); | ||
231 | err_release_mapping: | 244 | err_release_mapping: |
232 | arm_iommu_release_mapping(mapping); | 245 | if (is_support_iommu) |
246 | arm_iommu_release_mapping(mapping); | ||
233 | err_config_cleanup: | 247 | err_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 | } |