From e07b650662ea0529d99741691c47856ef1034c9c Mon Sep 17 00:00:00 2001 From: Inki Dae Date: Fri, 4 May 2012 19:13:14 +0900 Subject: libdrm: add exynos drm support this patch adds libdrm_exynos helper layer that inclues some intefaces for exynos specific gem and virtual display driver and also adds exynos module name to modtest and vbltest. Changelog v2: - fixed exynos broken ioctl. the pointer of uint64_t *edid should be removed. - removed unnecessary definitions. - added drm prime interfaces. this feature is used to share a buffer between drivers or memory managers and for this, please, refer to below links: http://www.mjmwired.net/kernel/Documentation/dma-buf-sharing.txt http://lwn.net/Articles/488664/ this patch is based on a link below: git://anongit.freedesktop.org/mesa/drm commit id: d72a44c7c4f5eea9c1e5bb0c36cb9e0224b9ca22 Reviewed-by: Rob Clark Reviewed-by: Alex Deucher Signed-off-by: Inki Dae Signed-off-by: Kyungmin Park Signed-off-by: Rob Clark --- exynos/exynos_drm.c | 396 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 396 insertions(+) create mode 100644 exynos/exynos_drm.c (limited to 'exynos/exynos_drm.c') diff --git a/exynos/exynos_drm.c b/exynos/exynos_drm.c new file mode 100644 index 00000000..4db755e7 --- /dev/null +++ b/exynos/exynos_drm.c @@ -0,0 +1,396 @@ +/* + * Copyright (C) 2012 Samsung Electronics Co., Ltd. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * 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. + * + * Authors: + * Inki Dae + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include + +#include +#include + +#include + +#include "exynos_drm.h" +#include "exynos_drmif.h" + +/* + * Create exynos drm device object. + * + * @fd: file descriptor to exynos drm driver opened. + * + * if true, return the device object else NULL. + */ +struct exynos_device * exynos_device_create(int fd) +{ + struct exynos_device *dev; + + dev = calloc(sizeof(*dev), 1); + if (!dev) { + fprintf(stderr, "failed to create device[%s].\n", + strerror(errno)); + return NULL; + } + + dev->fd = fd; + + return dev; +} + +/* + * Destroy exynos drm device object + * + * @dev: exynos drm device object. + */ +void exynos_device_destroy(struct exynos_device *dev) +{ + free(dev); +} + +/* + * Create a exynos buffer object to exynos drm device. + * + * @dev: exynos drm device object. + * @size: user-desired size. + * flags: user-desired memory type. + * user can set one or more types among several types to memory + * allocation and cache attribute types. and as default, + * EXYNOS_BO_NONCONTIG and EXYNOS-BO_NONCACHABLE types would + * be used. + * + * if true, return a exynos buffer object else NULL. + */ +struct exynos_bo * exynos_bo_create(struct exynos_device *dev, + size_t size, uint32_t flags) +{ + struct exynos_bo *bo; + struct drm_exynos_gem_create req = { + .size = size, + .flags = flags, + }; + + if (size == 0) { + fprintf(stderr, "invalid size.\n"); + goto fail; + } + + bo = calloc(sizeof(*bo), 1); + if (!bo) { + fprintf(stderr, "failed to create bo[%s].\n", + strerror(errno)); + goto err_free_bo; + } + + bo->dev = dev; + + if (drmIoctl(dev->fd, DRM_IOCTL_EXYNOS_GEM_CREATE, &req)){ + fprintf(stderr, "failed to create gem object[%s].\n", + 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; +} + +/* + * Get information to gem region allocated. + * + * @dev: exynos drm device object. + * @handle: gem handle to request gem info. + * @size: size to gem object and returned by kernel side. + * @flags: gem flags to gem object and returned by kernel side. + * + * with this function call, you can get flags and size to gem handle + * through bo object. + * + * if true, return 0 else negative. + */ +int exynos_bo_get_info(struct exynos_device *dev, uint32_t handle, + size_t *size, uint32_t *flags) +{ + int ret; + struct drm_exynos_gem_info req = { + .handle = handle, + }; + + ret = drmIoctl(dev->fd, DRM_IOCTL_EXYNOS_GEM_GET, &req); + if (ret < 0) { + fprintf(stderr, "failed to get gem object information[%s].\n", + strerror(errno)); + return ret; + } + + *size = req.size; + *flags = req.flags; + + return 0; +} + +/* + * Destroy a exynos buffer object. + * + * @bo: a exynos buffer object to be destroyed. + */ +void exynos_bo_destroy(struct exynos_bo *bo) +{ + if (!bo) + return; + + if (bo->vaddr) + munmap(bo->vaddr, bo->size); + + if (bo->handle) { + struct drm_gem_close req = { + .handle = bo->handle, + }; + + drmIoctl(bo->dev->fd, DRM_IOCTL_GEM_CLOSE, &req); + } + + free(bo); +} + + +/* + * Get a exynos buffer object from a gem global object name. + * + * @dev: a exynos device object. + * @name: a gem global object name exported by another process. + * + * this interface is used to get a exynos buffer object from a gem + * global object name sent by another process for buffer sharing. + * + * if true, return a exynos buffer object else NULL. + * + */ +struct exynos_bo * exynos_bo_from_name(struct exynos_device *dev, uint32_t name) +{ + struct exynos_bo *bo; + struct drm_gem_open req = { + .name = name, + }; + + bo = calloc(sizeof(*bo), 1); + if (!bo) { + fprintf(stderr, "failed to allocate bo[%s].\n", + strerror(errno)); + return NULL; + } + + if (drmIoctl(dev->fd, DRM_IOCTL_GEM_OPEN, &req)) { + fprintf(stderr, "failed to open gem object[%s].\n", + strerror(errno)); + goto err_free_bo; + } + + bo->dev = dev; + bo->name = name; + bo->handle = req.handle; + + return bo; + +err_free_bo: + free(bo); + return NULL; +} + +/* + * Get a gem global object name from a gem object handle. + * + * @bo: a exynos buffer object including gem handle. + * @name: a gem global object name to be got by kernel driver. + * + * this interface is used to get a gem global object name from a gem object + * handle to a buffer that wants to share it with another process. + * + * if true, return 0 else negative. + */ +int exynos_bo_get_name(struct exynos_bo *bo, uint32_t *name) +{ + if (!bo->name) { + struct drm_gem_flink req = { + .handle = bo->handle, + }; + int ret; + + ret = drmIoctl(bo->dev->fd, DRM_IOCTL_GEM_FLINK, &req); + if (ret) { + fprintf(stderr, "failed to get gem global name[%s].\n", + strerror(errno)); + return ret; + } + + bo->name = req.name; + } + + *name = bo->name; + + return 0; +} + +uint32_t exynos_bo_handle(struct exynos_bo *bo) +{ + return bo->handle; +} + +/* + * Mmap a buffer to user space. + * + * @bo: a exynos buffer object including a gem object handle to be mmapped + * to user space. + * + * if true, user pointer mmaped else NULL. + */ +void *exynos_bo_map(struct exynos_bo *bo) +{ + if (!bo->vaddr) { + struct exynos_device *dev = bo->dev; + struct drm_exynos_gem_mmap req = { + .handle = bo->handle, + .size = bo->size, + }; + int ret; + + ret = drmIoctl(dev->fd, DRM_IOCTL_EXYNOS_GEM_MMAP, &req); + if (ret) { + fprintf(stderr, "failed to mmap[%s].\n", + strerror(errno)); + return NULL; + } + + bo->vaddr = req.mapped; + } + + return bo->vaddr; +} + +/* + * Export gem object to dmabuf as file descriptor. + * + * @dev: a exynos device object. + * @handle: gem handle to be exported into dmabuf as file descriptor. + * @fd: file descriptor to dmabuf exported from gem handle and + * returned by kernel side. + * + * if true, return 0 else negative. + */ +int exynos_prime_handle_to_fd(struct exynos_device *dev, uint32_t handle, + int *fd) +{ + int ret; + struct drm_prime_handle req = { + .handle = handle, + }; + + ret = drmIoctl(dev->fd, DRM_IOCTL_PRIME_HANDLE_TO_FD, &req); + if (ret) { + fprintf(stderr, "failed to mmap[%s].\n", + strerror(errno)); + return ret; + } + + *fd = req.fd; + return 0; +} + +/* + * Import file descriptor into gem handle. + * + * @dev: a exynos device object. + * @fd: file descriptor exported into dmabuf. + * @handle: gem handle to gem object imported from file descriptor + * and returned by kernel side. + * + * if true, return 0 else negative. + */ +int exynos_prime_fd_to_handle(struct exynos_device *dev, int fd, + uint32_t *handle) +{ + int ret; + struct drm_prime_handle req = { + .fd = fd, + }; + + ret = drmIoctl(dev->fd, DRM_IOCTL_PRIME_FD_TO_HANDLE, &req); + if (ret) { + fprintf(stderr, "failed to mmap[%s].\n", + strerror(errno)); + return ret; + } + + *handle = req.handle; + return 0; +} + + + +/* + * Request Wireless Display connection or disconnection. + * + * @dev: a exynos device object. + * @connect: indicate whether connectoin or disconnection request. + * @ext: indicate whether edid data includes extentions data or not. + * @edid: a pointer to edid data from Wireless Display device. + * + * this interface is used to request Virtual Display driver connection or + * disconnection. for this, user should get a edid data from the Wireless + * Display device and then send that data to kernel driver with connection + * request + * + * if true, return 0 else negative. + */ +int exynos_vidi_connection(struct exynos_device *dev, uint32_t connect, + uint32_t ext, void *edid) +{ + struct drm_exynos_vidi_connection req = { + .connection = connect, + .extensions = ext, + .edid = edid, + }; + int ret; + + ret = drmIoctl(dev->fd, DRM_IOCTL_EXYNOS_VIDI_CONNECTION, &req); + if (ret) { + fprintf(stderr, "failed to request vidi connection[%s].\n", + strerror(errno)); + return ret; + } + + return 0; +} -- cgit v1.2.3