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