aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/gpu/drm/rockchip/rockchip_drm_drv.c101
1 files changed, 54 insertions, 47 deletions
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
index c30d649cb147..b360e6251836 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
@@ -14,19 +14,19 @@
14 * GNU General Public License for more details. 14 * GNU General Public License for more details.
15 */ 15 */
16 16
17#include <asm/dma-iommu.h>
18
19#include <drm/drmP.h> 17#include <drm/drmP.h>
20#include <drm/drm_crtc_helper.h> 18#include <drm/drm_crtc_helper.h>
21#include <drm/drm_fb_helper.h> 19#include <drm/drm_fb_helper.h>
22#include <drm/drm_gem_cma_helper.h> 20#include <drm/drm_gem_cma_helper.h>
23#include <drm/drm_of.h> 21#include <drm/drm_of.h>
24#include <linux/dma-mapping.h> 22#include <linux/dma-mapping.h>
23#include <linux/dma-iommu.h>
25#include <linux/pm_runtime.h> 24#include <linux/pm_runtime.h>
26#include <linux/module.h> 25#include <linux/module.h>
27#include <linux/of_graph.h> 26#include <linux/of_graph.h>
28#include <linux/component.h> 27#include <linux/component.h>
29#include <linux/console.h> 28#include <linux/console.h>
29#include <linux/iommu.h>
30 30
31#include "rockchip_drm_drv.h" 31#include "rockchip_drm_drv.h"
32#include "rockchip_drm_fb.h" 32#include "rockchip_drm_fb.h"
@@ -50,28 +50,31 @@ static struct drm_driver rockchip_drm_driver;
50int rockchip_drm_dma_attach_device(struct drm_device *drm_dev, 50int rockchip_drm_dma_attach_device(struct drm_device *drm_dev,
51 struct device *dev) 51 struct device *dev)
52{ 52{
53 struct dma_iommu_mapping *mapping = drm_dev->dev->archdata.mapping; 53 struct rockchip_drm_private *private = drm_dev->dev_private;
54 int ret; 54 int ret;
55 55
56 if (!is_support_iommu) 56 if (!is_support_iommu)
57 return 0; 57 return 0;
58 58
59 ret = dma_set_coherent_mask(dev, DMA_BIT_MASK(32)); 59 ret = iommu_attach_device(private->domain, dev);
60 if (ret) 60 if (ret) {
61 dev_err(dev, "Failed to attach iommu device\n");
61 return ret; 62 return ret;
63 }
62 64
63 dma_set_max_seg_size(dev, DMA_BIT_MASK(32)); 65 return 0;
64
65 return arm_iommu_attach_device(dev, mapping);
66} 66}
67 67
68void rockchip_drm_dma_detach_device(struct drm_device *drm_dev, 68void rockchip_drm_dma_detach_device(struct drm_device *drm_dev,
69 struct device *dev) 69 struct device *dev)
70{ 70{
71 struct rockchip_drm_private *private = drm_dev->dev_private;
72 struct iommu_domain *domain = private->domain;
73
71 if (!is_support_iommu) 74 if (!is_support_iommu)
72 return; 75 return;
73 76
74 arm_iommu_detach_device(dev); 77 iommu_detach_device(domain, dev);
75} 78}
76 79
77int rockchip_register_crtc_funcs(struct drm_crtc *crtc, 80int rockchip_register_crtc_funcs(struct drm_crtc *crtc,
@@ -123,11 +126,46 @@ static void rockchip_drm_crtc_disable_vblank(struct drm_device *dev,
123 priv->crtc_funcs[pipe]->disable_vblank(crtc); 126 priv->crtc_funcs[pipe]->disable_vblank(crtc);
124} 127}
125 128
129static int rockchip_drm_init_iommu(struct drm_device *drm_dev)
130{
131 struct rockchip_drm_private *private = drm_dev->dev_private;
132 struct iommu_domain_geometry *geometry;
133 u64 start, end;
134
135 if (!is_support_iommu)
136 return 0;
137
138 private->domain = iommu_domain_alloc(&platform_bus_type);
139 if (!private->domain)
140 return -ENOMEM;
141
142 geometry = &private->domain->geometry;
143 start = geometry->aperture_start;
144 end = geometry->aperture_end;
145
146 DRM_DEBUG("IOMMU context initialized (aperture: %#llx-%#llx)\n",
147 start, end);
148 drm_mm_init(&private->mm, start, end - start + 1);
149 mutex_init(&private->mm_lock);
150
151 return 0;
152}
153
154static void rockchip_iommu_cleanup(struct drm_device *drm_dev)
155{
156 struct rockchip_drm_private *private = drm_dev->dev_private;
157
158 if (!is_support_iommu)
159 return;
160
161 drm_mm_takedown(&private->mm);
162 iommu_domain_free(private->domain);
163}
164
126static int rockchip_drm_bind(struct device *dev) 165static int rockchip_drm_bind(struct device *dev)
127{ 166{
128 struct drm_device *drm_dev; 167 struct drm_device *drm_dev;
129 struct rockchip_drm_private *private; 168 struct rockchip_drm_private *private;
130 struct dma_iommu_mapping *mapping = NULL;
131 int ret; 169 int ret;
132 170
133 drm_dev = drm_dev_alloc(&rockchip_drm_driver, dev); 171 drm_dev = drm_dev_alloc(&rockchip_drm_driver, dev);
@@ -151,38 +189,14 @@ static int rockchip_drm_bind(struct device *dev)
151 189
152 rockchip_drm_mode_config_init(drm_dev); 190 rockchip_drm_mode_config_init(drm_dev);
153 191
154 dev->dma_parms = devm_kzalloc(dev, sizeof(*dev->dma_parms), 192 ret = rockchip_drm_init_iommu(drm_dev);
155 GFP_KERNEL); 193 if (ret)
156 if (!dev->dma_parms) {
157 ret = -ENOMEM;
158 goto err_config_cleanup; 194 goto err_config_cleanup;
159 }
160
161 if (is_support_iommu) {
162 /* TODO(djkurtz): fetch the mapping start/size from somewhere */
163 mapping = arm_iommu_create_mapping(&platform_bus_type,
164 0x00000000,
165 SZ_2G);
166 if (IS_ERR(mapping)) {
167 ret = PTR_ERR(mapping);
168 goto err_config_cleanup;
169 }
170
171 ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32));
172 if (ret)
173 goto err_release_mapping;
174
175 dma_set_max_seg_size(dev, DMA_BIT_MASK(32));
176
177 ret = arm_iommu_attach_device(dev, mapping);
178 if (ret)
179 goto err_release_mapping;
180 }
181 195
182 /* Try to bind all sub drivers. */ 196 /* Try to bind all sub drivers. */
183 ret = component_bind_all(dev, drm_dev); 197 ret = component_bind_all(dev, drm_dev);
184 if (ret) 198 if (ret)
185 goto err_detach_device; 199 goto err_iommu_cleanup;
186 200
187 /* init kms poll for handling hpd */ 201 /* init kms poll for handling hpd */
188 drm_kms_helper_poll_init(drm_dev); 202 drm_kms_helper_poll_init(drm_dev);
@@ -207,8 +221,6 @@ static int rockchip_drm_bind(struct device *dev)
207 if (ret) 221 if (ret)
208 goto err_fbdev_fini; 222 goto err_fbdev_fini;
209 223
210 if (is_support_iommu)
211 arm_iommu_release_mapping(mapping);
212 return 0; 224 return 0;
213err_fbdev_fini: 225err_fbdev_fini:
214 rockchip_drm_fbdev_fini(drm_dev); 226 rockchip_drm_fbdev_fini(drm_dev);
@@ -217,12 +229,8 @@ err_vblank_cleanup:
217err_kms_helper_poll_fini: 229err_kms_helper_poll_fini:
218 drm_kms_helper_poll_fini(drm_dev); 230 drm_kms_helper_poll_fini(drm_dev);
219 component_unbind_all(dev, drm_dev); 231 component_unbind_all(dev, drm_dev);
220err_detach_device: 232err_iommu_cleanup:
221 if (is_support_iommu) 233 rockchip_iommu_cleanup(drm_dev);
222 arm_iommu_detach_device(dev);
223err_release_mapping:
224 if (is_support_iommu)
225 arm_iommu_release_mapping(mapping);
226err_config_cleanup: 234err_config_cleanup:
227 drm_mode_config_cleanup(drm_dev); 235 drm_mode_config_cleanup(drm_dev);
228 drm_dev->dev_private = NULL; 236 drm_dev->dev_private = NULL;
@@ -239,8 +247,7 @@ static void rockchip_drm_unbind(struct device *dev)
239 drm_vblank_cleanup(drm_dev); 247 drm_vblank_cleanup(drm_dev);
240 drm_kms_helper_poll_fini(drm_dev); 248 drm_kms_helper_poll_fini(drm_dev);
241 component_unbind_all(dev, drm_dev); 249 component_unbind_all(dev, drm_dev);
242 if (is_support_iommu) 250 rockchip_iommu_cleanup(drm_dev);
243 arm_iommu_detach_device(dev);
244 drm_mode_config_cleanup(drm_dev); 251 drm_mode_config_cleanup(drm_dev);
245 drm_dev->dev_private = NULL; 252 drm_dev->dev_private = NULL;
246 drm_dev_unregister(drm_dev); 253 drm_dev_unregister(drm_dev);