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