diff options
Diffstat (limited to 'drivers/gpu/ion/omap/omap_ion.c')
-rwxr-xr-x | drivers/gpu/ion/omap/omap_ion.c | 299 |
1 files changed, 299 insertions, 0 deletions
diff --git a/drivers/gpu/ion/omap/omap_ion.c b/drivers/gpu/ion/omap/omap_ion.c new file mode 100755 index 00000000000..e9b91f0787d --- /dev/null +++ b/drivers/gpu/ion/omap/omap_ion.c | |||
@@ -0,0 +1,299 @@ | |||
1 | /* | ||
2 | * drivers/gpu/omap/omap_ion.c | ||
3 | * | ||
4 | * Copyright (C) 2011 Google, Inc. | ||
5 | * | ||
6 | * This software is licensed under the terms of the GNU General Public | ||
7 | * License version 2, as published by the Free Software Foundation, and | ||
8 | * may be copied, distributed, and modified under those terms. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | * | ||
15 | */ | ||
16 | |||
17 | #include <linux/err.h> | ||
18 | #include <linux/ion.h> | ||
19 | #include <linux/omap_ion.h> | ||
20 | #include <linux/platform_device.h> | ||
21 | #include <linux/slab.h> | ||
22 | #include <linux/uaccess.h> | ||
23 | #include "../ion_priv.h" | ||
24 | #include "omap_ion_priv.h" | ||
25 | #include <linux/module.h> | ||
26 | #include <linux/of.h> | ||
27 | |||
28 | |||
29 | struct ion_device *omap_ion_device; | ||
30 | EXPORT_SYMBOL(omap_ion_device); | ||
31 | |||
32 | static int num_heaps; | ||
33 | static struct ion_heap **heaps; | ||
34 | static struct ion_heap *tiler_heap; | ||
35 | static struct ion_heap *nonsecure_tiler_heap; | ||
36 | |||
37 | static struct ion_platform_data omap_ion_data = { | ||
38 | .nr = 5, | ||
39 | .heaps = { | ||
40 | { | ||
41 | .type = ION_HEAP_TYPE_CARVEOUT, | ||
42 | .id = OMAP_ION_HEAP_SECURE_INPUT, | ||
43 | .name = "secure_input", | ||
44 | }, | ||
45 | { .type = OMAP_ION_HEAP_TYPE_TILER, | ||
46 | .id = OMAP_ION_HEAP_TILER, | ||
47 | .name = "tiler", | ||
48 | }, | ||
49 | { | ||
50 | .type = OMAP_ION_HEAP_TYPE_TILER, | ||
51 | .id = OMAP_ION_HEAP_NONSECURE_TILER, | ||
52 | .name = "nonsecure_tiler", | ||
53 | }, | ||
54 | { | ||
55 | .type = ION_HEAP_TYPE_SYSTEM, | ||
56 | .id = OMAP_ION_HEAP_SYSTEM, | ||
57 | .name = "system", | ||
58 | }, | ||
59 | { | ||
60 | .type = OMAP_ION_HEAP_TYPE_TILER_RESERVATION, | ||
61 | .id = OMAP_ION_HEAP_TILER_RESERVATION, | ||
62 | .name = "tiler_reservation", | ||
63 | }, | ||
64 | }, | ||
65 | }; | ||
66 | |||
67 | |||
68 | int omap_ion_tiler_alloc(struct ion_client *client, | ||
69 | struct omap_ion_tiler_alloc_data *data) | ||
70 | { | ||
71 | return omap_tiler_alloc(tiler_heap, client, data); | ||
72 | } | ||
73 | EXPORT_SYMBOL(omap_ion_tiler_alloc); | ||
74 | |||
75 | int omap_ion_nonsecure_tiler_alloc(struct ion_client *client, | ||
76 | struct omap_ion_tiler_alloc_data *data) | ||
77 | { | ||
78 | if (!nonsecure_tiler_heap) | ||
79 | return -ENOMEM; | ||
80 | return omap_tiler_alloc(nonsecure_tiler_heap, client, data); | ||
81 | } | ||
82 | EXPORT_SYMBOL(omap_ion_nonsecure_tiler_alloc); | ||
83 | |||
84 | static long omap_ion_ioctl(struct ion_client *client, unsigned int cmd, | ||
85 | unsigned long arg) | ||
86 | { | ||
87 | switch (cmd) { | ||
88 | case OMAP_ION_TILER_ALLOC: | ||
89 | { | ||
90 | struct omap_ion_tiler_alloc_data data; | ||
91 | int ret; | ||
92 | |||
93 | if (!tiler_heap) { | ||
94 | pr_err("%s: Tiler heap requested but no tiler heap " | ||
95 | "exists on this platform\n", __func__); | ||
96 | return -EINVAL; | ||
97 | } | ||
98 | if (copy_from_user(&data, (void __user *)arg, sizeof(data))) | ||
99 | return -EFAULT; | ||
100 | ret = omap_ion_tiler_alloc(client, &data); | ||
101 | if (ret) | ||
102 | return ret; | ||
103 | if (copy_to_user((void __user *)arg, &data, | ||
104 | sizeof(data))) | ||
105 | return -EFAULT; | ||
106 | break; | ||
107 | } | ||
108 | default: | ||
109 | pr_err("%s: Unknown custom ioctl\n", __func__); | ||
110 | return -ENOTTY; | ||
111 | } | ||
112 | return 0; | ||
113 | } | ||
114 | |||
115 | static int omap_ion_probe(struct platform_device *pdev) | ||
116 | { | ||
117 | int err; | ||
118 | int i; | ||
119 | struct device_node *node = pdev->dev.of_node; | ||
120 | uint omap_ion_heap_secure_input_base = 0; | ||
121 | uint omap_ion_heap_tiler_base = 0; | ||
122 | uint omap_ion_heap_nonsecure_tiler_base = 0; | ||
123 | uint omap_ion_heap_secure_input_size = 0; | ||
124 | uint omap_ion_heap_tiler_size = 0; | ||
125 | uint omap_ion_heap_nonsecure_tiler_size = 0; | ||
126 | |||
127 | omap_ion_device = ion_device_create(omap_ion_ioctl); | ||
128 | if (IS_ERR_OR_NULL(omap_ion_device)) { | ||
129 | kfree(heaps); | ||
130 | return PTR_ERR(omap_ion_device); | ||
131 | } | ||
132 | |||
133 | if (node) { | ||
134 | of_property_read_u32(node, "ti,omap_ion_heap_secure_input_base", | ||
135 | &omap_ion_heap_secure_input_base); | ||
136 | of_property_read_u32(node, "ti,omap_ion_heap_tiler_base", | ||
137 | &omap_ion_heap_tiler_size); | ||
138 | of_property_read_u32(node, "ti,omap_ion_heap_nonsecure_tiler_base", | ||
139 | &omap_ion_heap_nonsecure_tiler_base); | ||
140 | |||
141 | of_property_read_u32(node, "ti,omap_ion_heap_secure_input_size", | ||
142 | &omap_ion_heap_secure_input_size); | ||
143 | of_property_read_u32(node, "ti,omap_ion_heap_tiler_size", | ||
144 | &omap_ion_heap_tiler_size); | ||
145 | of_property_read_u32(node, "ti,omap_ion_heap_nonsecure_tiler_size", | ||
146 | &omap_ion_heap_nonsecure_tiler_size); | ||
147 | } | ||
148 | |||
149 | num_heaps = omap_ion_data.nr; | ||
150 | |||
151 | heaps = kzalloc(sizeof(struct ion_heap *)*num_heaps, GFP_KERNEL); | ||
152 | |||
153 | |||
154 | for (i = 0; i < num_heaps; i++) { | ||
155 | struct ion_platform_heap *heap_data = &omap_ion_data.heaps[i]; | ||
156 | if (heap_data->type == (enum ion_heap_type)OMAP_ION_HEAP_TYPE_TILER) { | ||
157 | if (heap_data->id == OMAP_ION_HEAP_NONSECURE_TILER) { | ||
158 | heap_data->base = omap_ion_heap_nonsecure_tiler_base; | ||
159 | heap_data->size = omap_ion_heap_nonsecure_tiler_size; | ||
160 | } else { | ||
161 | heap_data->base = omap_ion_heap_tiler_base; | ||
162 | heap_data->size = omap_ion_heap_tiler_size; | ||
163 | } | ||
164 | } else if (heap_data->type == | ||
165 | ION_HEAP_TYPE_CARVEOUT && heap_data->id == OMAP_ION_HEAP_SECURE_INPUT) { | ||
166 | heap_data->base = omap_ion_heap_secure_input_base; | ||
167 | heap_data->size = omap_ion_heap_secure_input_size; | ||
168 | } | ||
169 | } | ||
170 | |||
171 | /* create the heaps as specified in the board file */ | ||
172 | for (i = 0; i < num_heaps; i++) { | ||
173 | struct ion_platform_heap *heap_data = &omap_ion_data.heaps[i]; | ||
174 | if (heap_data->type == (enum ion_heap_type)OMAP_ION_HEAP_TYPE_TILER) { | ||
175 | heaps[i] = omap_tiler_heap_create(heap_data); | ||
176 | if (heap_data->id == OMAP_ION_HEAP_NONSECURE_TILER) | ||
177 | nonsecure_tiler_heap = heaps[i]; | ||
178 | else | ||
179 | tiler_heap = heaps[i]; | ||
180 | } else if (heap_data->type == | ||
181 | (enum ion_heap_type)OMAP_ION_HEAP_TYPE_TILER_RESERVATION) { | ||
182 | heaps[i] = omap_tiler_heap_create(heap_data); | ||
183 | } else { | ||
184 | heap_data->size = omap_ion_heap_secure_input_size; | ||
185 | heaps[i] = ion_heap_create(heap_data); | ||
186 | } | ||
187 | if (IS_ERR_OR_NULL(heaps[i])) { | ||
188 | err = PTR_ERR(heaps[i]); | ||
189 | goto err; | ||
190 | } | ||
191 | ion_device_add_heap(omap_ion_device, heaps[i]); | ||
192 | pr_info("%s: adding heap %s of type %d with %lx@%x\n", | ||
193 | __func__, heap_data->name, heap_data->type, | ||
194 | heap_data->base, heap_data->size); | ||
195 | |||
196 | } | ||
197 | |||
198 | platform_set_drvdata(pdev, omap_ion_device); | ||
199 | return 0; | ||
200 | err: | ||
201 | for (i = 0; i < num_heaps; i++) { | ||
202 | if (heaps[i]) { | ||
203 | if (heaps[i]->type == (enum ion_heap_type)OMAP_ION_HEAP_TYPE_TILER) | ||
204 | omap_tiler_heap_destroy(heaps[i]); | ||
205 | else | ||
206 | ion_heap_destroy(heaps[i]); | ||
207 | } | ||
208 | } | ||
209 | kfree(heaps); | ||
210 | return err; | ||
211 | } | ||
212 | |||
213 | static int omap_ion_remove(struct platform_device *pdev) | ||
214 | { | ||
215 | struct ion_device *idev = platform_get_drvdata(pdev); | ||
216 | int i; | ||
217 | |||
218 | ion_device_destroy(idev); | ||
219 | for (i = 0; i < num_heaps; i++) | ||
220 | if (heaps[i]->type == (enum ion_heap_type)OMAP_ION_HEAP_TYPE_TILER) | ||
221 | omap_tiler_heap_destroy(heaps[i]); | ||
222 | else | ||
223 | ion_heap_destroy(heaps[i]); | ||
224 | kfree(heaps); | ||
225 | return 0; | ||
226 | } | ||
227 | |||
228 | static void (*export_fd_to_ion_handles)(int fd, | ||
229 | struct ion_client **client, | ||
230 | struct ion_handle **handles, | ||
231 | int *num_handles); | ||
232 | |||
233 | void omap_ion_register_pvr_export(void *pvr_export_fd) | ||
234 | { | ||
235 | export_fd_to_ion_handles = pvr_export_fd; | ||
236 | } | ||
237 | EXPORT_SYMBOL(omap_ion_register_pvr_export); | ||
238 | |||
239 | int omap_ion_share_fd_to_buffers(int fd, struct ion_buffer **buffers, | ||
240 | int *num_handles) | ||
241 | { | ||
242 | struct ion_handle **handles; | ||
243 | struct ion_client *client; | ||
244 | int i = 0, ret = 0; | ||
245 | |||
246 | handles = kzalloc(*num_handles * sizeof(struct ion_handle *), | ||
247 | GFP_KERNEL); | ||
248 | if (!handles) | ||
249 | return -ENOMEM; | ||
250 | |||
251 | if (export_fd_to_ion_handles) { | ||
252 | export_fd_to_ion_handles(fd, | ||
253 | &client, | ||
254 | handles, | ||
255 | num_handles); | ||
256 | } else { | ||
257 | pr_err("%s: export_fd_to_ion_handles not initialized", | ||
258 | __func__); | ||
259 | ret = -EINVAL; | ||
260 | goto exit; | ||
261 | } | ||
262 | |||
263 | for (i = 0; i < *num_handles; i++) { | ||
264 | if (handles[i]) | ||
265 | buffers[i] = ion_share_dma_buf(client, handles[i]); | ||
266 | } | ||
267 | |||
268 | exit: | ||
269 | kfree(handles); | ||
270 | return ret; | ||
271 | } | ||
272 | EXPORT_SYMBOL(omap_ion_share_fd_to_buffers); | ||
273 | |||
274 | static const struct of_device_id omap_ion_of_match[] = { | ||
275 | {.compatible = "ti,ion-omap", }, | ||
276 | { }, | ||
277 | }; | ||
278 | |||
279 | |||
280 | static struct platform_driver ion_driver = { | ||
281 | .probe = omap_ion_probe, | ||
282 | .remove = omap_ion_remove, | ||
283 | .driver = { .name = "ion-omap", | ||
284 | .of_match_table = omap_ion_of_match | ||
285 | } | ||
286 | }; | ||
287 | |||
288 | static int __init ion_init(void) | ||
289 | { | ||
290 | return platform_driver_register(&ion_driver); | ||
291 | } | ||
292 | |||
293 | static void __exit ion_exit(void) | ||
294 | { | ||
295 | platform_driver_unregister(&ion_driver); | ||
296 | } | ||
297 | |||
298 | module_init(ion_init); | ||
299 | module_exit(ion_exit); | ||