diff options
Diffstat (limited to 'rockchip/rockchip_drm.c')
-rw-r--r-- | rockchip/rockchip_drm.c | 274 |
1 files changed, 274 insertions, 0 deletions
diff --git a/rockchip/rockchip_drm.c b/rockchip/rockchip_drm.c new file mode 100644 index 00000000..d56a68b4 --- /dev/null +++ b/rockchip/rockchip_drm.c | |||
@@ -0,0 +1,274 @@ | |||
1 | /* | ||
2 | * Copyright (C) ROCKCHIP, Inc. | ||
3 | * Author:yzq<yzq@rock-chips.com> | ||
4 | * | ||
5 | * based on exynos_drm.c | ||
6 | * | ||
7 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
8 | * copy of this software and associated documentation files (the "Software"), | ||
9 | * to deal in the Software without restriction, including without limitation | ||
10 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
11 | * and/or sell copies of the Software, and to permit persons to whom the | ||
12 | * Software is furnished to do so, subject to the following conditions: | ||
13 | * | ||
14 | * The above copyright notice and this permission notice (including the next | ||
15 | * paragraph) shall be included in all copies or substantial portions of the | ||
16 | * Software. | ||
17 | * | ||
18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
21 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
24 | * SOFTWARE. | ||
25 | * | ||
26 | */ | ||
27 | |||
28 | #ifdef HAVE_CONFIG_H | ||
29 | #include "config.h" | ||
30 | #endif | ||
31 | |||
32 | #include <stdlib.h> | ||
33 | #include <stdio.h> | ||
34 | #include <string.h> | ||
35 | #include <errno.h> | ||
36 | |||
37 | #include <sys/mman.h> | ||
38 | #include <linux/stddef.h> | ||
39 | |||
40 | #include <xf86drm.h> | ||
41 | |||
42 | #include "rockchip_drm.h" | ||
43 | #include "rockchip_drmif.h" | ||
44 | |||
45 | /* | ||
46 | * Create rockchip drm device object. | ||
47 | * | ||
48 | * @fd: file descriptor to rockchip drm driver opened. | ||
49 | * | ||
50 | * if true, return the device object else NULL. | ||
51 | */ | ||
52 | struct rockchip_device *rockchip_device_create(int fd) | ||
53 | { | ||
54 | struct rockchip_device *dev; | ||
55 | |||
56 | dev = calloc(1, sizeof(*dev)); | ||
57 | if (!dev) { | ||
58 | fprintf(stderr, "failed to create device[%s].\n", | ||
59 | strerror(errno)); | ||
60 | return NULL; | ||
61 | } | ||
62 | |||
63 | dev->fd = fd; | ||
64 | |||
65 | return dev; | ||
66 | } | ||
67 | |||
68 | /* | ||
69 | * Destroy rockchip drm device object | ||
70 | * | ||
71 | * @dev: rockchip drm device object. | ||
72 | */ | ||
73 | void rockchip_device_destroy(struct rockchip_device *dev) | ||
74 | { | ||
75 | free(dev); | ||
76 | } | ||
77 | |||
78 | /* | ||
79 | * Create a rockchip buffer object to rockchip drm device. | ||
80 | * | ||
81 | * @dev: rockchip drm device object. | ||
82 | * @size: user-desired size. | ||
83 | * flags: user-desired memory type. | ||
84 | * user can set one or more types among several types to memory | ||
85 | * allocation and cache attribute types. and as default, | ||
86 | * ROCKCHIP_BO_NONCONTIG and ROCKCHIP-BO_NONCACHABLE types would | ||
87 | * be used. | ||
88 | * | ||
89 | * if true, return a rockchip buffer object else NULL. | ||
90 | */ | ||
91 | struct rockchip_bo *rockchip_bo_create(struct rockchip_device *dev, | ||
92 | size_t size, uint32_t flags) | ||
93 | { | ||
94 | struct rockchip_bo *bo; | ||
95 | struct drm_rockchip_gem_create req = { | ||
96 | .size = size, | ||
97 | .flags = flags, | ||
98 | }; | ||
99 | |||
100 | if (size == 0) { | ||
101 | fprintf(stderr, "invalid size.\n"); | ||
102 | return NULL; | ||
103 | } | ||
104 | |||
105 | bo = calloc(1, sizeof(*bo)); | ||
106 | if (!bo) { | ||
107 | fprintf(stderr, "failed to create bo[%s].\n", | ||
108 | strerror(errno)); | ||
109 | goto fail; | ||
110 | } | ||
111 | |||
112 | bo->dev = dev; | ||
113 | |||
114 | if (drmIoctl(dev->fd, DRM_IOCTL_ROCKCHIP_GEM_CREATE, &req)){ | ||
115 | fprintf(stderr, "failed to create gem object[%s].\n", | ||
116 | strerror(errno)); | ||
117 | goto err_free_bo; | ||
118 | } | ||
119 | |||
120 | bo->handle = req.handle; | ||
121 | bo->size = size; | ||
122 | bo->flags = flags; | ||
123 | |||
124 | return bo; | ||
125 | |||
126 | err_free_bo: | ||
127 | free(bo); | ||
128 | fail: | ||
129 | return NULL; | ||
130 | } | ||
131 | |||
132 | /* | ||
133 | * Destroy a rockchip buffer object. | ||
134 | * | ||
135 | * @bo: a rockchip buffer object to be destroyed. | ||
136 | */ | ||
137 | void rockchip_bo_destroy(struct rockchip_bo *bo) | ||
138 | { | ||
139 | if (!bo) | ||
140 | return; | ||
141 | |||
142 | if (bo->vaddr) | ||
143 | munmap(bo->vaddr, bo->size); | ||
144 | |||
145 | if (bo->handle) { | ||
146 | struct drm_gem_close req = { | ||
147 | .handle = bo->handle, | ||
148 | }; | ||
149 | |||
150 | drmIoctl(bo->dev->fd, DRM_IOCTL_GEM_CLOSE, &req); | ||
151 | } | ||
152 | |||
153 | free(bo); | ||
154 | } | ||
155 | |||
156 | |||
157 | /* | ||
158 | * Get a rockchip buffer object from a gem global object name. | ||
159 | * | ||
160 | * @dev: a rockchip device object. | ||
161 | * @name: a gem global object name exported by another process. | ||
162 | * | ||
163 | * this interface is used to get a rockchip buffer object from a gem | ||
164 | * global object name sent by another process for buffer sharing. | ||
165 | * | ||
166 | * if true, return a rockchip buffer object else NULL. | ||
167 | * | ||
168 | */ | ||
169 | struct rockchip_bo *rockchip_bo_from_name(struct rockchip_device *dev, | ||
170 | uint32_t name) | ||
171 | { | ||
172 | struct rockchip_bo *bo; | ||
173 | struct drm_gem_open req = { | ||
174 | .name = name, | ||
175 | }; | ||
176 | |||
177 | bo = calloc(1, sizeof(*bo)); | ||
178 | if (!bo) { | ||
179 | fprintf(stderr, "failed to allocate bo[%s].\n", | ||
180 | strerror(errno)); | ||
181 | return NULL; | ||
182 | } | ||
183 | |||
184 | if (drmIoctl(dev->fd, DRM_IOCTL_GEM_OPEN, &req)) { | ||
185 | fprintf(stderr, "failed to open gem object[%s].\n", | ||
186 | strerror(errno)); | ||
187 | goto err_free_bo; | ||
188 | } | ||
189 | |||
190 | bo->dev = dev; | ||
191 | bo->name = name; | ||
192 | bo->handle = req.handle; | ||
193 | |||
194 | return bo; | ||
195 | |||
196 | err_free_bo: | ||
197 | free(bo); | ||
198 | return NULL; | ||
199 | } | ||
200 | |||
201 | /* | ||
202 | * Get a gem global object name from a gem object handle. | ||
203 | * | ||
204 | * @bo: a rockchip buffer object including gem handle. | ||
205 | * @name: a gem global object name to be got by kernel driver. | ||
206 | * | ||
207 | * this interface is used to get a gem global object name from a gem object | ||
208 | * handle to a buffer that wants to share it with another process. | ||
209 | * | ||
210 | * if true, return 0 else negative. | ||
211 | */ | ||
212 | int rockchip_bo_get_name(struct rockchip_bo *bo, uint32_t *name) | ||
213 | { | ||
214 | if (!bo->name) { | ||
215 | struct drm_gem_flink req = { | ||
216 | .handle = bo->handle, | ||
217 | }; | ||
218 | int ret; | ||
219 | |||
220 | ret = drmIoctl(bo->dev->fd, DRM_IOCTL_GEM_FLINK, &req); | ||
221 | if (ret) { | ||
222 | fprintf(stderr, "failed to get gem global name[%s].\n", | ||
223 | strerror(errno)); | ||
224 | return ret; | ||
225 | } | ||
226 | |||
227 | bo->name = req.name; | ||
228 | } | ||
229 | |||
230 | *name = bo->name; | ||
231 | |||
232 | return 0; | ||
233 | } | ||
234 | |||
235 | uint32_t rockchip_bo_handle(struct rockchip_bo *bo) | ||
236 | { | ||
237 | return bo->handle; | ||
238 | } | ||
239 | |||
240 | /* | ||
241 | * Mmap a buffer to user space. | ||
242 | * | ||
243 | * @bo: a rockchip buffer object including a gem object handle to be mmapped | ||
244 | * to user space. | ||
245 | * | ||
246 | * if true, user pointer mmaped else NULL. | ||
247 | */ | ||
248 | void *rockchip_bo_map(struct rockchip_bo *bo) | ||
249 | { | ||
250 | if (!bo->vaddr) { | ||
251 | struct rockchip_device *dev = bo->dev; | ||
252 | struct drm_rockchip_gem_map_off req = { | ||
253 | .handle = bo->handle, | ||
254 | }; | ||
255 | int ret; | ||
256 | |||
257 | ret = drmIoctl(dev->fd, DRM_IOCTL_ROCKCHIP_GEM_MAP_OFFSET, &req); | ||
258 | if (ret) { | ||
259 | fprintf(stderr, "failed to ioctl gem map offset[%s].\n", | ||
260 | strerror(errno)); | ||
261 | return NULL; | ||
262 | } | ||
263 | |||
264 | bo->vaddr = mmap(0, bo->size, PROT_READ | PROT_WRITE, | ||
265 | MAP_SHARED, dev->fd, req.offset); | ||
266 | if (bo->vaddr == MAP_FAILED) { | ||
267 | fprintf(stderr, "failed to mmap buffer[%s].\n", | ||
268 | strerror(errno)); | ||
269 | return NULL; | ||
270 | } | ||
271 | } | ||
272 | |||
273 | return bo->vaddr; | ||
274 | } | ||