blob: 4db755e7b3cfdbbb7aa20d7aa279904628b7b2bb [file] [log] [blame]
Inki Daee07b6502012-05-04 19:13:14 +09001/*
2 * Copyright (C) 2012 Samsung Electronics Co., Ltd.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 * SOFTWARE.
22 *
23 * Authors:
24 * Inki Dae <inki.dae@samsung.com>
25 */
26
27#ifdef HAVE_CONFIG_H
28#include "config.h"
29#endif
30
31#include <stdlib.h>
32#include <stdio.h>
33#include <string.h>
34#include <errno.h>
35
36#include <sys/mman.h>
37#include <linux/stddef.h>
38
39#include <xf86drm.h>
40
41#include "exynos_drm.h"
42#include "exynos_drmif.h"
43
44/*
45 * Create exynos drm device object.
46 *
47 * @fd: file descriptor to exynos drm driver opened.
48 *
49 * if true, return the device object else NULL.
50 */
51struct exynos_device * exynos_device_create(int fd)
52{
53 struct exynos_device *dev;
54
55 dev = calloc(sizeof(*dev), 1);
56 if (!dev) {
57 fprintf(stderr, "failed to create device[%s].\n",
58 strerror(errno));
59 return NULL;
60 }
61
62 dev->fd = fd;
63
64 return dev;
65}
66
67/*
68 * Destroy exynos drm device object
69 *
70 * @dev: exynos drm device object.
71 */
72void exynos_device_destroy(struct exynos_device *dev)
73{
74 free(dev);
75}
76
77/*
78 * Create a exynos buffer object to exynos drm device.
79 *
80 * @dev: exynos drm device object.
81 * @size: user-desired size.
82 * flags: user-desired memory type.
83 * user can set one or more types among several types to memory
84 * allocation and cache attribute types. and as default,
85 * EXYNOS_BO_NONCONTIG and EXYNOS-BO_NONCACHABLE types would
86 * be used.
87 *
88 * if true, return a exynos buffer object else NULL.
89 */
90struct exynos_bo * exynos_bo_create(struct exynos_device *dev,
91 size_t size, uint32_t flags)
92{
93 struct exynos_bo *bo;
94 struct drm_exynos_gem_create req = {
95 .size = size,
96 .flags = flags,
97 };
98
99 if (size == 0) {
100 fprintf(stderr, "invalid size.\n");
101 goto fail;
102 }
103
104 bo = calloc(sizeof(*bo), 1);
105 if (!bo) {
106 fprintf(stderr, "failed to create bo[%s].\n",
107 strerror(errno));
108 goto err_free_bo;
109 }
110
111 bo->dev = dev;
112
113 if (drmIoctl(dev->fd, DRM_IOCTL_EXYNOS_GEM_CREATE, &req)){
114 fprintf(stderr, "failed to create gem object[%s].\n",
115 strerror(errno));
116 goto err_free_bo;
117 }
118
119 bo->handle = req.handle;
120 bo->size = size;
121 bo->flags = flags;
122
123 return bo;
124
125err_free_bo:
126 free(bo);
127fail:
128 return NULL;
129}
130
131/*
132 * Get information to gem region allocated.
133 *
134 * @dev: exynos drm device object.
135 * @handle: gem handle to request gem info.
136 * @size: size to gem object and returned by kernel side.
137 * @flags: gem flags to gem object and returned by kernel side.
138 *
139 * with this function call, you can get flags and size to gem handle
140 * through bo object.
141 *
142 * if true, return 0 else negative.
143 */
144int exynos_bo_get_info(struct exynos_device *dev, uint32_t handle,
145 size_t *size, uint32_t *flags)
146{
147 int ret;
148 struct drm_exynos_gem_info req = {
149 .handle = handle,
150 };
151
152 ret = drmIoctl(dev->fd, DRM_IOCTL_EXYNOS_GEM_GET, &req);
153 if (ret < 0) {
154 fprintf(stderr, "failed to get gem object information[%s].\n",
155 strerror(errno));
156 return ret;
157 }
158
159 *size = req.size;
160 *flags = req.flags;
161
162 return 0;
163}
164
165/*
166 * Destroy a exynos buffer object.
167 *
168 * @bo: a exynos buffer object to be destroyed.
169 */
170void exynos_bo_destroy(struct exynos_bo *bo)
171{
172 if (!bo)
173 return;
174
175 if (bo->vaddr)
176 munmap(bo->vaddr, bo->size);
177
178 if (bo->handle) {
179 struct drm_gem_close req = {
180 .handle = bo->handle,
181 };
182
183 drmIoctl(bo->dev->fd, DRM_IOCTL_GEM_CLOSE, &req);
184 }
185
186 free(bo);
187}
188
189
190/*
191 * Get a exynos buffer object from a gem global object name.
192 *
193 * @dev: a exynos device object.
194 * @name: a gem global object name exported by another process.
195 *
196 * this interface is used to get a exynos buffer object from a gem
197 * global object name sent by another process for buffer sharing.
198 *
199 * if true, return a exynos buffer object else NULL.
200 *
201 */
202struct exynos_bo * exynos_bo_from_name(struct exynos_device *dev, uint32_t name)
203{
204 struct exynos_bo *bo;
205 struct drm_gem_open req = {
206 .name = name,
207 };
208
209 bo = calloc(sizeof(*bo), 1);
210 if (!bo) {
211 fprintf(stderr, "failed to allocate bo[%s].\n",
212 strerror(errno));
213 return NULL;
214 }
215
216 if (drmIoctl(dev->fd, DRM_IOCTL_GEM_OPEN, &req)) {
217 fprintf(stderr, "failed to open gem object[%s].\n",
218 strerror(errno));
219 goto err_free_bo;
220 }
221
222 bo->dev = dev;
223 bo->name = name;
224 bo->handle = req.handle;
225
226 return bo;
227
228err_free_bo:
229 free(bo);
230 return NULL;
231}
232
233/*
234 * Get a gem global object name from a gem object handle.
235 *
236 * @bo: a exynos buffer object including gem handle.
237 * @name: a gem global object name to be got by kernel driver.
238 *
239 * this interface is used to get a gem global object name from a gem object
240 * handle to a buffer that wants to share it with another process.
241 *
242 * if true, return 0 else negative.
243 */
244int exynos_bo_get_name(struct exynos_bo *bo, uint32_t *name)
245{
246 if (!bo->name) {
247 struct drm_gem_flink req = {
248 .handle = bo->handle,
249 };
250 int ret;
251
252 ret = drmIoctl(bo->dev->fd, DRM_IOCTL_GEM_FLINK, &req);
253 if (ret) {
254 fprintf(stderr, "failed to get gem global name[%s].\n",
255 strerror(errno));
256 return ret;
257 }
258
259 bo->name = req.name;
260 }
261
262 *name = bo->name;
263
264 return 0;
265}
266
267uint32_t exynos_bo_handle(struct exynos_bo *bo)
268{
269 return bo->handle;
270}
271
272/*
273 * Mmap a buffer to user space.
274 *
275 * @bo: a exynos buffer object including a gem object handle to be mmapped
276 * to user space.
277 *
278 * if true, user pointer mmaped else NULL.
279 */
280void *exynos_bo_map(struct exynos_bo *bo)
281{
282 if (!bo->vaddr) {
283 struct exynos_device *dev = bo->dev;
284 struct drm_exynos_gem_mmap req = {
285 .handle = bo->handle,
286 .size = bo->size,
287 };
288 int ret;
289
290 ret = drmIoctl(dev->fd, DRM_IOCTL_EXYNOS_GEM_MMAP, &req);
291 if (ret) {
292 fprintf(stderr, "failed to mmap[%s].\n",
293 strerror(errno));
294 return NULL;
295 }
296
297 bo->vaddr = req.mapped;
298 }
299
300 return bo->vaddr;
301}
302
303/*
304 * Export gem object to dmabuf as file descriptor.
305 *
306 * @dev: a exynos device object.
307 * @handle: gem handle to be exported into dmabuf as file descriptor.
308 * @fd: file descriptor to dmabuf exported from gem handle and
309 * returned by kernel side.
310 *
311 * if true, return 0 else negative.
312 */
313int exynos_prime_handle_to_fd(struct exynos_device *dev, uint32_t handle,
314 int *fd)
315{
316 int ret;
317 struct drm_prime_handle req = {
318 .handle = handle,
319 };
320
321 ret = drmIoctl(dev->fd, DRM_IOCTL_PRIME_HANDLE_TO_FD, &req);
322 if (ret) {
323 fprintf(stderr, "failed to mmap[%s].\n",
324 strerror(errno));
325 return ret;
326 }
327
328 *fd = req.fd;
329 return 0;
330}
331
332/*
333 * Import file descriptor into gem handle.
334 *
335 * @dev: a exynos device object.
336 * @fd: file descriptor exported into dmabuf.
337 * @handle: gem handle to gem object imported from file descriptor
338 * and returned by kernel side.
339 *
340 * if true, return 0 else negative.
341 */
342int exynos_prime_fd_to_handle(struct exynos_device *dev, int fd,
343 uint32_t *handle)
344{
345 int ret;
346 struct drm_prime_handle req = {
347 .fd = fd,
348 };
349
350 ret = drmIoctl(dev->fd, DRM_IOCTL_PRIME_FD_TO_HANDLE, &req);
351 if (ret) {
352 fprintf(stderr, "failed to mmap[%s].\n",
353 strerror(errno));
354 return ret;
355 }
356
357 *handle = req.handle;
358 return 0;
359}
360
361
362
363/*
364 * Request Wireless Display connection or disconnection.
365 *
366 * @dev: a exynos device object.
367 * @connect: indicate whether connectoin or disconnection request.
368 * @ext: indicate whether edid data includes extentions data or not.
369 * @edid: a pointer to edid data from Wireless Display device.
370 *
371 * this interface is used to request Virtual Display driver connection or
372 * disconnection. for this, user should get a edid data from the Wireless
373 * Display device and then send that data to kernel driver with connection
374 * request
375 *
376 * if true, return 0 else negative.
377 */
378int exynos_vidi_connection(struct exynos_device *dev, uint32_t connect,
379 uint32_t ext, void *edid)
380{
381 struct drm_exynos_vidi_connection req = {
382 .connection = connect,
383 .extensions = ext,
384 .edid = edid,
385 };
386 int ret;
387
388 ret = drmIoctl(dev->fd, DRM_IOCTL_EXYNOS_VIDI_CONNECTION, &req);
389 if (ret) {
390 fprintf(stderr, "failed to request vidi connection[%s].\n",
391 strerror(errno));
392 return ret;
393 }
394
395 return 0;
396}