xref: /aosp_15_r20/external/libdrm/exynos/exynos_drm.c (revision 7688df22e49036ff52a766b7101da3a49edadb8c)
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