exynos_drm.c revision baaff307
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 41baaff307Smrg#include "libdrm.h" 42e88f27b3Smrg#include "exynos_drm.h" 43e88f27b3Smrg#include "exynos_drmif.h" 44e88f27b3Smrg 45e88f27b3Smrg/* 46e88f27b3Smrg * Create exynos drm device object. 47e88f27b3Smrg * 48e88f27b3Smrg * @fd: file descriptor to exynos drm driver opened. 49e88f27b3Smrg * 50e88f27b3Smrg * if true, return the device object else NULL. 51e88f27b3Smrg */ 52baaff307Smrgdrm_public struct exynos_device * exynos_device_create(int fd) 53e88f27b3Smrg{ 54e88f27b3Smrg struct exynos_device *dev; 55e88f27b3Smrg 56e88f27b3Smrg dev = calloc(sizeof(*dev), 1); 57e88f27b3Smrg if (!dev) { 58e88f27b3Smrg fprintf(stderr, "failed to create device[%s].\n", 59e88f27b3Smrg strerror(errno)); 60e88f27b3Smrg return NULL; 61e88f27b3Smrg } 62e88f27b3Smrg 63e88f27b3Smrg dev->fd = fd; 64e88f27b3Smrg 65e88f27b3Smrg return dev; 66e88f27b3Smrg} 67e88f27b3Smrg 68e88f27b3Smrg/* 69e88f27b3Smrg * Destroy exynos drm device object 70e88f27b3Smrg * 71e88f27b3Smrg * @dev: exynos drm device object. 72e88f27b3Smrg */ 73baaff307Smrgdrm_public void exynos_device_destroy(struct exynos_device *dev) 74e88f27b3Smrg{ 75e88f27b3Smrg free(dev); 76e88f27b3Smrg} 77e88f27b3Smrg 78e88f27b3Smrg/* 79e88f27b3Smrg * Create a exynos buffer object to exynos drm device. 80e88f27b3Smrg * 81e88f27b3Smrg * @dev: exynos drm device object. 82e88f27b3Smrg * @size: user-desired size. 83e88f27b3Smrg * flags: user-desired memory type. 84e88f27b3Smrg * user can set one or more types among several types to memory 85e88f27b3Smrg * allocation and cache attribute types. and as default, 86e88f27b3Smrg * EXYNOS_BO_NONCONTIG and EXYNOS-BO_NONCACHABLE types would 87e88f27b3Smrg * be used. 88e88f27b3Smrg * 89e88f27b3Smrg * if true, return a exynos buffer object else NULL. 90e88f27b3Smrg */ 91baaff307Smrgdrm_public struct exynos_bo * exynos_bo_create(struct exynos_device *dev, 92baaff307Smrg size_t size, uint32_t flags) 93e88f27b3Smrg{ 94e88f27b3Smrg struct exynos_bo *bo; 95e88f27b3Smrg struct drm_exynos_gem_create req = { 96e88f27b3Smrg .size = size, 97e88f27b3Smrg .flags = flags, 98e88f27b3Smrg }; 99e88f27b3Smrg 100e88f27b3Smrg if (size == 0) { 101e88f27b3Smrg fprintf(stderr, "invalid size.\n"); 102e88f27b3Smrg goto fail; 103e88f27b3Smrg } 104e88f27b3Smrg 105e88f27b3Smrg bo = calloc(sizeof(*bo), 1); 106e88f27b3Smrg if (!bo) { 107e88f27b3Smrg fprintf(stderr, "failed to create bo[%s].\n", 108e88f27b3Smrg strerror(errno)); 109e88f27b3Smrg goto err_free_bo; 110e88f27b3Smrg } 111e88f27b3Smrg 112e88f27b3Smrg bo->dev = dev; 113e88f27b3Smrg 114e88f27b3Smrg if (drmIoctl(dev->fd, DRM_IOCTL_EXYNOS_GEM_CREATE, &req)){ 115e88f27b3Smrg fprintf(stderr, "failed to create gem object[%s].\n", 116e88f27b3Smrg strerror(errno)); 117e88f27b3Smrg goto err_free_bo; 118e88f27b3Smrg } 119e88f27b3Smrg 120e88f27b3Smrg bo->handle = req.handle; 121e88f27b3Smrg bo->size = size; 122e88f27b3Smrg bo->flags = flags; 123e88f27b3Smrg 124e88f27b3Smrg return bo; 125e88f27b3Smrg 126e88f27b3Smrgerr_free_bo: 127e88f27b3Smrg free(bo); 128e88f27b3Smrgfail: 129e88f27b3Smrg return NULL; 130e88f27b3Smrg} 131e88f27b3Smrg 132e88f27b3Smrg/* 133e88f27b3Smrg * Get information to gem region allocated. 134e88f27b3Smrg * 135e88f27b3Smrg * @dev: exynos drm device object. 136e88f27b3Smrg * @handle: gem handle to request gem info. 137e88f27b3Smrg * @size: size to gem object and returned by kernel side. 138e88f27b3Smrg * @flags: gem flags to gem object and returned by kernel side. 139e88f27b3Smrg * 140e88f27b3Smrg * with this function call, you can get flags and size to gem handle 141e88f27b3Smrg * through bo object. 142e88f27b3Smrg * 143e88f27b3Smrg * if true, return 0 else negative. 144e88f27b3Smrg */ 145baaff307Smrgdrm_public int exynos_bo_get_info(struct exynos_device *dev, uint32_t handle, 146baaff307Smrg size_t *size, uint32_t *flags) 147e88f27b3Smrg{ 148e88f27b3Smrg int ret; 149e88f27b3Smrg struct drm_exynos_gem_info req = { 150e88f27b3Smrg .handle = handle, 151e88f27b3Smrg }; 152e88f27b3Smrg 153e88f27b3Smrg ret = drmIoctl(dev->fd, DRM_IOCTL_EXYNOS_GEM_GET, &req); 154e88f27b3Smrg if (ret < 0) { 155e88f27b3Smrg fprintf(stderr, "failed to get gem object information[%s].\n", 156e88f27b3Smrg strerror(errno)); 157e88f27b3Smrg return ret; 158e88f27b3Smrg } 159e88f27b3Smrg 160e88f27b3Smrg *size = req.size; 161e88f27b3Smrg *flags = req.flags; 162e88f27b3Smrg 163e88f27b3Smrg return 0; 164e88f27b3Smrg} 165e88f27b3Smrg 166e88f27b3Smrg/* 167e88f27b3Smrg * Destroy a exynos buffer object. 168e88f27b3Smrg * 169e88f27b3Smrg * @bo: a exynos buffer object to be destroyed. 170e88f27b3Smrg */ 171baaff307Smrgdrm_public void exynos_bo_destroy(struct exynos_bo *bo) 172e88f27b3Smrg{ 173e88f27b3Smrg if (!bo) 174e88f27b3Smrg return; 175e88f27b3Smrg 176e88f27b3Smrg if (bo->vaddr) 177e88f27b3Smrg munmap(bo->vaddr, bo->size); 178e88f27b3Smrg 179e88f27b3Smrg if (bo->handle) { 180e88f27b3Smrg struct drm_gem_close req = { 181e88f27b3Smrg .handle = bo->handle, 182e88f27b3Smrg }; 183e88f27b3Smrg 184e88f27b3Smrg drmIoctl(bo->dev->fd, DRM_IOCTL_GEM_CLOSE, &req); 185e88f27b3Smrg } 186e88f27b3Smrg 187e88f27b3Smrg free(bo); 188e88f27b3Smrg} 189e88f27b3Smrg 190e88f27b3Smrg 191e88f27b3Smrg/* 192e88f27b3Smrg * Get a exynos buffer object from a gem global object name. 193e88f27b3Smrg * 194e88f27b3Smrg * @dev: a exynos device object. 195e88f27b3Smrg * @name: a gem global object name exported by another process. 196e88f27b3Smrg * 197e88f27b3Smrg * this interface is used to get a exynos buffer object from a gem 198e88f27b3Smrg * global object name sent by another process for buffer sharing. 199e88f27b3Smrg * 200e88f27b3Smrg * if true, return a exynos buffer object else NULL. 201e88f27b3Smrg * 202e88f27b3Smrg */ 203baaff307Smrgdrm_public struct exynos_bo * 204baaff307Smrgexynos_bo_from_name(struct exynos_device *dev, uint32_t name) 205e88f27b3Smrg{ 206e88f27b3Smrg struct exynos_bo *bo; 207e88f27b3Smrg struct drm_gem_open req = { 208e88f27b3Smrg .name = name, 209e88f27b3Smrg }; 210e88f27b3Smrg 211e88f27b3Smrg bo = calloc(sizeof(*bo), 1); 212e88f27b3Smrg if (!bo) { 213e88f27b3Smrg fprintf(stderr, "failed to allocate bo[%s].\n", 214e88f27b3Smrg strerror(errno)); 215e88f27b3Smrg return NULL; 216e88f27b3Smrg } 217e88f27b3Smrg 218e88f27b3Smrg if (drmIoctl(dev->fd, DRM_IOCTL_GEM_OPEN, &req)) { 219e88f27b3Smrg fprintf(stderr, "failed to open gem object[%s].\n", 220e88f27b3Smrg strerror(errno)); 221e88f27b3Smrg goto err_free_bo; 222e88f27b3Smrg } 223e88f27b3Smrg 224e88f27b3Smrg bo->dev = dev; 225e88f27b3Smrg bo->name = name; 226e88f27b3Smrg bo->handle = req.handle; 227e88f27b3Smrg 228e88f27b3Smrg return bo; 229e88f27b3Smrg 230e88f27b3Smrgerr_free_bo: 231e88f27b3Smrg free(bo); 232e88f27b3Smrg return NULL; 233e88f27b3Smrg} 234e88f27b3Smrg 235e88f27b3Smrg/* 236e88f27b3Smrg * Get a gem global object name from a gem object handle. 237e88f27b3Smrg * 238e88f27b3Smrg * @bo: a exynos buffer object including gem handle. 239e88f27b3Smrg * @name: a gem global object name to be got by kernel driver. 240e88f27b3Smrg * 241e88f27b3Smrg * this interface is used to get a gem global object name from a gem object 242e88f27b3Smrg * handle to a buffer that wants to share it with another process. 243e88f27b3Smrg * 244e88f27b3Smrg * if true, return 0 else negative. 245e88f27b3Smrg */ 246baaff307Smrgdrm_public int exynos_bo_get_name(struct exynos_bo *bo, uint32_t *name) 247e88f27b3Smrg{ 248e88f27b3Smrg if (!bo->name) { 249e88f27b3Smrg struct drm_gem_flink req = { 250e88f27b3Smrg .handle = bo->handle, 251e88f27b3Smrg }; 252e88f27b3Smrg int ret; 253e88f27b3Smrg 254e88f27b3Smrg ret = drmIoctl(bo->dev->fd, DRM_IOCTL_GEM_FLINK, &req); 255e88f27b3Smrg if (ret) { 256e88f27b3Smrg fprintf(stderr, "failed to get gem global name[%s].\n", 257e88f27b3Smrg strerror(errno)); 258e88f27b3Smrg return ret; 259e88f27b3Smrg } 260e88f27b3Smrg 261e88f27b3Smrg bo->name = req.name; 262e88f27b3Smrg } 263e88f27b3Smrg 264e88f27b3Smrg *name = bo->name; 265e88f27b3Smrg 266e88f27b3Smrg return 0; 267e88f27b3Smrg} 268e88f27b3Smrg 269baaff307Smrgdrm_public uint32_t exynos_bo_handle(struct exynos_bo *bo) 270e88f27b3Smrg{ 271e88f27b3Smrg return bo->handle; 272e88f27b3Smrg} 273e88f27b3Smrg 274e88f27b3Smrg/* 275e88f27b3Smrg * Mmap a buffer to user space. 276e88f27b3Smrg * 277e88f27b3Smrg * @bo: a exynos buffer object including a gem object handle to be mmapped 278e88f27b3Smrg * to user space. 279e88f27b3Smrg * 280e88f27b3Smrg * if true, user pointer mmaped else NULL. 281e88f27b3Smrg */ 282baaff307Smrgdrm_public void *exynos_bo_map(struct exynos_bo *bo) 283e88f27b3Smrg{ 284e88f27b3Smrg if (!bo->vaddr) { 285e88f27b3Smrg struct exynos_device *dev = bo->dev; 286e88f27b3Smrg struct drm_exynos_gem_mmap req = { 287e88f27b3Smrg .handle = bo->handle, 288e88f27b3Smrg .size = bo->size, 289e88f27b3Smrg }; 290e88f27b3Smrg int ret; 291e88f27b3Smrg 292e88f27b3Smrg ret = drmIoctl(dev->fd, DRM_IOCTL_EXYNOS_GEM_MMAP, &req); 293e88f27b3Smrg if (ret) { 294e88f27b3Smrg fprintf(stderr, "failed to mmap[%s].\n", 295e88f27b3Smrg strerror(errno)); 296e88f27b3Smrg return NULL; 297e88f27b3Smrg } 298e88f27b3Smrg 299baaff307Smrg bo->vaddr = (void *)(uintptr_t)req.mapped; 300e88f27b3Smrg } 301e88f27b3Smrg 302e88f27b3Smrg return bo->vaddr; 303e88f27b3Smrg} 304e88f27b3Smrg 305e88f27b3Smrg/* 306e88f27b3Smrg * Export gem object to dmabuf as file descriptor. 307e88f27b3Smrg * 308baaff307Smrg * @dev: exynos device object 309baaff307Smrg * @handle: gem handle to export as file descriptor of dmabuf 310baaff307Smrg * @fd: file descriptor returned from kernel 311e88f27b3Smrg * 312baaff307Smrg * @return: 0 on success, -1 on error, and errno will be set 313e88f27b3Smrg */ 314baaff307Smrgdrm_public int 315baaff307Smrgexynos_prime_handle_to_fd(struct exynos_device *dev, uint32_t handle, int *fd) 316e88f27b3Smrg{ 317baaff307Smrg return drmPrimeHandleToFD(dev->fd, handle, 0, fd); 318e88f27b3Smrg} 319e88f27b3Smrg 320e88f27b3Smrg/* 321e88f27b3Smrg * Import file descriptor into gem handle. 322e88f27b3Smrg * 323baaff307Smrg * @dev: exynos device object 324baaff307Smrg * @fd: file descriptor of dmabuf to import 325baaff307Smrg * @handle: gem handle returned from kernel 326e88f27b3Smrg * 327baaff307Smrg * @return: 0 on success, -1 on error, and errno will be set 328e88f27b3Smrg */ 329baaff307Smrgdrm_public int 330baaff307Smrgexynos_prime_fd_to_handle(struct exynos_device *dev, int fd, uint32_t *handle) 331e88f27b3Smrg{ 332baaff307Smrg return drmPrimeFDToHandle(dev->fd, fd, handle); 333e88f27b3Smrg} 334e88f27b3Smrg 335e88f27b3Smrg 336e88f27b3Smrg 337e88f27b3Smrg/* 338e88f27b3Smrg * Request Wireless Display connection or disconnection. 339e88f27b3Smrg * 340e88f27b3Smrg * @dev: a exynos device object. 341e88f27b3Smrg * @connect: indicate whether connectoin or disconnection request. 342e88f27b3Smrg * @ext: indicate whether edid data includes extentions data or not. 343e88f27b3Smrg * @edid: a pointer to edid data from Wireless Display device. 344e88f27b3Smrg * 345e88f27b3Smrg * this interface is used to request Virtual Display driver connection or 346e88f27b3Smrg * disconnection. for this, user should get a edid data from the Wireless 347e88f27b3Smrg * Display device and then send that data to kernel driver with connection 348e88f27b3Smrg * request 349e88f27b3Smrg * 350e88f27b3Smrg * if true, return 0 else negative. 351e88f27b3Smrg */ 352baaff307Smrgdrm_public int 353baaff307Smrgexynos_vidi_connection(struct exynos_device *dev, uint32_t connect, 354baaff307Smrg uint32_t ext, void *edid) 355e88f27b3Smrg{ 356e88f27b3Smrg struct drm_exynos_vidi_connection req = { 357e88f27b3Smrg .connection = connect, 358e88f27b3Smrg .extensions = ext, 359baaff307Smrg .edid = (uint64_t)(uintptr_t)edid, 360e88f27b3Smrg }; 361e88f27b3Smrg int ret; 362e88f27b3Smrg 363e88f27b3Smrg ret = drmIoctl(dev->fd, DRM_IOCTL_EXYNOS_VIDI_CONNECTION, &req); 364e88f27b3Smrg if (ret) { 365e88f27b3Smrg fprintf(stderr, "failed to request vidi connection[%s].\n", 366e88f27b3Smrg strerror(errno)); 367e88f27b3Smrg return ret; 368e88f27b3Smrg } 369e88f27b3Smrg 370e88f27b3Smrg return 0; 371e88f27b3Smrg} 372