1 #include <ion/ion.h>
2 #include <linux/ion_4.12.h>
3 
4 #include "ion.h"
5 
ion_get_heap_id(int ion_fd,uint32_t heap_type)6 int ion_get_heap_id(int ion_fd, uint32_t heap_type)
7 {
8 	int heap_count = 0;
9 	int ret = -1;
10 
11 	if (ion_query_heap_cnt(ion_fd, &heap_count))
12 	{
13 		return -1;
14 	}
15 
16 	struct ion_heap_data *heap_data =
17 			malloc(heap_count * sizeof(struct ion_heap_data));
18 
19 	if (ion_query_get_heaps(ion_fd, heap_count, heap_data))
20 	{
21 		free(heap_data);
22 		return -1;
23 	}
24 
25 	for (struct ion_heap_data *hi = heap_data;
26 	     (hi - heap_data) < heap_count;
27 	     ++hi)
28 	{
29 		if (hi->type == heap_type)
30 		{
31 			ret = hi->heap_id;
32 			break;
33 		}
34 	}
35 
36 	free(heap_data);
37 
38 	return ret;
39 }
40 
41 static const int kBitsInAnInt = (sizeof(int) * 8);
42 
ion_alloc_one_fd(int ion_fd,size_t size,int heap_id,int * ion_buffer_fd)43 int ion_alloc_one_fd(int ion_fd, size_t size, int heap_id, int *ion_buffer_fd)
44 {
45 	if (heap_id < 0 || heap_id >= kBitsInAnInt)
46 	{
47 		return -1;
48 	}
49 
50 	const int align = 0;
51 	const int heap_mask = 1 << heap_id;
52 	const int flags = 0;
53 
54 	return ion_alloc_fd(ion_fd, size, align, heap_mask, flags, ion_buffer_fd);
55 }
56 
ion_mmap(void ** ptr,int ion_buffer_fd,size_t size)57 int ion_mmap(void **ptr, int ion_buffer_fd, size_t size)
58 {
59 	void *const k_addr = 0;
60 	const int k_prot = PROT_READ | PROT_WRITE;
61 	const int k_flags = MAP_SHARED;
62 
63 	void *ret = mmap(k_addr, size, k_prot, k_flags, ion_buffer_fd, 0);
64 
65 	if (ret == MAP_FAILED)
66 	{
67 		return -1;
68 	}
69 
70 	*ptr = ret;
71 	return 0;
72 }
73 
ion_munmap(void * ptr,size_t size)74 int ion_munmap(void *ptr, size_t size)
75 {
76 	if (munmap(ptr, size))
77 	{
78 		return -1;
79 	}
80 
81 	return 0;
82 }
83 
drm_check_prime_caps(int drm_fd)84 int drm_check_prime_caps(int drm_fd)
85 {
86 	struct drm_get_cap drm_get_cap_arg = {
87 		.capability = DRM_CAP_PRIME,
88 		.value = 0
89 	};
90 
91 	if (drmIoctl(drm_fd, DRM_IOCTL_GET_CAP, &drm_get_cap_arg))
92 	{
93 		return -1;
94 	}
95 
96 	if (!(drm_get_cap_arg.value & DRM_PRIME_CAP_IMPORT) ||
97 	    !(drm_get_cap_arg.value & DRM_PRIME_CAP_EXPORT))
98 	{
99 		return -1;
100 	}
101 
102 	return 0;
103 }
104 
gem_handle_for_ion_buffer(int drm_fd,uint32_t * gem_handle,int ion_buffer_fd)105 int gem_handle_for_ion_buffer(int drm_fd, uint32_t *gem_handle, int ion_buffer_fd)
106 {
107 	struct drm_prime_handle drm_prime_fd_to_handle_arg = {
108 		.handle = 0,
109 		.flags = 0,
110 		.fd = ion_buffer_fd
111 	};
112 
113 	if (drmIoctl(drm_fd,
114 		     DRM_IOCTL_PRIME_FD_TO_HANDLE,
115 		     &drm_prime_fd_to_handle_arg))
116 	{
117 		return -1;
118 	}
119 
120 	*gem_handle = drm_prime_fd_to_handle_arg.handle;
121 
122 	return 0;
123 }
124 
ion_fd_for_gem_handle(int drm_fd,int * ion_fd,uint32_t gem_handle)125 int ion_fd_for_gem_handle(int drm_fd, int *ion_fd, uint32_t gem_handle)
126 {
127 	struct drm_prime_handle drm_prime_handle_to_fd_arg = {
128 		.handle = gem_handle,
129 		.flags = 0,
130 		.fd = 0
131 	};
132 
133 	if (drmIoctl(drm_fd,
134 		     DRM_IOCTL_PRIME_HANDLE_TO_FD,
135 		     &drm_prime_handle_to_fd_arg))
136 	{
137 		return -1;
138 	}
139 
140 	*ion_fd = drm_prime_handle_to_fd_arg.fd;
141 
142 	return 0;
143 }
144 
drm_fb_for_ion_buffer(int drm_fd,uint32_t * fb_id,int ion_buffer_fd,const struct fb_configuration * fb_config)145 int drm_fb_for_ion_buffer(int drm_fd, uint32_t *fb_id, int ion_buffer_fd,
146 			  const struct fb_configuration *fb_config)
147 {
148 	uint32_t gem_handle = 0;
149 
150 	if (gem_handle_for_ion_buffer(drm_fd, &gem_handle, ion_buffer_fd))
151 	{
152 		return -1;
153 	}
154 
155 	int ret = drm_fb_for_gem_handle(drm_fd, fb_id, gem_handle, fb_config);
156 
157 	gem_release_handle(drm_fd, gem_handle);
158 	return ret;
159 }
160 
drm_release_fb(int drm_fd,uint32_t fb_id)161 void drm_release_fb(int drm_fd, uint32_t fb_id)
162 {
163 	(void)drmIoctl(drm_fd, DRM_IOCTL_MODE_RMFB, &fb_id);
164 }
165 
ion_clone_fd_via_gem(int drm_fd,int * cloned_fd,int ion_buffer_fd)166 int ion_clone_fd_via_gem(int drm_fd, int *cloned_fd, int ion_buffer_fd)
167 {
168 	uint32_t gem_handle = 0;
169 	if (gem_handle_for_ion_buffer(drm_fd, &gem_handle, ion_buffer_fd))
170 	{
171 		return -1;
172 	}
173 
174 	int ret = ion_fd_for_gem_handle(drm_fd, cloned_fd, gem_handle);
175 	gem_release_handle(drm_fd, gem_handle);
176 
177 	return ret;
178 }
179 
180 
181