/* * Copyright (c) 2019 Amlogic, Inc. All rights reserved. * * This source code is subject to the terms and conditions defined in the * file 'LICENSE' which is part of this source code package. * * Description: */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include #include #include #include #include #include #include "meson_drmif.h" #include "meson_drm_log.h" #define LOG_NDEBUG 0 #define LOG_TAG "meson_drm" /* * Create meson drm device object. * @fd: file descriptor to meson drm driver opened. * * if true, returen the device object else NULL. */ struct meson_device *meson_device_create(int fd, int render_fd) { struct meson_device *dev; dev = calloc(sizeof(*dev), 1); if (!dev) { MESON_ALOGE("%s %d failed to create device[%s].\n",__FUNCTION__,__LINE__, strerror(errno)); return NULL; } dev->fd = fd; dev->render_fd = render_fd; return dev; } /* * Destroy meson drm device object * * @dev: meson drm device object. */ void meson_device_destroy(struct meson_device *dev) { free(dev); } /* * Create a meson buffer object to meson drm device. * * @dev: meson drm device object. * @size: buffer size. * @flags: buffer allocation flag. * * user can set one or more flags to allocation specified buffer object * * if true, return a meson buffer object else NULL. */ struct meson_bo *meson_bo_create(struct meson_device *dev, size_t size, uint32_t flags, int alloc_only) { int fd; struct meson_bo *bo; struct drm_meson_gem_create req = { .size = size, .flags = flags, }; if (size == 0) { MESON_ALOGE("%s %d invalid size.\n",__FUNCTION__,__LINE__); goto fail; } bo = calloc(sizeof(*bo), 1); MESON_ALOGD("%s %d meson_bo_create:%p\n",__FUNCTION__,__LINE__,bo); if (!bo) { MESON_ALOGE("%s %d failed to create bo[%s].\n",__FUNCTION__,__LINE__, strerror(errno)); goto err_free_bo; } bo->dev = dev; fd = alloc_only ? dev->render_fd : dev->fd; if (drmIoctl(fd, DRM_IOCTL_MESON_GEM_CREATE, &req)) { MESON_ALOGE("%s %d failed to create gem object[%s].\n",__FUNCTION__,__LINE__, strerror(errno)); goto err_free_bo; } bo->handle = req.handle; bo->size = size; bo->flags = flags; return bo; err_free_bo: free(bo); fail: return NULL; } /* * Destroy a meson buffer object. * @bo: a meson buffer object to be destroyed. */ void meson_bo_destroy(struct meson_bo *bo) { MESON_ALOGD("%s %d meson_bo_destroy:%p\n",__FUNCTION__,__LINE__,bo); if (!bo) return; if (bo->vaddr) munmap(bo->vaddr, bo->size); if (bo->fd) close(bo->fd); if (bo->handle) { struct drm_gem_close req = { .handle = bo->handle, }; drmIoctl(bo->dev->fd, DRM_IOCTL_GEM_CLOSE, &req); } free(bo); } uint32_t meson_bo_handle(struct meson_bo *bo) { return bo->handle; } int meson_bo_dmabuf(struct meson_bo *bo, int alloc_only, int ready_only) { int fd = alloc_only ? bo->dev->render_fd : bo->dev->fd; MESON_ALOGD("%s, bo is %p, alloc_only is %d.\n", __func__, bo, alloc_only); if (!bo->fd) { struct drm_prime_handle req = { .handle = bo->handle, .flags = DRM_CLOEXEC | DRM_RDWR, }; int ret; if (ready_only) req.flags = MESON_RDONLY; else req.flags = DRM_CLOEXEC | DRM_RDWR; ret = drmIoctl(fd, DRM_IOCTL_MESON_PRIME_HANDLE_TO_FD, &req); if (ret) { MESON_ALOGE("%s, FD_TO_HANDLE error return is %d.\n", __func__, ret); return ret; } bo->fd = req.fd; } return bo->fd; } size_t meson_bo_size(struct meson_bo *bo) { return bo->size; } struct meson_bo *meson_bo_import(struct meson_device *dev, int fd, size_t size, uint32_t flags) { int ret; struct meson_bo *bo = NULL; struct drm_prime_handle req = { .fd = fd, }; bo = calloc(sizeof(*bo), 1); if (!bo) { MESON_ALOGE("%s %d failed to create bo[%s].\n",__FUNCTION__,__LINE__, strerror(errno)); goto fail; } ret = drmIoctl(dev->fd, DRM_IOCTL_PRIME_FD_TO_HANDLE, &req); if (ret) goto err_free_bo; bo->dev = dev; bo->size = size; bo->flags = flags; bo->handle = req.handle; return bo; err_free_bo: free(bo); fail: return NULL; }