Back to index

libdrm  2.4.37
omap_drm.c
Go to the documentation of this file.
00001 /* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
00002 
00003 /*
00004  * Copyright (C) 2011 Texas Instruments, Inc
00005  *
00006  * Permission is hereby granted, free of charge, to any person obtaining a
00007  * copy of this software and associated documentation files (the "Software"),
00008  * to deal in the Software without restriction, including without limitation
00009  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
00010  * and/or sell copies of the Software, and to permit persons to whom the
00011  * Software is furnished to do so, subject to the following conditions:
00012  *
00013  * The above copyright notice and this permission notice (including the next
00014  * paragraph) shall be included in all copies or substantial portions of the
00015  * Software.
00016  *
00017  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00018  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00019  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
00020  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
00021  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
00022  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
00023  * SOFTWARE.
00024  *
00025  * Authors:
00026  *    Rob Clark <rob@ti.com>
00027  */
00028 
00029 #ifdef HAVE_CONFIG_H
00030 #include "config.h"
00031 #endif
00032 
00033 #include <stdlib.h>
00034 #include <linux/stddef.h>
00035 #include <errno.h>
00036 #include <sys/mman.h>
00037 #include <fcntl.h>
00038 
00039 #include <xf86drm.h>
00040 
00041 #include "omap_drm.h"
00042 #include "omap_drmif.h"
00043 
00044 #define __round_mask(x, y) ((__typeof__(x))((y)-1))
00045 #define round_up(x, y) ((((x)-1) | __round_mask(x, y))+1)
00046 #define PAGE_SIZE 4096
00047 
00048 struct omap_device {
00049        int fd;
00050 };
00051 
00052 /* a GEM buffer object allocated from the DRM device */
00053 struct omap_bo {
00054        struct omap_device   *dev;
00055        void          *map;         /* userspace mmap'ing (if there is one) */
00056        uint32_t      size;
00057        uint32_t      handle;
00058        uint32_t      name;         /* flink global handle (DRI2 name) */
00059        uint64_t      offset;              /* offset to mmap() */
00060        int           fd;           /* dmabuf handle */
00061 };
00062 
00063 struct omap_device * omap_device_new(int fd)
00064 {
00065        struct omap_device *dev = calloc(sizeof(*dev), 1);
00066        if (!dev)
00067               return NULL;
00068        dev->fd = fd;
00069        return dev;
00070 }
00071 
00072 void omap_device_del(struct omap_device *dev)
00073 {
00074        free(dev);
00075 }
00076 
00077 int omap_get_param(struct omap_device *dev, uint64_t param, uint64_t *value)
00078 {
00079        struct drm_omap_param req = {
00080                      .param = param,
00081        };
00082        int ret;
00083 
00084        ret = drmCommandWriteRead(dev->fd, DRM_OMAP_GET_PARAM, &req, sizeof(req));
00085        if (ret) {
00086               return ret;
00087        }
00088 
00089        *value = req.value;
00090 
00091        return 0;
00092 }
00093 
00094 int omap_set_param(struct omap_device *dev, uint64_t param, uint64_t value)
00095 {
00096        struct drm_omap_param req = {
00097                      .param = param,
00098                      .value = value,
00099        };
00100        return drmCommandWrite(dev->fd, DRM_OMAP_SET_PARAM, &req, sizeof(req));
00101 }
00102 
00103 /* allocate a new buffer object */
00104 static struct omap_bo * omap_bo_new_impl(struct omap_device *dev,
00105               union omap_gem_size size, uint32_t flags)
00106 {
00107        struct omap_bo *bo = NULL;
00108        struct drm_omap_gem_new req = {
00109                      .size = size,
00110                      .flags = flags,
00111        };
00112 
00113        if (size.bytes == 0) {
00114               goto fail;
00115        }
00116 
00117        bo = calloc(sizeof(*bo), 1);
00118        if (!bo) {
00119               goto fail;
00120        }
00121 
00122        bo->dev = dev;
00123 
00124        if (flags & OMAP_BO_TILED) {
00125               bo->size = round_up(size.tiled.width, PAGE_SIZE) * size.tiled.height;
00126        } else {
00127               bo->size = size.bytes;
00128        }
00129 
00130        if (drmCommandWriteRead(dev->fd, DRM_OMAP_GEM_NEW, &req, sizeof(req))) {
00131               goto fail;
00132        }
00133 
00134        bo->handle = req.handle;
00135 
00136        return bo;
00137 
00138 fail:
00139        free(bo);
00140        return NULL;
00141 }
00142 
00143 
00144 /* allocate a new (un-tiled) buffer object */
00145 struct omap_bo * omap_bo_new(struct omap_device *dev,
00146               uint32_t size, uint32_t flags)
00147 {
00148        union omap_gem_size gsize = {
00149                      .bytes = size,
00150        };
00151        if (flags & OMAP_BO_TILED) {
00152               return NULL;
00153        }
00154        return omap_bo_new_impl(dev, gsize, flags);
00155 }
00156 
00157 /* allocate a new buffer object */
00158 struct omap_bo * omap_bo_new_tiled(struct omap_device *dev,
00159               uint32_t width, uint32_t height, uint32_t flags)
00160 {
00161        union omap_gem_size gsize = {
00162                      .tiled = {
00163                             .width = width,
00164                             .height = height,
00165                      },
00166        };
00167        if (!(flags & OMAP_BO_TILED)) {
00168               return NULL;
00169        }
00170        return omap_bo_new_impl(dev, gsize, flags);
00171 }
00172 
00173 /* get buffer info */
00174 static int get_buffer_info(struct omap_bo *bo)
00175 {
00176        struct drm_omap_gem_info req = {
00177                      .handle = bo->handle,
00178        };
00179        int ret = drmCommandWriteRead(bo->dev->fd, DRM_OMAP_GEM_INFO,
00180                      &req, sizeof(req));
00181        if (ret) {
00182               return ret;
00183        }
00184 
00185        /* really all we need for now is mmap offset */
00186        bo->offset = req.offset;
00187        bo->size = req.size;
00188 
00189        return 0;
00190 }
00191 
00192 /* import a buffer object from DRI2 name */
00193 struct omap_bo * omap_bo_from_name(struct omap_device *dev, uint32_t name)
00194 {
00195        struct omap_bo *bo;
00196        struct drm_gem_open req = {
00197                      .name = name,
00198        };
00199 
00200        bo = calloc(sizeof(*bo), 1);
00201        if (!bo) {
00202               goto fail;
00203        }
00204 
00205        if (drmIoctl(dev->fd, DRM_IOCTL_GEM_OPEN, &req)) {
00206               goto fail;
00207        }
00208 
00209        bo->dev = dev;
00210        bo->name = name;
00211        bo->handle = req.handle;
00212 
00213        return bo;
00214 
00215 fail:
00216        free(bo);
00217        return NULL;
00218 }
00219 
00220 /* destroy a buffer object */
00221 void omap_bo_del(struct omap_bo *bo)
00222 {
00223        if (!bo) {
00224               return;
00225        }
00226 
00227        if (bo->map) {
00228               munmap(bo->map, bo->size);
00229        }
00230 
00231        if (bo->handle) {
00232               struct drm_gem_close req = {
00233                             .handle = bo->handle,
00234               };
00235 
00236               drmIoctl(bo->dev->fd, DRM_IOCTL_GEM_CLOSE, &req);
00237        }
00238 
00239        free(bo);
00240 }
00241 
00242 /* get the global flink/DRI2 buffer name */
00243 int omap_bo_get_name(struct omap_bo *bo, uint32_t *name)
00244 {
00245        if (!bo->name) {
00246               struct drm_gem_flink req = {
00247                             .handle = bo->handle,
00248               };
00249               int ret;
00250 
00251               ret = drmIoctl(bo->dev->fd, DRM_IOCTL_GEM_FLINK, &req);
00252               if (ret) {
00253                      return ret;
00254               }
00255 
00256               bo->name = req.name;
00257        }
00258 
00259        *name = bo->name;
00260 
00261        return 0;
00262 }
00263 
00264 uint32_t omap_bo_handle(struct omap_bo *bo)
00265 {
00266        return bo->handle;
00267 }
00268 
00269 int omap_bo_dmabuf(struct omap_bo *bo)
00270 {
00271        if (!bo->fd) {
00272               struct drm_prime_handle req = {
00273                             .handle = bo->handle,
00274                             .flags = DRM_CLOEXEC,
00275               };
00276               int ret;
00277 
00278               ret = drmIoctl(bo->dev->fd, DRM_IOCTL_PRIME_HANDLE_TO_FD, &req);
00279               if (ret) {
00280                      return ret;
00281               }
00282 
00283               bo->fd = req.fd;
00284        }
00285        return bo->fd;
00286 }
00287 
00288 uint32_t omap_bo_size(struct omap_bo *bo)
00289 {
00290        if (!bo->size) {
00291               get_buffer_info(bo);
00292        }
00293        return bo->size;
00294 }
00295 
00296 void * omap_bo_map(struct omap_bo *bo)
00297 {
00298        if (!bo->map) {
00299               if (!bo->offset) {
00300                      get_buffer_info(bo);
00301               }
00302 
00303               bo->map = mmap(0, bo->size, PROT_READ | PROT_WRITE,
00304                             MAP_SHARED, bo->dev->fd, bo->offset);
00305               if (bo->map == MAP_FAILED) {
00306                      bo->map = NULL;
00307               }
00308        }
00309        return bo->map;
00310 }
00311 
00312 int omap_bo_cpu_prep(struct omap_bo *bo, enum omap_gem_op op)
00313 {
00314        struct drm_omap_gem_cpu_prep req = {
00315                      .handle = bo->handle,
00316                      .op = op,
00317        };
00318        return drmCommandWrite(bo->dev->fd,
00319                      DRM_OMAP_GEM_CPU_PREP, &req, sizeof(req));
00320 }
00321 
00322 int omap_bo_cpu_fini(struct omap_bo *bo, enum omap_gem_op op)
00323 {
00324        struct drm_omap_gem_cpu_fini req = {
00325                      .handle = bo->handle,
00326                      .op = op,
00327                      .nregions = 0,
00328        };
00329        return drmCommandWrite(bo->dev->fd,
00330                      DRM_OMAP_GEM_CPU_FINI, &req, sizeof(req));
00331 }