/* * Copyright (C) 2019 Rockchip Electronics Co., Ltd. * * This software is available to you under a choice of one of two * licenses. You may choose to be licensed under the terms of the GNU * General Public License (GPL), available from the file * COPYING in the main directory of this source tree, or the * OpenIB.org BSD license below: * * Redistribution and use in source and binary forms, with or * without modification, are permitted provided that the following * conditions are met: * * - Redistributions of source code must retain the above * copyright notice, this list of conditions and the following * disclaimer. * * - Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials * provided with the distribution. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ #include #include #include #include #include #include #include #include #include #include "drm.h" #include "uvc_log.h" #define DRM_DEVICE "/dev/dri/card0" int drm_open(void) { int fd; fd = open(DRM_DEVICE, O_RDWR); if (fd < 0) { LOG_ERROR("open %s failed!\n", DRM_DEVICE); return -1; } return fd; } void drm_close(int fd) { if (fd >= 0) close(fd); } static int drm_ioctl(int fd, int req, void *arg) { int ret; do { ret = ioctl(fd, req, arg); } while (ret == -1 && (errno == EINTR || errno == EAGAIN)); return ret; } int drm_alloc(int fd, size_t len, size_t align, unsigned int *handle, unsigned int flags) { int ret; struct drm_mode_create_dumb dmcb; memset(&dmcb, 0, sizeof(struct drm_mode_create_dumb)); dmcb.bpp = 8; dmcb.width = (len + align - 1) & (~(align - 1)); dmcb.height = 1; dmcb.flags = flags; if (handle == NULL) return -EINVAL; ret = drm_ioctl(fd, DRM_IOCTL_MODE_CREATE_DUMB, &dmcb); if (ret < 0) return ret; *handle = dmcb.handle; return ret; } int drm_free(int fd, unsigned int handle) { struct drm_mode_destroy_dumb data = { .handle = handle, }; return drm_ioctl(fd, DRM_IOCTL_MODE_DESTROY_DUMB, &data); } void *drm_map_buffer(int fd, unsigned int handle, size_t len) { struct drm_mode_map_dumb dmmd; void *buf = NULL; int ret; memset(&dmmd, 0, sizeof(dmmd)); dmmd.handle = handle; ret = drm_ioctl(fd, DRM_IOCTL_MODE_MAP_DUMB, &dmmd); if (ret) { LOG_ERROR("map_dumb failed: %s\n", strerror(ret)); return NULL; } buf = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, dmmd.offset); if (buf == MAP_FAILED) { LOG_ERROR("mmap failed: %s\n", strerror(errno)); return NULL; } return buf; } void drm_unmap_buffer(void *buf, size_t len) { if (buf) munmap(buf, len); } int drm_handle_to_fd(int fd, unsigned int handle, int *map_fd, unsigned int flags) { int ret; struct drm_prime_handle dph; memset(&dph, 0, sizeof(struct drm_prime_handle)); dph.handle = handle; dph.fd = -1; dph.flags = flags; if (map_fd == NULL) return -EINVAL; ret = drm_ioctl(fd, DRM_IOCTL_PRIME_HANDLE_TO_FD, &dph); if (ret < 0) return ret; *map_fd = dph.fd; if (*map_fd < 0) { LOG_ERROR("map ioctl returned negative fd\n"); return -EINVAL; } return ret; } int drm_get_info_from_name( int fd, unsigned int name, unsigned int *handle, int *size) { int ret = 0; struct drm_gem_open req; req.name = name; ret = drm_ioctl(fd, DRM_IOCTL_GEM_OPEN, &req); if (ret < 0) { return ret; } *handle = req.handle; *size = (int)req.size; return ret; }