OSDN Git Service

Export drmDevicesEqual
[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 int drm_tegra_new(struct drm_tegra **drmp, int fd)
78 {
79         bool supported = false;
80         drmVersionPtr version;
81
82         version = drmGetVersion(fd);
83         if (!version)
84                 return -ENOMEM;
85
86         if (!strncmp(version->name, "tegra", version->name_len))
87                 supported = true;
88
89         drmFreeVersion(version);
90
91         if (!supported)
92                 return -ENOTSUP;
93
94         return drm_tegra_wrap(drmp, fd, false);
95 }
96
97 void drm_tegra_close(struct drm_tegra *drm)
98 {
99         if (!drm)
100                 return;
101
102         if (drm->close)
103                 close(drm->fd);
104
105         free(drm);
106 }
107
108 int drm_tegra_bo_new(struct drm_tegra_bo **bop, struct drm_tegra *drm,
109                      uint32_t flags, uint32_t size)
110 {
111         struct drm_tegra_gem_create args;
112         struct drm_tegra_bo *bo;
113         int err;
114
115         if (!drm || size == 0 || !bop)
116                 return -EINVAL;
117
118         bo = calloc(1, sizeof(*bo));
119         if (!bo)
120                 return -ENOMEM;
121
122         atomic_set(&bo->ref, 1);
123         bo->flags = flags;
124         bo->size = size;
125         bo->drm = drm;
126
127         memset(&args, 0, sizeof(args));
128         args.flags = flags;
129         args.size = size;
130
131         err = drmCommandWriteRead(drm->fd, DRM_TEGRA_GEM_CREATE, &args,
132                                   sizeof(args));
133         if (err < 0) {
134                 err = -errno;
135                 free(bo);
136                 return err;
137         }
138
139         bo->handle = args.handle;
140
141         *bop = bo;
142
143         return 0;
144 }
145
146 int drm_tegra_bo_wrap(struct drm_tegra_bo **bop, struct drm_tegra *drm,
147                       uint32_t handle, uint32_t flags, uint32_t size)
148 {
149         struct drm_tegra_bo *bo;
150
151         if (!drm || !bop)
152                 return -EINVAL;
153
154         bo = calloc(1, sizeof(*bo));
155         if (!bo)
156                 return -ENOMEM;
157
158         atomic_set(&bo->ref, 1);
159         bo->handle = handle;
160         bo->flags = flags;
161         bo->size = size;
162         bo->drm = drm;
163
164         *bop = bo;
165
166         return 0;
167 }
168
169 struct drm_tegra_bo *drm_tegra_bo_ref(struct drm_tegra_bo *bo)
170 {
171         if (bo)
172                 atomic_inc(&bo->ref);
173
174         return bo;
175 }
176
177 void drm_tegra_bo_unref(struct drm_tegra_bo *bo)
178 {
179         if (bo && atomic_dec_and_test(&bo->ref))
180                 drm_tegra_bo_free(bo);
181 }
182
183 int drm_tegra_bo_get_handle(struct drm_tegra_bo *bo, uint32_t *handle)
184 {
185         if (!bo || !handle)
186                 return -EINVAL;
187
188         *handle = bo->handle;
189
190         return 0;
191 }
192
193 int drm_tegra_bo_map(struct drm_tegra_bo *bo, void **ptr)
194 {
195         struct drm_tegra *drm = bo->drm;
196
197         if (!bo->map) {
198                 struct drm_tegra_gem_mmap args;
199                 int err;
200
201                 memset(&args, 0, sizeof(args));
202                 args.handle = bo->handle;
203
204                 err = drmCommandWriteRead(drm->fd, DRM_TEGRA_GEM_MMAP, &args,
205                                           sizeof(args));
206                 if (err < 0)
207                         return -errno;
208
209                 bo->offset = args.offset;
210
211                 bo->map = mmap(0, bo->size, PROT_READ | PROT_WRITE, MAP_SHARED,
212                                drm->fd, bo->offset);
213                 if (bo->map == MAP_FAILED) {
214                         bo->map = NULL;
215                         return -errno;
216                 }
217         }
218
219         if (ptr)
220                 *ptr = bo->map;
221
222         return 0;
223 }
224
225 int drm_tegra_bo_unmap(struct drm_tegra_bo *bo)
226 {
227         if (!bo)
228                 return -EINVAL;
229
230         if (!bo->map)
231                 return 0;
232
233         if (munmap(bo->map, bo->size))
234                 return -errno;
235
236         bo->map = NULL;
237
238         return 0;
239 }
240
241 int drm_tegra_bo_get_flags(struct drm_tegra_bo *bo, uint32_t *flags)
242 {
243         struct drm_tegra_gem_get_flags args;
244         struct drm_tegra *drm = bo->drm;
245         int err;
246
247         if (!bo)
248                 return -EINVAL;
249
250         memset(&args, 0, sizeof(args));
251         args.handle = bo->handle;
252
253         err = drmCommandWriteRead(drm->fd, DRM_TEGRA_GEM_GET_FLAGS, &args,
254                                   sizeof(args));
255         if (err < 0)
256                 return -errno;
257
258         if (flags)
259                 *flags = args.flags;
260
261         return 0;
262 }
263
264 int drm_tegra_bo_set_flags(struct drm_tegra_bo *bo, uint32_t flags)
265 {
266         struct drm_tegra_gem_get_flags args;
267         struct drm_tegra *drm = bo->drm;
268         int err;
269
270         if (!bo)
271                 return -EINVAL;
272
273         memset(&args, 0, sizeof(args));
274         args.handle = bo->handle;
275         args.flags = flags;
276
277         err = drmCommandWriteRead(drm->fd, DRM_TEGRA_GEM_SET_FLAGS, &args,
278                                   sizeof(args));
279         if (err < 0)
280                 return -errno;
281
282         return 0;
283 }
284
285 int drm_tegra_bo_get_tiling(struct drm_tegra_bo *bo,
286                             struct drm_tegra_bo_tiling *tiling)
287 {
288         struct drm_tegra_gem_get_tiling args;
289         struct drm_tegra *drm = bo->drm;
290         int err;
291
292         if (!bo)
293                 return -EINVAL;
294
295         memset(&args, 0, sizeof(args));
296         args.handle = bo->handle;
297
298         err = drmCommandWriteRead(drm->fd, DRM_TEGRA_GEM_GET_TILING, &args,
299                                   sizeof(args));
300         if (err < 0)
301                 return -errno;
302
303         if (tiling) {
304                 tiling->mode = args.mode;
305                 tiling->value = args.value;
306         }
307
308         return 0;
309 }
310
311 int drm_tegra_bo_set_tiling(struct drm_tegra_bo *bo,
312                             const struct drm_tegra_bo_tiling *tiling)
313 {
314         struct drm_tegra_gem_set_tiling args;
315         struct drm_tegra *drm = bo->drm;
316         int err;
317
318         if (!bo)
319                 return -EINVAL;
320
321         memset(&args, 0, sizeof(args));
322         args.handle = bo->handle;
323         args.mode = tiling->mode;
324         args.value = tiling->value;
325
326         err = drmCommandWriteRead(drm->fd, DRM_TEGRA_GEM_SET_TILING, &args,
327                                   sizeof(args));
328         if (err < 0)
329                 return -errno;
330
331         return 0;
332 }