From: Thierry Reding <treding@xxxxxxxxxx> These functions can be used to open channels to engines, manage job submissions, create push buffers to store command streams in and wait until jobs have been completed. Signed-off-by: Thierry Reding <treding@xxxxxxxxxx> --- Changes in v2: - automatically allocate buffer objects as required by pushbuffers - pushbuffers can now have more than one associated buffer object - add drm_tegra_pushbuf_prepare() function tegra/Makefile.am | 4 ++ tegra/channel.c | 127 +++++++++++++++++++++++++++++++++ tegra/fence.c | 71 +++++++++++++++++++ tegra/job.c | 180 +++++++++++++++++++++++++++++++++++++++++++++++ tegra/private.h | 72 +++++++++++++++++++ tegra/pushbuf.c | 205 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ tegra/tegra.c | 2 + tegra/tegra.h | 52 ++++++++++++++ 8 files changed, 713 insertions(+) create mode 100644 tegra/channel.c create mode 100644 tegra/fence.c create mode 100644 tegra/job.c create mode 100644 tegra/pushbuf.c diff --git a/tegra/Makefile.am b/tegra/Makefile.am index 1b83145b120d..c73587e8661e 100644 --- a/tegra/Makefile.am +++ b/tegra/Makefile.am @@ -11,6 +11,10 @@ libdrm_tegra_la_LDFLAGS = -version-number 0:0:0 -no-undefined libdrm_tegra_la_LIBADD = ../libdrm.la @PTHREADSTUBS_LIBS@ libdrm_tegra_la_SOURCES = \ + channel.c \ + fence.c \ + job.c \ + pushbuf.c \ tegra.c libdrm_tegraincludedir = ${includedir}/libdrm diff --git a/tegra/channel.c b/tegra/channel.c new file mode 100644 index 000000000000..3ab1d578f8e5 --- /dev/null +++ b/tegra/channel.c @@ -0,0 +1,127 @@ +/* + * Copyright © 2012, 2013 Thierry Reding + * Copyright © 2013 Erik Faye-Lund + * Copyright © 2014 NVIDIA Corporation + * + * 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 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) 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. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include <errno.h> +#include <string.h> + +#include "private.h" + +static int drm_tegra_channel_setup(struct drm_tegra_channel *channel) +{ + struct drm_tegra *drm = channel->drm; + struct drm_tegra_get_syncpt args; + int err; + + memset(&args, 0, sizeof(args)); + args.context = channel->context; + args.index = 0; + + err = ioctl(drm->fd, DRM_IOCTL_TEGRA_GET_SYNCPT, &args); + if (err < 0) + return -errno; + + channel->syncpt = args.id; + + return 0; +} + +drm_public +int drm_tegra_channel_open(struct drm_tegra_channel **channelp, + struct drm_tegra *drm, + enum drm_tegra_class client) +{ + struct drm_tegra_open_channel args; + struct drm_tegra_channel *channel; + enum host1x_class class; + int err; + + switch (client) { + case DRM_TEGRA_GR2D: + class = HOST1X_CLASS_GR2D; + break; + + case DRM_TEGRA_GR3D: + class = HOST1X_CLASS_GR3D; + break; + + default: + return -EINVAL; + } + + channel = calloc(1, sizeof(*channel)); + if (!channel) + return -ENOMEM; + + channel->drm = drm; + + memset(&args, 0, sizeof(args)); + args.client = class; + + err = ioctl(drm->fd, DRM_IOCTL_TEGRA_OPEN_CHANNEL, &args); + if (err < 0) { + free(channel); + return -errno; + } + + channel->context = args.context; + channel->class = class; + + err = drm_tegra_channel_setup(channel); + if (err < 0) { + free(channel); + return err; + } + + *channelp = channel; + + return 0; +} + +drm_public +int drm_tegra_channel_close(struct drm_tegra_channel *channel) +{ + struct drm_tegra_close_channel args; + struct drm_tegra *drm; + int err; + + if (!channel) + return -EINVAL; + + drm = channel->drm; + + memset(&args, 0, sizeof(args)); + args.context = channel->context; + + err = ioctl(drm->fd, DRM_IOCTL_TEGRA_CLOSE_CHANNEL, &args); + if (err < 0) + return -errno; + + free(channel); + + return 0; +} diff --git a/tegra/fence.c b/tegra/fence.c new file mode 100644 index 000000000000..f58725ca8472 --- /dev/null +++ b/tegra/fence.c @@ -0,0 +1,71 @@ +/* + * Copyright © 2012, 2013 Thierry Reding + * Copyright © 2013 Erik Faye-Lund + * Copyright © 2014 NVIDIA Corporation + * + * 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 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) 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. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include <errno.h> +#include <string.h> + +#include "private.h" + +drm_public +int drm_tegra_fence_wait_timeout(struct drm_tegra_fence *fence, + unsigned long timeout) +{ + struct drm_tegra_syncpt_wait args; + int err; + + memset(&args, 0, sizeof(args)); + args.id = fence->syncpt; + args.thresh = fence->value; + args.timeout = timeout; + + while (true) { + err = ioctl(fence->drm->fd, DRM_IOCTL_TEGRA_SYNCPT_WAIT, &args); + if (err < 0) { + if (errno == EINTR) + continue; + + return -errno; + } + + break; + } + + return 0; +} + +drm_public +int drm_tegra_fence_wait(struct drm_tegra_fence *fence) +{ + return drm_tegra_fence_wait_timeout(fence, -1); +} + +drm_public +void drm_tegra_fence_free(struct drm_tegra_fence *fence) +{ + free(fence); +} diff --git a/tegra/job.c b/tegra/job.c new file mode 100644 index 000000000000..8df643c9a9bb --- /dev/null +++ b/tegra/job.c @@ -0,0 +1,180 @@ +/* + * Copyright © 2012, 2013 Thierry Reding + * Copyright © 2013 Erik Faye-Lund + * Copyright © 2014 NVIDIA Corporation + * + * 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 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) 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. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include <errno.h> +#include <stdlib.h> +#include <string.h> + +#include "private.h" + +int drm_tegra_job_add_reloc(struct drm_tegra_job *job, + const struct drm_tegra_reloc *reloc) +{ + struct drm_tegra_reloc *relocs; + size_t size; + + size = (job->num_relocs + 1) * sizeof(*reloc); + + relocs = realloc(job->relocs, size); + if (!reloc) + return -ENOMEM; + + job->relocs = relocs; + + job->relocs[job->num_relocs++] = *reloc; + + return 0; +} + +int drm_tegra_job_add_cmdbuf(struct drm_tegra_job *job, + const struct drm_tegra_cmdbuf *cmdbuf) +{ + struct drm_tegra_cmdbuf *cmdbufs; + size_t size; + + size = (job->num_cmdbufs + 1) * sizeof(*cmdbuf); + + cmdbufs = realloc(job->cmdbufs, size); + if (!cmdbufs) + return -ENOMEM; + + cmdbufs[job->num_cmdbufs++] = *cmdbuf; + job->cmdbufs = cmdbufs; + + return 0; +} + +drm_public +int drm_tegra_job_new(struct drm_tegra_job **jobp, + struct drm_tegra_channel *channel) +{ + struct drm_tegra_job *job; + + job = calloc(1, sizeof(*job)); + if (!job) + return -ENOMEM; + + DRMINITLISTHEAD(&job->pushbufs); + job->channel = channel; + + *jobp = job; + + return 0; +} + +drm_public +int drm_tegra_job_free(struct drm_tegra_job *job) +{ + struct drm_tegra_pushbuf_private *pushbuf; + + if (!job) + return -EINVAL; + + DRMLISTFOREACHENTRY(pushbuf, &job->pushbufs, list) + drm_tegra_pushbuf_free(&pushbuf->base); + + free(job->cmdbufs); + free(job->relocs); + free(job); + + return 0; +} + +drm_public +int drm_tegra_job_submit(struct drm_tegra_job *job, + struct drm_tegra_fence **fencep) +{ + struct drm_tegra *drm = job->channel->drm; + struct drm_tegra_pushbuf_private *pushbuf; + struct drm_tegra_fence *fence = NULL; + struct drm_tegra_cmdbuf *cmdbufs; + struct drm_tegra_syncpt *syncpts; + struct drm_tegra_submit args; + unsigned int i; + int err; + + /* + * Make sure the current command stream buffer is queued for + * submission. + */ + err = drm_tegra_pushbuf_queue(job->pushbuf); + if (err < 0) + return err; + + job->pushbuf = NULL; + + if (fencep) { + fence = calloc(1, sizeof(*fence)); + if (!fence) + return -ENOMEM; + } + + syncpts = calloc(1, sizeof(*syncpts)); + if (!syncpts) { + free(cmdbufs); + free(fence); + return -ENOMEM; + } + + syncpts[0].id = job->syncpt; + syncpts[0].incrs = job->increments; + + memset(&args, 0, sizeof(args)); + args.context = job->channel->context; + args.num_syncpts = 1; + args.num_cmdbufs = job->num_cmdbufs; + args.num_relocs = job->num_relocs; + args.num_waitchks = 0; + args.waitchk_mask = 0; + args.timeout = 1000; + + args.syncpts = (uintptr_t)syncpts; + args.cmdbufs = (uintptr_t)job->cmdbufs; + args.relocs = (uintptr_t)job->relocs; + args.waitchks = 0; + + err = ioctl(drm->fd, DRM_IOCTL_TEGRA_SUBMIT, &args); + if (err < 0) { + free(syncpts); + free(cmdbufs); + free(fence); + return -errno; + } + + if (fence) { + fence->syncpt = job->syncpt; + fence->value = args.fence; + fence->drm = drm; + *fencep = fence; + } + + free(syncpts); + free(cmdbufs); + + return 0; +} diff --git a/tegra/private.h b/tegra/private.h index 9b6bc9395d23..fc74fb56b58d 100644 --- a/tegra/private.h +++ b/tegra/private.h @@ -26,13 +26,31 @@ #define __DRM_TEGRA_PRIVATE_H__ 1 #include <stdbool.h> +#include <stddef.h> #include <stdint.h> #include <libdrm.h> +#include <libdrm_lists.h> #include <xf86atomic.h> +#include "tegra_drm.h" #include "tegra.h" +#define container_of(ptr, type, member) ({ \ + const typeof(((type *)0)->member) *__mptr = (ptr); \ + (type *)((char *)__mptr - offsetof(type, member)); \ + }) + +#define align(offset, align) \ + (((offset) + (align) - 1) & ~((align) - 1)) + +enum host1x_class { + HOST1X_CLASS_HOST1X = 0x01, + HOST1X_CLASS_GR2D = 0x51, + HOST1X_CLASS_GR2D_SB = 0x52, + HOST1X_CLASS_GR3D = 0x60, +}; + struct drm_tegra { bool close; int fd; @@ -40,6 +58,7 @@ struct drm_tegra { struct drm_tegra_bo { struct drm_tegra *drm; + drmMMListHead list; uint32_t handle; uint32_t offset; uint32_t flags; @@ -48,4 +67,57 @@ struct drm_tegra_bo { void *map; }; +struct drm_tegra_channel { + struct drm_tegra *drm; + enum host1x_class class; + uint64_t context; + uint32_t syncpt; +}; + +struct drm_tegra_fence { + struct drm_tegra *drm; + uint32_t syncpt; + uint32_t value; +}; + +struct drm_tegra_pushbuf_private { + struct drm_tegra_pushbuf base; + struct drm_tegra_job *job; + drmMMListHead list; + drmMMListHead bos; + + struct drm_tegra_bo *bo; + uint32_t *start; + uint32_t *end; +}; + +static inline struct drm_tegra_pushbuf_private * +pushbuf_priv(struct drm_tegra_pushbuf *pb) +{ + return container_of(pb, struct drm_tegra_pushbuf_private, base); +} + +int drm_tegra_pushbuf_queue(struct drm_tegra_pushbuf_private *pushbuf); + +struct drm_tegra_job { + struct drm_tegra_channel *channel; + + unsigned int increments; + uint32_t syncpt; + + struct drm_tegra_reloc *relocs; + unsigned int num_relocs; + + struct drm_tegra_cmdbuf *cmdbufs; + unsigned int num_cmdbufs; + + struct drm_tegra_pushbuf_private *pushbuf; + drmMMListHead pushbufs; +}; + +int drm_tegra_job_add_reloc(struct drm_tegra_job *job, + const struct drm_tegra_reloc *reloc); +int drm_tegra_job_add_cmdbuf(struct drm_tegra_job *job, + const struct drm_tegra_cmdbuf *cmdbuf); + #endif /* __DRM_TEGRA_PRIVATE_H__ */ diff --git a/tegra/pushbuf.c b/tegra/pushbuf.c new file mode 100644 index 000000000000..178d5cd57541 --- /dev/null +++ b/tegra/pushbuf.c @@ -0,0 +1,205 @@ +/* + * Copyright © 2012, 2013 Thierry Reding + * Copyright © 2013 Erik Faye-Lund + * Copyright © 2014 NVIDIA Corporation + * + * 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 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) 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. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include <errno.h> +#include <stdlib.h> +#include <string.h> + +#include "private.h" + +#define HOST1X_OPCODE_NONINCR(offset, count) \ + ((0x2 << 28) | (((offset) & 0xfff) << 16) | ((count) & 0xffff)) + +int drm_tegra_pushbuf_queue(struct drm_tegra_pushbuf_private *pushbuf) +{ + struct drm_tegra_cmdbuf cmdbuf; + int err; + + if (!pushbuf || !pushbuf->bo) + return 0; + + /* unmap buffer object since it won't be accessed anymore */ + drm_tegra_bo_unmap(pushbuf->bo); + + /* add buffer object as command buffers for this job */ + memset(&cmdbuf, 0, sizeof(cmdbuf)); + cmdbuf.words = pushbuf->base.ptr - pushbuf->start; + cmdbuf.handle = pushbuf->bo->handle; + cmdbuf.offset = 0; + + err = drm_tegra_job_add_cmdbuf(pushbuf->job, &cmdbuf); + if (err < 0) + return err; + + return 0; +} + +static inline unsigned long +drm_tegra_pushbuf_get_offset(struct drm_tegra_pushbuf *pushbuf) +{ + struct drm_tegra_pushbuf_private *priv = pushbuf_priv(pushbuf); + + return (unsigned long)pushbuf->ptr - (unsigned long)priv->start; +} + +drm_public +int drm_tegra_pushbuf_new(struct drm_tegra_pushbuf **pushbufp, + struct drm_tegra_job *job) +{ + struct drm_tegra_pushbuf_private *pushbuf; + void *ptr; + int err; + + pushbuf = calloc(1, sizeof(*pushbuf)); + if (!pushbuf) + return -ENOMEM; + + DRMINITLISTHEAD(&pushbuf->list); + DRMINITLISTHEAD(&pushbuf->bos); + pushbuf->job = job; + + *pushbufp = &pushbuf->base; + + DRMLISTADD(&pushbuf->list, &job->pushbufs); + job->pushbuf = pushbuf; + + return 0; +} + +drm_public +int drm_tegra_pushbuf_free(struct drm_tegra_pushbuf *pushbuf) +{ + struct drm_tegra_pushbuf_private *priv = pushbuf_priv(pushbuf); + struct drm_tegra_bo *bo, *tmp; + + if (!pushbuf) + return -EINVAL; + + drm_tegra_bo_unmap(priv->bo); + + DRMLISTFOREACHENTRYSAFE(bo, tmp, &priv->bos, list) + drm_tegra_bo_put(priv->bo); + + DRMLISTDEL(&priv->list); + free(priv); + + return 0; +} + +/** + * drm_tegra_pushbuf_prepare() - prepare push buffer for a series of pushes + * @pushbuf: push buffer + * @words: maximum number of words in series of pushes to follow + */ +drm_public +int drm_tegra_pushbuf_prepare(struct drm_tegra_pushbuf *pushbuf, + unsigned int words) +{ + struct drm_tegra_pushbuf_private *priv = pushbuf_priv(pushbuf); + struct drm_tegra_channel *channel = priv->job->channel; + struct drm_tegra_bo *bo; + void *ptr; + int err; + + if (priv->bo && (pushbuf->ptr + words < priv->end)) + return 0; + + /* + * Align to full pages, since buffer object allocations are page + * granular anyway. + */ + words = align(words, 1024); + + err = drm_tegra_bo_new(&bo, channel->drm, 0, words * sizeof(uint32_t)); + if (err < 0) + return err; + + err = drm_tegra_bo_map(bo, &ptr); + if (err < 0) { + drm_tegra_bo_put(bo); + return err; + } + + /* queue current command stream buffer for submission */ + err = drm_tegra_pushbuf_queue(priv); + if (err < 0) { + drm_tegra_bo_unmap(bo); + drm_tegra_bo_put(bo); + return err; + } + + DRMLISTADD(&bo->list, &priv->bos); + + priv->start = priv->base.ptr = ptr; + priv->end = priv->start + bo->size; + priv->bo = bo; + + return 0; +} + +drm_public +int drm_tegra_pushbuf_relocate(struct drm_tegra_pushbuf *pushbuf, + struct drm_tegra_bo *target, + unsigned long offset, + unsigned long shift) +{ + struct drm_tegra_pushbuf_private *priv = pushbuf_priv(pushbuf); + struct drm_tegra_reloc reloc; + int err; + + memset(&reloc, 0, sizeof(reloc)); + reloc.cmdbuf.handle = priv->bo->handle; + reloc.cmdbuf.offset = drm_tegra_pushbuf_get_offset(pushbuf); + reloc.target.handle = target->handle; + reloc.target.offset = offset; + reloc.shift = shift; + + err = drm_tegra_job_add_reloc(priv->job, &reloc); + if (err < 0) + return err; + + *pushbuf->ptr++ = 0xdeadbeef; + + return 0; +} + +drm_public +int drm_tegra_pushbuf_sync(struct drm_tegra_pushbuf *pushbuf, + enum drm_tegra_syncpt_cond cond) +{ + struct drm_tegra_pushbuf_private *priv = pushbuf_priv(pushbuf); + + if (cond >= DRM_TEGRA_SYNCPT_COND_MAX) + return -EINVAL; + + *pushbuf->ptr++ = HOST1X_OPCODE_NONINCR(0x0, 0x1); + *pushbuf->ptr++ = cond << 8 | priv->job->syncpt; + priv->job->increments++; + + return 0; +} diff --git a/tegra/tegra.c b/tegra/tegra.c index bf6d035453d5..1f7b9e7345b6 100644 --- a/tegra/tegra.c +++ b/tegra/tegra.c @@ -56,6 +56,7 @@ static void drm_tegra_bo_free(struct drm_tegra_bo *bo) drmIoctl(drm->fd, DRM_IOCTL_GEM_CLOSE, &args); + DRMLISTDEL(&bo->list); free(bo); } @@ -127,6 +128,7 @@ int drm_tegra_bo_new(struct drm_tegra_bo **bop, struct drm_tegra *drm, if (!bo) return -ENOMEM; + DRMINITLISTHEAD(&bo->list); atomic_set(&bo->ref, 1); bo->flags = flags; bo->size = size; diff --git a/tegra/tegra.h b/tegra/tegra.h index 0731cb3bd4dc..4cf3b49a3e3e 100644 --- a/tegra/tegra.h +++ b/tegra/tegra.h @@ -28,6 +28,13 @@ #include <stdint.h> #include <stdlib.h> +#include <tegra_drm.h> + +enum drm_tegra_class { + DRM_TEGRA_GR2D, + DRM_TEGRA_GR3D, +}; + struct drm_tegra_bo; struct drm_tegra; @@ -44,4 +51,49 @@ int drm_tegra_bo_get_handle(struct drm_tegra_bo *bo, uint32_t *handle); int drm_tegra_bo_map(struct drm_tegra_bo *bo, void **ptr); int drm_tegra_bo_unmap(struct drm_tegra_bo *bo); +struct drm_tegra_channel; +struct drm_tegra_job; + +struct drm_tegra_pushbuf { + uint32_t *ptr; +}; + +struct drm_tegra_fence; + +enum drm_tegra_syncpt_cond { + DRM_TEGRA_SYNCPT_COND_IMMEDIATE, + DRM_TEGRA_SYNCPT_COND_OP_DONE, + DRM_TEGRA_SYNCPT_COND_RD_DONE, + DRM_TEGRA_SYNCPT_COND_WR_SAFE, + DRM_TEGRA_SYNCPT_COND_MAX, +}; + +int drm_tegra_channel_open(struct drm_tegra_channel **channelp, + struct drm_tegra *drm, + enum drm_tegra_class client); +int drm_tegra_channel_close(struct drm_tegra_channel *channel); + +int drm_tegra_job_new(struct drm_tegra_job **jobp, + struct drm_tegra_channel *channel); +int drm_tegra_job_free(struct drm_tegra_job *job); +int drm_tegra_job_submit(struct drm_tegra_job *job, + struct drm_tegra_fence **fencep); + +int drm_tegra_pushbuf_new(struct drm_tegra_pushbuf **pushbufp, + struct drm_tegra_job *job); +int drm_tegra_pushbuf_free(struct drm_tegra_pushbuf *pushbuf); +int drm_tegra_pushbuf_prepare(struct drm_tegra_pushbuf *pushbuf, + unsigned int words); +int drm_tegra_pushbuf_relocate(struct drm_tegra_pushbuf *pushbuf, + struct drm_tegra_bo *target, + unsigned long offset, + unsigned long shift); +int drm_tegra_pushbuf_sync(struct drm_tegra_pushbuf *pushbuf, + enum drm_tegra_syncpt_cond cond); + +int drm_tegra_fence_wait_timeout(struct drm_tegra_fence *fence, + unsigned long timeout); +int drm_tegra_fence_wait(struct drm_tegra_fence *fence); +void drm_tegra_fence_free(struct drm_tegra_fence *fence); + #endif /* __DRM_TEGRA_H__ */ -- 1.9.1 _______________________________________________ dri-devel mailing list dri-devel@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/dri-devel