exynos_drm.c revision baaff307
1/* 2 * Copyright (C) 2012 Samsung Electronics Co., Ltd. 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice (including the next 12 * paragraph) shall be included in all copies or substantial portions of the 13 * Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 * SOFTWARE. 22 * 23 * Authors: 24 * Inki Dae <inki.dae@samsung.com> 25 */ 26 27#ifdef HAVE_CONFIG_H 28#include "config.h" 29#endif 30 31#include <stdlib.h> 32#include <stdio.h> 33#include <string.h> 34#include <errno.h> 35 36#include <sys/mman.h> 37#include <linux/stddef.h> 38 39#include <xf86drm.h> 40 41#include "libdrm.h" 42#include "exynos_drm.h" 43#include "exynos_drmif.h" 44 45/* 46 * Create exynos drm device object. 47 * 48 * @fd: file descriptor to exynos drm driver opened. 49 * 50 * if true, return the device object else NULL. 51 */ 52drm_public struct exynos_device * exynos_device_create(int fd) 53{ 54 struct exynos_device *dev; 55 56 dev = calloc(sizeof(*dev), 1); 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 exynos drm device object 70 * 71 * @dev: exynos drm device object. 72 */ 73drm_public void exynos_device_destroy(struct exynos_device *dev) 74{ 75 free(dev); 76} 77 78/* 79 * Create a exynos buffer object to exynos drm device. 80 * 81 * @dev: exynos 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 * EXYNOS_BO_NONCONTIG and EXYNOS-BO_NONCACHABLE types would 87 * be used. 88 * 89 * if true, return a exynos buffer object else NULL. 90 */ 91drm_public struct exynos_bo * exynos_bo_create(struct exynos_device *dev, 92 size_t size, uint32_t flags) 93{ 94 struct exynos_bo *bo; 95 struct drm_exynos_gem_create req = { 96 .size = size, 97 .flags = flags, 98 }; 99 100 if (size == 0) { 101 fprintf(stderr, "invalid size.\n"); 102 goto fail; 103 } 104 105 bo = calloc(sizeof(*bo), 1); 106 if (!bo) { 107 fprintf(stderr, "failed to create bo[%s].\n", 108 strerror(errno)); 109 goto err_free_bo; 110 } 111 112 bo->dev = dev; 113 114 if (drmIoctl(dev->fd, DRM_IOCTL_EXYNOS_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 126err_free_bo: 127 free(bo); 128fail: 129 return NULL; 130} 131 132/* 133 * Get information to gem region allocated. 134 * 135 * @dev: exynos drm device object. 136 * @handle: gem handle to request gem info. 137 * @size: size to gem object and returned by kernel side. 138 * @flags: gem flags to gem object and returned by kernel side. 139 * 140 * with this function call, you can get flags and size to gem handle 141 * through bo object. 142 * 143 * if true, return 0 else negative. 144 */ 145drm_public int exynos_bo_get_info(struct exynos_device *dev, uint32_t handle, 146 size_t *size, uint32_t *flags) 147{ 148 int ret; 149 struct drm_exynos_gem_info req = { 150 .handle = handle, 151 }; 152 153 ret = drmIoctl(dev->fd, DRM_IOCTL_EXYNOS_GEM_GET, &req); 154 if (ret < 0) { 155 fprintf(stderr, "failed to get gem object information[%s].\n", 156 strerror(errno)); 157 return ret; 158 } 159 160 *size = req.size; 161 *flags = req.flags; 162 163 return 0; 164} 165 166/* 167 * Destroy a exynos buffer object. 168 * 169 * @bo: a exynos buffer object to be destroyed. 170 */ 171drm_public void exynos_bo_destroy(struct exynos_bo *bo) 172{ 173 if (!bo) 174 return; 175 176 if (bo->vaddr) 177 munmap(bo->vaddr, bo->size); 178 179 if (bo->handle) { 180 struct drm_gem_close req = { 181 .handle = bo->handle, 182 }; 183 184 drmIoctl(bo->dev->fd, DRM_IOCTL_GEM_CLOSE, &req); 185 } 186 187 free(bo); 188} 189 190 191/* 192 * Get a exynos buffer object from a gem global object name. 193 * 194 * @dev: a exynos device object. 195 * @name: a gem global object name exported by another process. 196 * 197 * this interface is used to get a exynos buffer object from a gem 198 * global object name sent by another process for buffer sharing. 199 * 200 * if true, return a exynos buffer object else NULL. 201 * 202 */ 203drm_public struct exynos_bo * 204exynos_bo_from_name(struct exynos_device *dev, uint32_t name) 205{ 206 struct exynos_bo *bo; 207 struct drm_gem_open req = { 208 .name = name, 209 }; 210 211 bo = calloc(sizeof(*bo), 1); 212 if (!bo) { 213 fprintf(stderr, "failed to allocate bo[%s].\n", 214 strerror(errno)); 215 return NULL; 216 } 217 218 if (drmIoctl(dev->fd, DRM_IOCTL_GEM_OPEN, &req)) { 219 fprintf(stderr, "failed to open gem object[%s].\n", 220 strerror(errno)); 221 goto err_free_bo; 222 } 223 224 bo->dev = dev; 225 bo->name = name; 226 bo->handle = req.handle; 227 228 return bo; 229 230err_free_bo: 231 free(bo); 232 return NULL; 233} 234 235/* 236 * Get a gem global object name from a gem object handle. 237 * 238 * @bo: a exynos buffer object including gem handle. 239 * @name: a gem global object name to be got by kernel driver. 240 * 241 * this interface is used to get a gem global object name from a gem object 242 * handle to a buffer that wants to share it with another process. 243 * 244 * if true, return 0 else negative. 245 */ 246drm_public int exynos_bo_get_name(struct exynos_bo *bo, uint32_t *name) 247{ 248 if (!bo->name) { 249 struct drm_gem_flink req = { 250 .handle = bo->handle, 251 }; 252 int ret; 253 254 ret = drmIoctl(bo->dev->fd, DRM_IOCTL_GEM_FLINK, &req); 255 if (ret) { 256 fprintf(stderr, "failed to get gem global name[%s].\n", 257 strerror(errno)); 258 return ret; 259 } 260 261 bo->name = req.name; 262 } 263 264 *name = bo->name; 265 266 return 0; 267} 268 269drm_public uint32_t exynos_bo_handle(struct exynos_bo *bo) 270{ 271 return bo->handle; 272} 273 274/* 275 * Mmap a buffer to user space. 276 * 277 * @bo: a exynos buffer object including a gem object handle to be mmapped 278 * to user space. 279 * 280 * if true, user pointer mmaped else NULL. 281 */ 282drm_public void *exynos_bo_map(struct exynos_bo *bo) 283{ 284 if (!bo->vaddr) { 285 struct exynos_device *dev = bo->dev; 286 struct drm_exynos_gem_mmap req = { 287 .handle = bo->handle, 288 .size = bo->size, 289 }; 290 int ret; 291 292 ret = drmIoctl(dev->fd, DRM_IOCTL_EXYNOS_GEM_MMAP, &req); 293 if (ret) { 294 fprintf(stderr, "failed to mmap[%s].\n", 295 strerror(errno)); 296 return NULL; 297 } 298 299 bo->vaddr = (void *)(uintptr_t)req.mapped; 300 } 301 302 return bo->vaddr; 303} 304 305/* 306 * Export gem object to dmabuf as file descriptor. 307 * 308 * @dev: exynos device object 309 * @handle: gem handle to export as file descriptor of dmabuf 310 * @fd: file descriptor returned from kernel 311 * 312 * @return: 0 on success, -1 on error, and errno will be set 313 */ 314drm_public int 315exynos_prime_handle_to_fd(struct exynos_device *dev, uint32_t handle, int *fd) 316{ 317 return drmPrimeHandleToFD(dev->fd, handle, 0, fd); 318} 319 320/* 321 * Import file descriptor into gem handle. 322 * 323 * @dev: exynos device object 324 * @fd: file descriptor of dmabuf to import 325 * @handle: gem handle returned from kernel 326 * 327 * @return: 0 on success, -1 on error, and errno will be set 328 */ 329drm_public int 330exynos_prime_fd_to_handle(struct exynos_device *dev, int fd, uint32_t *handle) 331{ 332 return drmPrimeFDToHandle(dev->fd, fd, handle); 333} 334 335 336 337/* 338 * Request Wireless Display connection or disconnection. 339 * 340 * @dev: a exynos device object. 341 * @connect: indicate whether connectoin or disconnection request. 342 * @ext: indicate whether edid data includes extentions data or not. 343 * @edid: a pointer to edid data from Wireless Display device. 344 * 345 * this interface is used to request Virtual Display driver connection or 346 * disconnection. for this, user should get a edid data from the Wireless 347 * Display device and then send that data to kernel driver with connection 348 * request 349 * 350 * if true, return 0 else negative. 351 */ 352drm_public int 353exynos_vidi_connection(struct exynos_device *dev, uint32_t connect, 354 uint32_t ext, void *edid) 355{ 356 struct drm_exynos_vidi_connection req = { 357 .connection = connect, 358 .extensions = ext, 359 .edid = (uint64_t)(uintptr_t)edid, 360 }; 361 int ret; 362 363 ret = drmIoctl(dev->fd, DRM_IOCTL_EXYNOS_VIDI_CONNECTION, &req); 364 if (ret) { 365 fprintf(stderr, "failed to request vidi connection[%s].\n", 366 strerror(errno)); 367 return ret; 368 } 369 370 return 0; 371} 372