Back to index

libdrm  2.4.37
exynos_drm.c
Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2012 Samsung Electronics Co., Ltd.
00003  *
00004  * Permission is hereby granted, free of charge, to any person obtaining a
00005  * copy of this software and associated documentation files (the "Software"),
00006  * to deal in the Software without restriction, including without limitation
00007  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
00008  * and/or sell copies of the Software, and to permit persons to whom the
00009  * Software is furnished to do so, subject to the following conditions:
00010  *
00011  * The above copyright notice and this permission notice (including the next
00012  * paragraph) shall be included in all copies or substantial portions of the
00013  * Software.
00014  *
00015  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00016  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00017  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
00018  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
00019  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
00020  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
00021  * SOFTWARE.
00022  *
00023  * Authors:
00024  *    Inki Dae <inki.dae@samsung.com>
00025  */
00026 
00027 #ifdef HAVE_CONFIG_H
00028 #include "config.h"
00029 #endif
00030 
00031 #include <stdlib.h>
00032 #include <stdio.h>
00033 #include <string.h>
00034 #include <errno.h>
00035 
00036 #include <sys/mman.h>
00037 #include <linux/stddef.h>
00038 
00039 #include <xf86drm.h>
00040 
00041 #include "exynos_drm.h"
00042 #include "exynos_drmif.h"
00043 
00044 /*
00045  * Create exynos drm device object.
00046  *
00047  * @fd: file descriptor to exynos drm driver opened.
00048  *
00049  * if true, return the device object else NULL.
00050  */
00051 struct exynos_device * exynos_device_create(int fd)
00052 {
00053        struct exynos_device *dev;
00054 
00055        dev = calloc(sizeof(*dev), 1);
00056        if (!dev) {
00057               fprintf(stderr, "failed to create device[%s].\n",
00058                             strerror(errno));
00059               return NULL;
00060        }
00061 
00062        dev->fd = fd;
00063 
00064        return dev;
00065 }
00066 
00067 /*
00068  * Destroy exynos drm device object
00069  *
00070  * @dev: exynos drm device object.
00071  */
00072 void exynos_device_destroy(struct exynos_device *dev)
00073 {
00074        free(dev);
00075 }
00076 
00077 /*
00078  * Create a exynos buffer object to exynos drm device.
00079  *
00080  * @dev: exynos drm device object.
00081  * @size: user-desired size.
00082  * flags: user-desired memory type.
00083  *     user can set one or more types among several types to memory
00084  *     allocation and cache attribute types. and as default,
00085  *     EXYNOS_BO_NONCONTIG and EXYNOS-BO_NONCACHABLE types would
00086  *     be used.
00087  *
00088  * if true, return a exynos buffer object else NULL.
00089  */
00090 struct exynos_bo * exynos_bo_create(struct exynos_device *dev,
00091                                           size_t size, uint32_t flags)
00092 {
00093        struct exynos_bo *bo;
00094        struct drm_exynos_gem_create req = {
00095               .size = size,
00096               .flags = flags,
00097        };
00098 
00099        if (size == 0) {
00100               fprintf(stderr, "invalid size.\n");
00101               goto fail;
00102        }
00103 
00104        bo = calloc(sizeof(*bo), 1);
00105        if (!bo) {
00106               fprintf(stderr, "failed to create bo[%s].\n",
00107                             strerror(errno));
00108               goto err_free_bo;
00109        }
00110 
00111        bo->dev = dev;
00112 
00113        if (drmIoctl(dev->fd, DRM_IOCTL_EXYNOS_GEM_CREATE, &req)){
00114               fprintf(stderr, "failed to create gem object[%s].\n",
00115                             strerror(errno));
00116               goto err_free_bo;
00117        }
00118 
00119        bo->handle = req.handle;
00120        bo->size = size;
00121        bo->flags = flags;
00122 
00123        return bo;
00124 
00125 err_free_bo:
00126        free(bo);
00127 fail:
00128        return NULL;
00129 }
00130 
00131 /*
00132  * Get information to gem region allocated.
00133  *
00134  * @dev: exynos drm device object.
00135  * @handle: gem handle to request gem info.
00136  * @size: size to gem object and returned by kernel side.
00137  * @flags: gem flags to gem object and returned by kernel side.
00138  *
00139  * with this function call, you can get flags and size to gem handle
00140  * through bo object.
00141  *
00142  * if true, return 0 else negative.
00143  */
00144 int exynos_bo_get_info(struct exynos_device *dev, uint32_t handle,
00145                      size_t *size, uint32_t *flags)
00146 {
00147        int ret;
00148        struct drm_exynos_gem_info req = {
00149               .handle = handle,
00150        };
00151 
00152        ret = drmIoctl(dev->fd, DRM_IOCTL_EXYNOS_GEM_GET, &req);
00153        if (ret < 0) {
00154               fprintf(stderr, "failed to get gem object information[%s].\n",
00155                             strerror(errno));
00156               return ret;
00157        }
00158 
00159        *size = req.size;
00160        *flags = req.flags;
00161 
00162        return 0;
00163 }
00164 
00165 /*
00166  * Destroy a exynos buffer object.
00167  *
00168  * @bo: a exynos buffer object to be destroyed.
00169  */
00170 void exynos_bo_destroy(struct exynos_bo *bo)
00171 {
00172        if (!bo)
00173               return;
00174 
00175        if (bo->vaddr)
00176               munmap(bo->vaddr, bo->size);
00177 
00178        if (bo->handle) {
00179               struct drm_gem_close req = {
00180                      .handle = bo->handle,
00181               };
00182 
00183               drmIoctl(bo->dev->fd, DRM_IOCTL_GEM_CLOSE, &req);
00184        }
00185 
00186        free(bo);
00187 }
00188 
00189 
00190 /*
00191  * Get a exynos buffer object from a gem global object name.
00192  *
00193  * @dev: a exynos device object.
00194  * @name: a gem global object name exported by another process.
00195  *
00196  * this interface is used to get a exynos buffer object from a gem
00197  * global object name sent by another process for buffer sharing.
00198  *
00199  * if true, return a exynos buffer object else NULL.
00200  *
00201  */
00202 struct exynos_bo * exynos_bo_from_name(struct exynos_device *dev, uint32_t name)
00203 {
00204        struct exynos_bo *bo;
00205        struct drm_gem_open req = {
00206               .name = name,
00207        };
00208 
00209        bo = calloc(sizeof(*bo), 1);
00210        if (!bo) {
00211               fprintf(stderr, "failed to allocate bo[%s].\n",
00212                             strerror(errno));
00213               return NULL;
00214        }
00215 
00216        if (drmIoctl(dev->fd, DRM_IOCTL_GEM_OPEN, &req)) {
00217               fprintf(stderr, "failed to open gem object[%s].\n",
00218                             strerror(errno));
00219               goto err_free_bo;
00220        }
00221 
00222        bo->dev = dev;
00223        bo->name = name;
00224        bo->handle = req.handle;
00225 
00226        return bo;
00227 
00228 err_free_bo:
00229        free(bo);
00230        return NULL;
00231 }
00232 
00233 /*
00234  * Get a gem global object name from a gem object handle.
00235  *
00236  * @bo: a exynos buffer object including gem handle.
00237  * @name: a gem global object name to be got by kernel driver.
00238  *
00239  * this interface is used to get a gem global object name from a gem object
00240  * handle to a buffer that wants to share it with another process.
00241  *
00242  * if true, return 0 else negative.
00243  */
00244 int exynos_bo_get_name(struct exynos_bo *bo, uint32_t *name)
00245 {
00246        if (!bo->name) {
00247               struct drm_gem_flink req = {
00248                      .handle = bo->handle,
00249               };
00250               int ret;
00251 
00252               ret = drmIoctl(bo->dev->fd, DRM_IOCTL_GEM_FLINK, &req);
00253               if (ret) {
00254                      fprintf(stderr, "failed to get gem global name[%s].\n",
00255                                    strerror(errno));
00256                      return ret;
00257               }
00258 
00259               bo->name = req.name;
00260        }
00261 
00262        *name = bo->name;
00263 
00264        return 0;
00265 }
00266 
00267 uint32_t exynos_bo_handle(struct exynos_bo *bo)
00268 {
00269        return bo->handle;
00270 }
00271 
00272 /*
00273  * Mmap a buffer to user space.
00274  *
00275  * @bo: a exynos buffer object including a gem object handle to be mmapped
00276  *     to user space.
00277  *
00278  * if true, user pointer mmaped else NULL.
00279  */
00280 void *exynos_bo_map(struct exynos_bo *bo)
00281 {
00282        if (!bo->vaddr) {
00283               struct exynos_device *dev = bo->dev;
00284               struct drm_exynos_gem_mmap req = {
00285                      .handle = bo->handle,
00286                      .size  = bo->size,
00287               };
00288               int ret;
00289 
00290               ret = drmIoctl(dev->fd, DRM_IOCTL_EXYNOS_GEM_MMAP, &req);
00291               if (ret) {
00292                      fprintf(stderr, "failed to mmap[%s].\n",
00293                             strerror(errno));
00294                      return NULL;
00295               }
00296 
00297               bo->vaddr = req.mapped;
00298        }
00299 
00300        return bo->vaddr;
00301 }
00302 
00303 /*
00304  * Export gem object to dmabuf as file descriptor.
00305  *
00306  * @dev: a exynos device object.
00307  * @handle: gem handle to be exported into dmabuf as file descriptor.
00308  * @fd: file descriptor to dmabuf exported from gem handle and
00309  *     returned by kernel side.
00310  *
00311  * if true, return 0 else negative.
00312  */
00313 int exynos_prime_handle_to_fd(struct exynos_device *dev, uint32_t handle,
00314                                    int *fd)
00315 {
00316        int ret;
00317        struct drm_prime_handle req = {
00318               .handle       = handle,
00319        };
00320 
00321        ret = drmIoctl(dev->fd, DRM_IOCTL_PRIME_HANDLE_TO_FD, &req);
00322        if (ret) {
00323               fprintf(stderr, "failed to mmap[%s].\n",
00324                      strerror(errno));
00325               return ret;
00326        }
00327 
00328        *fd = req.fd;
00329        return 0;
00330 }
00331 
00332 /*
00333  * Import file descriptor into gem handle.
00334  *
00335  * @dev: a exynos device object.
00336  * @fd: file descriptor exported into dmabuf.
00337  * @handle: gem handle to gem object imported from file descriptor
00338  *     and returned by kernel side.
00339  *
00340  * if true, return 0 else negative.
00341  */
00342 int exynos_prime_fd_to_handle(struct exynos_device *dev, int fd,
00343                                    uint32_t *handle)
00344 {
00345        int ret;
00346        struct drm_prime_handle req = {
00347               .fd    = fd,
00348        };
00349 
00350        ret = drmIoctl(dev->fd, DRM_IOCTL_PRIME_FD_TO_HANDLE, &req);
00351        if (ret) {
00352               fprintf(stderr, "failed to mmap[%s].\n",
00353                      strerror(errno));
00354               return ret;
00355        }
00356 
00357        *handle = req.handle;
00358        return 0;
00359 }
00360 
00361 
00362 
00363 /*
00364  * Request Wireless Display connection or disconnection.
00365  *
00366  * @dev: a exynos device object.
00367  * @connect: indicate whether connectoin or disconnection request.
00368  * @ext: indicate whether edid data includes extentions data or not.
00369  * @edid: a pointer to edid data from Wireless Display device.
00370  *
00371  * this interface is used to request Virtual Display driver connection or
00372  * disconnection. for this, user should get a edid data from the Wireless
00373  * Display device and then send that data to kernel driver with connection
00374  * request
00375  *
00376  * if true, return 0 else negative.
00377  */
00378 int exynos_vidi_connection(struct exynos_device *dev, uint32_t connect,
00379                             uint32_t ext, void *edid)
00380 {
00381        struct drm_exynos_vidi_connection req = {
00382               .connection   = connect,
00383               .extensions   = ext,
00384               .edid         = edid,
00385        };
00386        int ret;
00387 
00388        ret = drmIoctl(dev->fd, DRM_IOCTL_EXYNOS_VIDI_CONNECTION, &req);
00389        if (ret) {
00390               fprintf(stderr, "failed to request vidi connection[%s].\n",
00391                             strerror(errno));
00392               return ret;
00393        }
00394 
00395        return 0;
00396 }