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