OSDN Git Service

intel: remove the drm_mm* symbol workarounds
[android-x86/external-libdrm.git] / tegra / tegra.c
1 /*
2  * Copyright © 2012, 2013 Thierry Reding
3  * Copyright © 2013 Erik Faye-Lund
4  * Copyright © 2014 NVIDIA Corporation
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a
7  * copy of this software and associated documentation files (the "Software"),
8  * to deal in the Software without restriction, including without limitation
9  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10  * and/or sell copies of the Software, and to permit persons to whom the
11  * Software is furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
20  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22  * OTHER DEALINGS IN THE SOFTWARE.
23  */
24
25 #ifdef HAVE_CONFIG_H
26 #  include "config.h"
27 #endif
28
29 #include <errno.h>
30 #include <fcntl.h>
31 #include <string.h>
32 #include <unistd.h>
33
34 #include <sys/mman.h>
35
36 #include <xf86drm.h>
37
38 #include <tegra_drm.h>
39
40 #include "private.h"
41
42 static void drm_tegra_bo_free(struct drm_tegra_bo *bo)
43 {
44         struct drm_tegra *drm = bo->drm;
45         struct drm_gem_close args;
46
47         if (bo->map)
48                 munmap(bo->map, bo->size);
49
50         memset(&args, 0, sizeof(args));
51         args.handle = bo->handle;
52
53         drmIoctl(drm->fd, DRM_IOCTL_GEM_CLOSE, &args);
54
55         free(bo);
56 }
57
58 static int drm_tegra_wrap(struct drm_tegra **drmp, int fd, bool close)
59 {
60         struct drm_tegra *drm;
61
62         if (fd < 0 || !drmp)
63                 return -EINVAL;
64
65         drm = calloc(1, sizeof(*drm));
66         if (!drm)
67                 return -ENOMEM;
68
69         drm->close = close;
70         drm->fd = fd;
71
72         *drmp = drm;
73
74         return 0;
75 }
76
77 drm_public
78 int drm_tegra_new(struct drm_tegra **drmp, int fd)
79 {
80         bool supported = false;
81         drmVersionPtr version;
82
83         version = drmGetVersion(fd);
84         if (!version)
85                 return -ENOMEM;
86
87         if (!strncmp(version->name, "tegra", version->name_len))
88                 supported = true;
89
90         drmFreeVersion(version);
91
92         if (!supported)
93                 return -ENOTSUP;
94
95         return drm_tegra_wrap(drmp, fd, false);
96 }
97
98 drm_public
99 void drm_tegra_close(struct drm_tegra *drm)
100 {
101         if (!drm)
102                 return;
103
104         if (drm->close)
105                 close(drm->fd);
106
107         free(drm);
108 }
109
110 drm_public
111 int drm_tegra_bo_new(struct drm_tegra_bo **bop, struct drm_tegra *drm,
112                      uint32_t flags, uint32_t size)
113 {
114         struct drm_tegra_gem_create args;
115         struct drm_tegra_bo *bo;
116         int err;
117
118         if (!drm || size == 0 || !bop)
119                 return -EINVAL;
120
121         bo = calloc(1, sizeof(*bo));
122         if (!bo)
123                 return -ENOMEM;
124
125         atomic_set(&bo->ref, 1);
126         bo->flags = flags;
127         bo->size = size;
128         bo->drm = drm;
129
130         memset(&args, 0, sizeof(args));
131         args.flags = flags;
132         args.size = size;
133
134         err = drmCommandWriteRead(drm->fd, DRM_TEGRA_GEM_CREATE, &args,
135                                   sizeof(args));
136         if (err < 0) {
137                 err = -errno;
138                 free(bo);
139                 return err;
140         }
141
142         bo->handle = args.handle;
143
144         *bop = bo;
145
146         return 0;
147 }
148
149 drm_public
150 int drm_tegra_bo_wrap(struct drm_tegra_bo **bop, struct drm_tegra *drm,
151                       uint32_t handle, uint32_t flags, uint32_t size)
152 {
153         struct drm_tegra_bo *bo;
154
155         if (!drm || !bop)
156                 return -EINVAL;
157
158         bo = calloc(1, sizeof(*bo));
159         if (!bo)
160                 return -ENOMEM;
161
162         atomic_set(&bo->ref, 1);
163         bo->handle = handle;
164         bo->flags = flags;
165         bo->size = size;
166         bo->drm = drm;
167
168         *bop = bo;
169
170         return 0;
171 }
172
173 drm_public
174 struct drm_tegra_bo *drm_tegra_bo_ref(struct drm_tegra_bo *bo)
175 {
176         if (bo)
177                 atomic_inc(&bo->ref);
178
179         return bo;
180 }
181
182 drm_public
183 void drm_tegra_bo_unref(struct drm_tegra_bo *bo)
184 {
185         if (bo && atomic_dec_and_test(&bo->ref))
186                 drm_tegra_bo_free(bo);
187 }
188
189 drm_public
190 int drm_tegra_bo_get_handle(struct drm_tegra_bo *bo, uint32_t *handle)
191 {
192         if (!bo || !handle)
193                 return -EINVAL;
194
195         *handle = bo->handle;
196
197         return 0;
198 }
199
200 drm_public
201 int drm_tegra_bo_map(struct drm_tegra_bo *bo, void **ptr)
202 {
203         struct drm_tegra *drm = bo->drm;
204
205         if (!bo->map) {
206                 struct drm_tegra_gem_mmap args;
207                 int err;
208
209                 memset(&args, 0, sizeof(args));
210                 args.handle = bo->handle;
211
212                 err = drmCommandWriteRead(drm->fd, DRM_TEGRA_GEM_MMAP, &args,
213                                           sizeof(args));
214                 if (err < 0)
215                         return -errno;
216
217                 bo->offset = args.offset;
218
219                 bo->map = mmap(0, bo->size, PROT_READ | PROT_WRITE, MAP_SHARED,
220                                drm->fd, bo->offset);
221                 if (bo->map == MAP_FAILED) {
222                         bo->map = NULL;
223                         return -errno;
224                 }
225         }
226
227         if (ptr)
228                 *ptr = bo->map;
229
230         return 0;
231 }
232
233 drm_public
234 int drm_tegra_bo_unmap(struct drm_tegra_bo *bo)
235 {
236         if (!bo)
237                 return -EINVAL;
238
239         if (!bo->map)
240                 return 0;
241
242         if (munmap(bo->map, bo->size))
243                 return -errno;
244
245         bo->map = NULL;
246
247         return 0;
248 }
249
250 drm_public
251 int drm_tegra_bo_get_flags(struct drm_tegra_bo *bo, uint32_t *flags)
252 {
253         struct drm_tegra_gem_get_flags args;
254         struct drm_tegra *drm = bo->drm;
255         int err;
256
257         if (!bo)
258                 return -EINVAL;
259
260         memset(&args, 0, sizeof(args));
261         args.handle = bo->handle;
262
263         err = drmCommandWriteRead(drm->fd, DRM_TEGRA_GEM_GET_FLAGS, &args,
264                                   sizeof(args));
265         if (err < 0)
266                 return -errno;
267
268         if (flags)
269                 *flags = args.flags;
270
271         return 0;
272 }
273
274 drm_public
275 int drm_tegra_bo_set_flags(struct drm_tegra_bo *bo, uint32_t flags)
276 {
277         struct drm_tegra_gem_get_flags args;
278         struct drm_tegra *drm = bo->drm;
279         int err;
280
281         if (!bo)
282                 return -EINVAL;
283
284         memset(&args, 0, sizeof(args));
285         args.handle = bo->handle;
286         args.flags = flags;
287
288         err = drmCommandWriteRead(drm->fd, DRM_TEGRA_GEM_SET_FLAGS, &args,
289                                   sizeof(args));
290         if (err < 0)
291                 return -errno;
292
293         return 0;
294 }
295
296 drm_public
297 int drm_tegra_bo_get_tiling(struct drm_tegra_bo *bo,
298                             struct drm_tegra_bo_tiling *tiling)
299 {
300         struct drm_tegra_gem_get_tiling args;
301         struct drm_tegra *drm = bo->drm;
302         int err;
303
304         if (!bo)
305                 return -EINVAL;
306
307         memset(&args, 0, sizeof(args));
308         args.handle = bo->handle;
309
310         err = drmCommandWriteRead(drm->fd, DRM_TEGRA_GEM_GET_TILING, &args,
311                                   sizeof(args));
312         if (err < 0)
313                 return -errno;
314
315         if (tiling) {
316                 tiling->mode = args.mode;
317                 tiling->value = args.value;
318         }
319
320         return 0;
321 }
322
323 drm_public
324 int drm_tegra_bo_set_tiling(struct drm_tegra_bo *bo,
325                             const struct drm_tegra_bo_tiling *tiling)
326 {
327         struct drm_tegra_gem_set_tiling args;
328         struct drm_tegra *drm = bo->drm;
329         int err;
330
331         if (!bo)
332                 return -EINVAL;
333
334         memset(&args, 0, sizeof(args));
335         args.handle = bo->handle;
336         args.mode = tiling->mode;
337         args.value = tiling->value;
338
339         err = drmCommandWriteRead(drm->fd, DRM_TEGRA_GEM_SET_TILING, &args,
340                                   sizeof(args));
341         if (err < 0)
342                 return -errno;
343
344         return 0;
345 }