1 /* 2 * Copyright (C) ROCKCHIP, Inc. 3 * Author:yzq<yzq (at) 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 struct rockchip_bo *rockchip_bo_from_handle(struct rockchip_device *dev, 133 uint32_t handle, uint32_t flags, uint32_t size) 134 { 135 struct rockchip_bo *bo; 136 137 if (size == 0) { 138 fprintf(stderr, "invalid size.\n"); 139 return NULL; 140 } 141 142 bo = calloc(1, sizeof(*bo)); 143 if (!bo) { 144 fprintf(stderr, "failed to create bo[%s].\n", 145 strerror(errno)); 146 return NULL; 147 } 148 149 bo->dev = dev; 150 bo->handle = handle; 151 bo->size = size; 152 bo->flags = flags; 153 154 return bo; 155 } 156 157 /* 158 * Destroy a rockchip buffer object. 159 * 160 * @bo: a rockchip buffer object to be destroyed. 161 */ 162 void rockchip_bo_destroy(struct rockchip_bo *bo) 163 { 164 if (!bo) 165 return; 166 167 if (bo->vaddr) 168 munmap(bo->vaddr, bo->size); 169 170 if (bo->handle) { 171 struct drm_gem_close req = { 172 .handle = bo->handle, 173 }; 174 175 drmIoctl(bo->dev->fd, DRM_IOCTL_GEM_CLOSE, &req); 176 } 177 178 free(bo); 179 } 180 181 182 /* 183 * Get a rockchip buffer object from a gem global object name. 184 * 185 * @dev: a rockchip device object. 186 * @name: a gem global object name exported by another process. 187 * 188 * this interface is used to get a rockchip buffer object from a gem 189 * global object name sent by another process for buffer sharing. 190 * 191 * if true, return a rockchip buffer object else NULL. 192 * 193 */ 194 struct rockchip_bo *rockchip_bo_from_name(struct rockchip_device *dev, 195 uint32_t name) 196 { 197 struct rockchip_bo *bo; 198 struct drm_gem_open req = { 199 .name = name, 200 }; 201 202 bo = calloc(1, sizeof(*bo)); 203 if (!bo) { 204 fprintf(stderr, "failed to allocate bo[%s].\n", 205 strerror(errno)); 206 return NULL; 207 } 208 209 if (drmIoctl(dev->fd, DRM_IOCTL_GEM_OPEN, &req)) { 210 fprintf(stderr, "failed to open gem object[%s].\n", 211 strerror(errno)); 212 goto err_free_bo; 213 } 214 215 bo->dev = dev; 216 bo->name = name; 217 bo->handle = req.handle; 218 219 return bo; 220 221 err_free_bo: 222 free(bo); 223 return NULL; 224 } 225 226 /* 227 * Get a gem global object name from a gem object handle. 228 * 229 * @bo: a rockchip buffer object including gem handle. 230 * @name: a gem global object name to be got by kernel driver. 231 * 232 * this interface is used to get a gem global object name from a gem object 233 * handle to a buffer that wants to share it with another process. 234 * 235 * if true, return 0 else negative. 236 */ 237 int rockchip_bo_get_name(struct rockchip_bo *bo, uint32_t *name) 238 { 239 if (!bo->name) { 240 struct drm_gem_flink req = { 241 .handle = bo->handle, 242 }; 243 int ret; 244 245 ret = drmIoctl(bo->dev->fd, DRM_IOCTL_GEM_FLINK, &req); 246 if (ret) { 247 fprintf(stderr, "failed to get gem global name[%s].\n", 248 strerror(errno)); 249 return ret; 250 } 251 252 bo->name = req.name; 253 } 254 255 *name = bo->name; 256 257 return 0; 258 } 259 260 uint32_t rockchip_bo_handle(struct rockchip_bo *bo) 261 { 262 return bo->handle; 263 } 264 265 /* 266 * Mmap a buffer to user space. 267 * 268 * @bo: a rockchip buffer object including a gem object handle to be mmapped 269 * to user space. 270 * 271 * if true, user pointer mmaped else NULL. 272 */ 273 void *rockchip_bo_map(struct rockchip_bo *bo) 274 { 275 if (!bo->vaddr) { 276 struct rockchip_device *dev = bo->dev; 277 struct drm_rockchip_gem_map_off req = { 278 .handle = bo->handle, 279 }; 280 int ret; 281 282 ret = drmIoctl(dev->fd, DRM_IOCTL_ROCKCHIP_GEM_MAP_OFFSET, &req); 283 if (ret) { 284 fprintf(stderr, "failed to ioctl gem map offset[%s].\n", 285 strerror(errno)); 286 return NULL; 287 } 288 289 bo->vaddr = mmap(0, bo->size, PROT_READ | PROT_WRITE, 290 MAP_SHARED, dev->fd, req.offset); 291 if (bo->vaddr == MAP_FAILED) { 292 fprintf(stderr, "failed to mmap buffer[%s].\n", 293 strerror(errno)); 294 return NULL; 295 } 296 } 297 298 return bo->vaddr; 299 } 300