summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThierry Reding <treding@nvidia.com>2014-02-24 11:55:13 +0100
committerThierry Reding <treding@nvidia.com>2018-05-02 17:29:40 +0200
commit9b44f814ea1a6d2bfc12549670824d8206b015af (patch)
tree0fdc161ddcea2e3eaa91a43118f19587cc167089
parentf0896fa5d12a85f7b799cd21d6a5286c93f20879 (diff)
WIP: tegra: Update for de-staged ABI
Signed-off-by: Thierry Reding <treding@nvidia.com>
-rw-r--r--include/drm/tegra_drm.h465
-rw-r--r--tegra/channel.c35
-rw-r--r--tegra/fence.c95
-rw-r--r--tegra/job.c130
-rw-r--r--tegra/private.h31
-rw-r--r--tegra/pushbuf.c111
-rw-r--r--tegra/tegra.c97
-rw-r--r--tegra/tegra.h62
-rw-r--r--tests/tegra/drm-test-tegra.c6
-rw-r--r--tests/tegra/host1x.h34
10 files changed, 719 insertions, 347 deletions
diff --git a/include/drm/tegra_drm.h b/include/drm/tegra_drm.h
index 12f9bf84..f61dc5ae 100644
--- a/include/drm/tegra_drm.h
+++ b/include/drm/tegra_drm.h
@@ -29,178 +29,431 @@
extern "C" {
#endif
-#define DRM_TEGRA_GEM_CREATE_TILED (1 << 0)
-#define DRM_TEGRA_GEM_CREATE_BOTTOM_UP (1 << 1)
+#define DRM_TEGRA_GEM_CONTIGUOUS (1 << 0)
+#define DRM_TEGRA_GEM_FLAGS (DRM_TEGRA_GEM_CONTIGUOUS)
+/**
+ * struct drm_tegra_gem_create - parameters for the GEM object creation IOCTL
+ */
struct drm_tegra_gem_create {
+ /**
+ * @size:
+ *
+ * The size, in bytes, of the buffer object to be created.
+ */
__u64 size;
+
+ /**
+ * @flags:
+ *
+ * A bitmask of flags that influence the creation of GEM objects:
+ *
+ * DRM_TEGRA_GEM_CONTIGUOUS - The buffer is to be backed by physically
+ * contiguous memory.
+ */
__u32 flags;
+
+ /**
+ * @handle:
+ *
+ * Return location for the handle of the created GEM object.
+ */
__u32 handle;
};
+/**
+ * struct drm_tegra_gem_mmap - parameters for the GEM mmap IOCTL
+ */
struct drm_tegra_gem_mmap {
+ /**
+ * @handle:
+ *
+ * Handle of the GEM object to obtain an mmap offset for.
+ */
__u32 handle;
- __u32 pad;
- __u64 offset;
-};
-
-struct drm_tegra_syncpt_read {
- __u32 id;
- __u32 value;
-};
-struct drm_tegra_syncpt_incr {
- __u32 id;
+ /**
+ * @pad:
+ *
+ * Structure padding that may be used in the future. Must be 0.
+ */
__u32 pad;
-};
-struct drm_tegra_syncpt_wait {
- __u32 id;
- __u32 thresh;
- __u32 timeout;
- __u32 value;
+ /**
+ * @offset:
+ *
+ * Return location for the mmap offset for the given GEM object.
+ */
+ __u64 offset;
};
-#define DRM_TEGRA_NO_TIMEOUT (0xffffffff)
+#define DRM_TEGRA_CHANNEL_FLAGS (0)
struct drm_tegra_open_channel {
+ /**
+ * @client:
+ *
+ * The client ID for this channel.
+ */
__u32 client;
- __u32 pad;
+
+ /**
+ * @flags:
+ *
+ * A bitmask of flags that influence the channel creation. Currently
+ * no flags are defined, so this must be 0.
+ */
+ __u32 flags;
+
+ /**
+ * @syncpts:
+ *
+ * Return location for the number of syncpoints used by this channel.
+ */
+ __u32 syncpts;
+
+ /**
+ * @version:
+ *
+ * Return location for the implementation version of this channel.
+ */
+ __u32 version;
+
+ /**
+ * @context:
+ *
+ * Return location for the application context of this channel. This
+ * context needs to be passed to the DRM_TEGRA_CHANNEL_CLOSE or the
+ * DRM_TEGRA_SUBMIT IOCTLs.
+ */
__u64 context;
+
+ /**
+ * @reserved:
+ *
+ * This field is reserved for future use. Must be 0.
+ */
+ __u64 reserved;
};
struct drm_tegra_close_channel {
+ /**
+ * @context:
+ *
+ * The application context of this channel. This is obtained from the
+ * DRM_TEGRA_OPEN_CHANNEL IOCTL.
+ */
__u64 context;
};
-struct drm_tegra_get_syncpt {
- __u64 context;
- __u32 index;
- __u32 id;
-};
+#define DRM_TEGRA_BUFFER_FLAGS (0)
-struct drm_tegra_get_syncpt_base {
- __u64 context;
- __u32 syncpt;
- __u32 id;
+struct drm_tegra_buffer {
+ /**
+ * @handle:
+ *
+ * Handle of the buffer.
+ */
+ __u32 handle;
+
+ /**
+ * @flags:
+ *
+ * A bitmask of flags specifying the usage of the buffer. Currently no
+ * flags are defined, so this must be 0.
+ */
+ __u32 flags;
};
-struct drm_tegra_syncpt {
- __u32 id;
- __u32 incrs;
+#define DRM_TEGRA_FENCE_WAIT (1 << 0)
+#define DRM_TEGRA_FENCE_EMIT (1 << 1)
+#define DRM_TEGRA_FENCE_FD (1 << 2)
+#define DRM_TEGRA_FENCE_FLAGS (DRM_TEGRA_FENCE_WAIT | \
+ DRM_TEGRA_FENCE_EMIT | \
+ DRM_TEGRA_FENCE_FD)
+
+struct drm_tegra_fence {
+ /**
+ * @handle:
+ *
+ * Handle (syncobj) or file descriptor (sync FD) of the fence. It is
+ * interpreted based on the DRM_TEGRA_FENCE_FD flag (see below).
+ */
+ __u32 handle;
+
+ /**
+ * @flags:
+ *
+ * A bitmask of flags that specify this fence.
+ *
+ * DRM_TEGRA_FENCE_WAIT - Wait for this fence before the new command
+ * buffer is submitted.
+ * DRM_TEGRA_FENCE_EMIT - Emit this fence when the command buffer is
+ * done being processed.
+ * DRM_TEGRA_FENCE_FD - This fence is a sync FD. If not specified, a
+ * syncobj will be used.
+ */
+ __u32 flags;
+
+ /**
+ * @offset:
+ *
+ * Offset in the command stream for this fence. This is used to patch
+ * the command stream with the resolved syncpoint ID.
+ */
+ __u32 offset;
+
+ /**
+ * @index:
+ *
+ * Syncpoint to use for this fence. This is an index into the list of
+ * syncpoints of the channel. It will be resolved to a real syncpoint
+ * ID upon job submission.
+ */
+ __u32 index;
+
+ /**
+ * @value:
+ *
+ * Number of times to increment the syncpoint.
+ */
+ __u32 value;
+
+ /**
+ * @reserved:
+ *
+ * This field is reserved for future use. Must be 0.
+ */
+ __u32 reserved[3];
};
+#define DRM_TEGRA_CMDBUF_FLAGS (0)
+
+/**
+ * struct drm_tegra_cmdbuf - structure describing a command buffer
+ */
struct drm_tegra_cmdbuf {
- __u32 handle;
+ /**
+ * @index:
+ *
+ * Index into the job's buffer handle list, pointing to the handle of
+ * the GEM object that contains this command buffer.
+ */
+ __u32 index;
+
+ /**
+ * @offset:
+ *
+ * Offset, in bytes, into the GEM object at which the command buffer
+ * starts. Needs to be a multiple of 4.
+ */
__u32 offset;
+
+ /**
+ * @words:
+ *
+ * Number of 32-bit words in this command buffer.
+ */
__u32 words;
+
+ /**
+ * @flags:
+ *
+ * A bitmask of flags that influence the processing of this command
+ * buffer. Currently no flags are defined, so this must be 0.
+ */
+ __u32 flags;
+
+ /**
+ * @pad:
+ *
+ * Structure padding that may be used in the future. Must be 0.
+ */
__u32 pad;
+
+ /**
+ * @num_fences:
+ *
+ * The number of fences attached to this command buffer.
+ */
+ __u32 num_fences;
+
+ /**
+ * @fences:
+ *
+ * Pointer to an array of @num_fences &struct drm_tegra_fence objects.
+ */
+ __u64 fences;
};
+#define DRM_TEGRA_RELOC_FLAGS (0)
+
+/**
+ * struct drm_tegra_reloc - GEM object relocation structure
+ */
struct drm_tegra_reloc {
struct {
- __u32 handle;
+ /**
+ * @cmdbuf.index:
+ *
+ * Index into the job's buffer handle list pointing to the
+ * handle of the GEM object containing the command buffer for
+ * which to perform this GEM object relocation.
+ */
+ __u32 index;
+
+ /**
+ * @cmdbuf.offset:
+ *
+ * Offset into the command buffer at which to insert the the
+ * relocated address.
+ */
__u32 offset;
} cmdbuf;
+
struct {
- __u32 handle;
+ /**
+ * @target.index:
+ *
+ * Index into the job's buffer handle list pointing to the
+ * handle of the GEM object to be relocated.
+ */
+ __u32 index;
+
+ /**
+ * @target.offset:
+ *
+ * Offset into the target GEM object at which the relocated
+ * data starts.
+ */
__u32 offset;
} target;
+
+ /**
+ * @shift:
+ *
+ * The number of bits by which to shift relocated addresses.
+ */
__u32 shift;
- __u32 pad;
-};
-struct drm_tegra_waitchk {
- __u32 handle;
- __u32 offset;
- __u32 syncpt;
- __u32 thresh;
+ /**
+ * @flags:
+ *
+ * A bitmask of flags that determine how the GEM object should be
+ * relocated.
+ */
+ __u32 flags;
+
+ /**
+ * @reserved:
+ *
+ * This field is reserved for future use. Must be 0.
+ */
+ __u64 reserved;
};
+#define DRM_TEGRA_SUBMIT_FLAGS (0)
+
+/**
+ * struct drm_tegra_submit - job submission structure
+ */
struct drm_tegra_submit {
+ /**
+ * @context:
+ *
+ * The application context identifying the channel to use for the
+ * execution of this job.
+ */
__u64 context;
- __u32 num_syncpts;
+
+ /**
+ * @num_buffers:
+ *
+ * The number of GEM objects used during the execution of this job.
+ */
+ __u32 num_buffers;
+
+ /**
+ * @num_cmdbufs:
+ *
+ * The number of command buffers to execute as part of this job.
+ */
__u32 num_cmdbufs;
- __u32 num_relocs;
- __u32 num_waitchks;
- __u32 waitchk_mask;
- __u32 timeout;
- __u64 syncpts;
- __u64 cmdbufs;
- __u64 relocs;
- __u64 waitchks;
- __u32 fence; /* Return value */
- __u32 reserved[5]; /* future expansion */
-};
+ /**
+ * @num_relocs:
+ *
+ * The number of relocations to perform before executing this job.
+ */
+ __u32 num_relocs;
-#define DRM_TEGRA_GEM_TILING_MODE_PITCH 0
-#define DRM_TEGRA_GEM_TILING_MODE_TILED 1
-#define DRM_TEGRA_GEM_TILING_MODE_BLOCK 2
+ /**
+ * @timeout:
+ *
+ * The maximum amount of time, in milliseconds, to allow for the
+ * execution of this job.
+ */
+ __u32 timeout;
-struct drm_tegra_gem_set_tiling {
- /* input */
- __u32 handle;
- __u32 mode;
- __u32 value;
- __u32 pad;
-};
+ /**
+ * @buffers:
+ *
+ * A pointer to @num_buffers &struct drm_tegra_buffer structures that
+ * specify the GEM objects used during the execution of this job.
+ */
+ __u64 buffers;
-struct drm_tegra_gem_get_tiling {
- /* input */
- __u32 handle;
- /* output */
- __u32 mode;
- __u32 value;
- __u32 pad;
-};
+ /**
+ * @cmdbufs:
+ *
+ * A pointer to @num_cmdbufs &struct drm_tegra_cmdbuf structures that
+ * define the command buffers to execute as part of this job.
+ */
+ __u64 cmdbufs;
-#define DRM_TEGRA_GEM_BOTTOM_UP (1 << 0)
-#define DRM_TEGRA_GEM_FLAGS (DRM_TEGRA_GEM_BOTTOM_UP)
+ /**
+ * @relocs:
+ *
+ * A pointer to @num_relocs &struct drm_tegra_reloc structures that
+ * specify the relocations that need to be performed before executing
+ * this job.
+ */
+ __u64 relocs;
-struct drm_tegra_gem_set_flags {
- /* input */
- __u32 handle;
- /* output */
+ /**
+ * @flags:
+ *
+ * A bitmask of flags that specify how to execute this job. Currently
+ * no flags are defined, so this must be 0.
+ */
__u32 flags;
-};
-struct drm_tegra_gem_get_flags {
- /* input */
- __u32 handle;
- /* output */
- __u32 flags;
+ /**
+ * @pad:
+ *
+ * Structure padding that may be used in the future. Must be 0.
+ */
+ __u32 pad;
+
+ /**
+ * @reserved:
+ *
+ * This field is reserved for future use. Must be 0.
+ */
+ __u64 reserved[9]; /* future expansion */
};
#define DRM_TEGRA_GEM_CREATE 0x00
#define DRM_TEGRA_GEM_MMAP 0x01
-#define DRM_TEGRA_SYNCPT_READ 0x02
-#define DRM_TEGRA_SYNCPT_INCR 0x03
-#define DRM_TEGRA_SYNCPT_WAIT 0x04
-#define DRM_TEGRA_OPEN_CHANNEL 0x05
-#define DRM_TEGRA_CLOSE_CHANNEL 0x06
-#define DRM_TEGRA_GET_SYNCPT 0x07
-#define DRM_TEGRA_SUBMIT 0x08
-#define DRM_TEGRA_GET_SYNCPT_BASE 0x09
-#define DRM_TEGRA_GEM_SET_TILING 0x0a
-#define DRM_TEGRA_GEM_GET_TILING 0x0b
-#define DRM_TEGRA_GEM_SET_FLAGS 0x0c
-#define DRM_TEGRA_GEM_GET_FLAGS 0x0d
+#define DRM_TEGRA_OPEN_CHANNEL 0x02
+#define DRM_TEGRA_CLOSE_CHANNEL 0x03
+#define DRM_TEGRA_SUBMIT 0x04
#define DRM_IOCTL_TEGRA_GEM_CREATE DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_GEM_CREATE, struct drm_tegra_gem_create)
#define DRM_IOCTL_TEGRA_GEM_MMAP DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_GEM_MMAP, struct drm_tegra_gem_mmap)
-#define DRM_IOCTL_TEGRA_SYNCPT_READ DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_SYNCPT_READ, struct drm_tegra_syncpt_read)
-#define DRM_IOCTL_TEGRA_SYNCPT_INCR DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_SYNCPT_INCR, struct drm_tegra_syncpt_incr)
-#define DRM_IOCTL_TEGRA_SYNCPT_WAIT DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_SYNCPT_WAIT, struct drm_tegra_syncpt_wait)
#define DRM_IOCTL_TEGRA_OPEN_CHANNEL DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_OPEN_CHANNEL, struct drm_tegra_open_channel)
-#define DRM_IOCTL_TEGRA_CLOSE_CHANNEL DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_CLOSE_CHANNEL, struct drm_tegra_open_channel)
-#define DRM_IOCTL_TEGRA_GET_SYNCPT DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_GET_SYNCPT, struct drm_tegra_get_syncpt)
+#define DRM_IOCTL_TEGRA_CLOSE_CHANNEL DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_CLOSE_CHANNEL, struct drm_tegra_close_channel)
#define DRM_IOCTL_TEGRA_SUBMIT DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_SUBMIT, struct drm_tegra_submit)
-#define DRM_IOCTL_TEGRA_GET_SYNCPT_BASE DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_GET_SYNCPT_BASE, struct drm_tegra_get_syncpt_base)
-#define DRM_IOCTL_TEGRA_GEM_SET_TILING DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_GEM_SET_TILING, struct drm_tegra_gem_set_tiling)
-#define DRM_IOCTL_TEGRA_GEM_GET_TILING DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_GEM_GET_TILING, struct drm_tegra_gem_get_tiling)
-#define DRM_IOCTL_TEGRA_GEM_SET_FLAGS DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_GEM_SET_FLAGS, struct drm_tegra_gem_set_flags)
-#define DRM_IOCTL_TEGRA_GEM_GET_FLAGS DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_GEM_GET_FLAGS, struct drm_tegra_gem_get_flags)
#if defined(__cplusplus)
}
diff --git a/tegra/channel.c b/tegra/channel.c
index 3818b5e8..4a41daaa 100644
--- a/tegra/channel.c
+++ b/tegra/channel.c
@@ -33,25 +33,6 @@
#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;
-}
-
int drm_tegra_channel_open(struct drm_tegra_channel **channelp,
struct drm_tegra *drm,
enum drm_tegra_class client)
@@ -62,6 +43,10 @@ int drm_tegra_channel_open(struct drm_tegra_channel **channelp,
int err;
switch (client) {
+ case DRM_TEGRA_HOST1X:
+ class = HOST1X_CLASS_HOST1X;
+ break;
+
case DRM_TEGRA_GR2D:
class = HOST1X_CLASS_GR2D;
break;
@@ -89,15 +74,10 @@ int drm_tegra_channel_open(struct drm_tegra_channel **channelp,
return -errno;
}
+ channel->num_syncpts = args.syncpts;
channel->context = args.context;
channel->class = class;
- err = drm_tegra_channel_setup(channel);
- if (err < 0) {
- free(channel);
- return err;
- }
-
*channelp = channel;
return 0;
@@ -125,3 +105,8 @@ int drm_tegra_channel_close(struct drm_tegra_channel *channel)
return 0;
}
+
+unsigned int drm_tegra_channel_get_syncpoints(struct drm_tegra_channel *channel)
+{
+ return channel->num_syncpts;
+}
diff --git a/tegra/fence.c b/tegra/fence.c
index a2dd394e..7e3dc432 100644
--- a/tegra/fence.c
+++ b/tegra/fence.c
@@ -1,7 +1,5 @@
/*
- * Copyright © 2012, 2013 Thierry Reding
- * Copyright © 2013 Erik Faye-Lund
- * Copyright © 2014 NVIDIA Corporation
+ * Copyright © 2018 NVIDIA Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@@ -27,44 +25,89 @@
#endif
#include <errno.h>
+#include <stdbool.h>
+#include <stdio.h> /* XXX remove */
#include <string.h>
+#include <unistd.h>
#include <sys/ioctl.h>
+#include <sys/poll.h>
#include "private.h"
-int drm_tegra_fence_wait_timeout(struct drm_tegra_fence *fence,
- unsigned long timeout)
+static int drm_tegra_syncobj_destroy(struct drm_tegra *drm, uint32_t handle)
{
- struct drm_tegra_syncpt_wait args;
+ struct drm_syncobj_destroy args;
int err;
memset(&args, 0, sizeof(args));
- args.id = fence->syncpt;
- args.thresh = fence->value;
- args.timeout = timeout;
+ args.handle = handle;
- while (true) {
- err = ioctl(fence->drm->fd, DRM_IOCTL_TEGRA_SYNCPT_WAIT, &args);
- if (err < 0) {
- if (errno == EINTR)
- continue;
-
- return -errno;
- }
-
- break;
- }
+ err = ioctl(drm->fd, DRM_IOCTL_SYNCOBJ_DESTROY, &args);
+ if (err < 0)
+ return -errno;
return 0;
}
-int drm_tegra_fence_wait(struct drm_tegra_fence *fence)
+int drm_tegra_fence_wait(struct drm_tegra *drm, struct drm_tegra_fence *fence)
{
- return drm_tegra_fence_wait_timeout(fence, -1);
-}
+ int err;
-void drm_tegra_fence_free(struct drm_tegra_fence *fence)
-{
- free(fence);
+ if ((fence->flags & DRM_TEGRA_FENCE_EMIT) == 0)
+ return 0;
+
+ printf("fence: %p\n", fence);
+ printf(" handle: %u\n", fence->handle);
+ printf(" flags: %x\n", fence->flags);
+ printf(" offset: %x\n", fence->offset);
+ printf(" index: %u\n", fence->index);
+ printf(" value: %u\n", fence->value);
+
+ if (fence->flags & DRM_TEGRA_FENCE_FD) {
+ while (true) {
+ struct pollfd fds = {
+ .fd = fence->handle,
+ .events = POLLIN,
+ };
+
+ err = poll(&fds, 1, -1);
+ if (err > 0) {
+ if (fds.revents & (POLLERR | POLLNVAL))
+ err = -EINVAL;
+ else
+ err = 0;
+
+ break;
+ }
+
+ if (err == 0) {
+ err = -ETIMEDOUT;
+ break;
+ }
+
+ if (errno != EINTR && errno != EAGAIN) {
+ err = -errno;
+ break;
+ }
+ }
+
+ close(fence->handle);
+ } else {
+ struct drm_syncobj_wait args;
+
+ memset(&args, 0, sizeof(args));
+ args.handles = (uintptr_t)&fence->handle;
+ args.count_handles = 1;
+ args.timeout_nsec = -1;
+ args.flags = DRM_SYNCOBJ_WAIT_FLAGS_WAIT_ALL;
+
+ err = ioctl(drm->fd, DRM_IOCTL_SYNCOBJ_WAIT, &args);
+ if (err < 0)
+ err = -errno;
+
+ drm_tegra_syncobj_destroy(drm, fence->handle);
+ }
+
+ return err;
}
diff --git a/tegra/job.c b/tegra/job.c
index 370c6939..80b6a855 100644
--- a/tegra/job.c
+++ b/tegra/job.c
@@ -43,7 +43,7 @@ int drm_tegra_job_add_reloc(struct drm_tegra_job *job,
size = (job->num_relocs + 1) * sizeof(*reloc);
relocs = realloc(job->relocs, size);
- if (!reloc)
+ if (!relocs)
return -ENOMEM;
job->relocs = relocs;
@@ -53,6 +53,41 @@ int drm_tegra_job_add_reloc(struct drm_tegra_job *job,
return 0;
}
+int drm_tegra_job_add_buffer(struct drm_tegra_job *job,
+ const struct drm_tegra_buffer *buffer,
+ unsigned int *index)
+{
+ struct drm_tegra_buffer *buffers;
+ unsigned int i;
+ size_t size;
+
+ /* check if the buffer is already in the job's buffer list */
+ for (i = 0; i < job->num_buffers; i++) {
+ if (job->buffers[i].handle == buffer->handle) {
+ if (index)
+ *index = i;
+
+ return 0;
+ }
+ }
+
+ size = (job->num_buffers + 1) * sizeof(*buffers);
+
+ buffers = realloc(job->buffers, size);
+ if (!buffers)
+ return -ENOMEM;
+
+ buffers[job->num_buffers] = *buffer;
+ job->buffers = buffers;
+
+ if (index)
+ *index = job->num_buffers;
+
+ job->num_buffers++;
+
+ return 0;
+}
+
int drm_tegra_job_add_cmdbuf(struct drm_tegra_job *job,
const struct drm_tegra_cmdbuf *cmdbuf)
{
@@ -105,12 +140,9 @@ int drm_tegra_job_free(struct drm_tegra_job *job)
return 0;
}
-int drm_tegra_job_submit(struct drm_tegra_job *job,
- struct drm_tegra_fence **fencep)
+int drm_tegra_job_submit(struct drm_tegra_job *job, unsigned long timeout)
{
struct drm_tegra *drm = job->channel->drm;
- struct drm_tegra_fence *fence = NULL;
- struct drm_tegra_syncpt *syncpts;
struct drm_tegra_submit args;
int err;
@@ -124,50 +156,78 @@ int drm_tegra_job_submit(struct drm_tegra_job *job,
job->pushbuf = NULL;
- if (fencep) {
- fence = calloc(1, sizeof(*fence));
- if (!fence)
- return -ENOMEM;
- }
-
- syncpts = calloc(1, sizeof(*syncpts));
- if (!syncpts) {
- 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_buffers = job->num_buffers;
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.buffers = (uintptr_t)job->buffers;
args.cmdbufs = (uintptr_t)job->cmdbufs;
args.relocs = (uintptr_t)job->relocs;
- args.waitchks = 0;
+ args.flags = 0;
err = ioctl(drm->fd, DRM_IOCTL_TEGRA_SUBMIT, &args);
- if (err < 0) {
- free(syncpts);
- free(fence);
+ if (err < 0)
return -errno;
- }
- if (fence) {
- fence->syncpt = job->syncpt;
- fence->value = args.fence;
- fence->drm = drm;
- *fencep = fence;
+ return 0;
+}
+
+static inline void *u64_to_ptr(__u64 address)
+{
+ return (void *)(uintptr_t)address;
+}
+
+unsigned int drm_tegra_job_get_fences(struct drm_tegra_job *job,
+ struct drm_fence *out_fences,
+ unsigned int count)
+{
+ unsigned int i, j, num = 0;
+
+ for (i = 0; i < job->num_cmdbufs; i++) {
+ struct drm_tegra_cmdbuf *cmdbuf = &job->cmdbufs[i];
+ struct drm_tegra_fence *fences = u64_to_ptr(cmdbuf->fences);
+
+ for (j = 0; j < cmdbuf->num_fences; j++) {
+ struct drm_tegra_fence *fence = &fences[j];
+
+ if (fence->flags & DRM_TEGRA_FENCE_EMIT) {
+ if (num < count) {
+ if ((fence->flags & DRM_TEGRA_FENCE_FD) == 0) {
+ out_fences[num].fence.handle = fence->handle;
+ out_fences[num].type = DRM_FENCE_SYNCOBJ;
+ } else {
+ out_fences[num].fence.fd = fence->handle;
+ out_fences[num].type = DRM_FENCE_FD;
+ }
+ }
+
+ num++;
+ }
+ }
}
- free(syncpts);
+ return num;
+}
+
+int drm_tegra_job_wait(struct drm_tegra_job *job)
+{
+ struct drm_tegra *drm = job->channel->drm;
+ unsigned int i, j;
+ int err;
+
+ for (i = 0; i < job->num_cmdbufs; i++) {
+ struct drm_tegra_cmdbuf *cmdbuf = &job->cmdbufs[i];
+ struct drm_tegra_fence *fences = u64_to_ptr(cmdbuf->fences);
+
+ for (j = 0; j < cmdbuf->num_fences; j++) {
+ err = drm_tegra_fence_wait(drm, &fences[j]);
+ if (err < 0)
+ return err;
+ }
+ }
return 0;
}
diff --git a/tegra/private.h b/tegra/private.h
index 1c9fca7d..9e9ae86c 100644
--- a/tegra/private.h
+++ b/tegra/private.h
@@ -60,7 +60,7 @@ struct drm_tegra_bo {
struct drm_tegra *drm;
drmMMListHead list;
uint32_t handle;
- uint32_t offset;
+ uint64_t offset;
uint32_t flags;
uint32_t size;
atomic_t ref;
@@ -70,14 +70,8 @@ struct drm_tegra_bo {
struct drm_tegra_channel {
struct drm_tegra *drm;
enum host1x_class class;
+ unsigned int num_syncpts;
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 {
@@ -87,8 +81,12 @@ struct drm_tegra_pushbuf_private {
drmMMListHead bos;
struct drm_tegra_bo *bo;
+ unsigned int index;
uint32_t *start;
uint32_t *end;
+
+ struct drm_tegra_fence *fences;
+ unsigned int num_fences;
};
static inline struct drm_tegra_pushbuf_private *
@@ -102,22 +100,25 @@ 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_buffer *buffers;
+ unsigned int num_buffers;
struct drm_tegra_cmdbuf *cmdbufs;
unsigned int num_cmdbufs;
+ struct drm_tegra_reloc *relocs;
+ unsigned int num_relocs;
+
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_buffer(struct drm_tegra_job *job,
+ const struct drm_tegra_buffer *buffer,
+ unsigned int *index);
int drm_tegra_job_add_cmdbuf(struct drm_tegra_job *job,
const struct drm_tegra_cmdbuf *cmdbuf);
+int drm_tegra_job_add_reloc(struct drm_tegra_job *job,
+ const struct drm_tegra_reloc *reloc);
#endif /* __DRM_TEGRA_PRIVATE_H__ */
diff --git a/tegra/pushbuf.c b/tegra/pushbuf.c
index 7be12a76..54a0f831 100644
--- a/tegra/pushbuf.c
+++ b/tegra/pushbuf.c
@@ -48,9 +48,14 @@ int drm_tegra_pushbuf_queue(struct drm_tegra_pushbuf_private *pushbuf)
/* 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.index = pushbuf->index;
cmdbuf.offset = 0;
+ cmdbuf.words = pushbuf->base.ptr - pushbuf->start;
+
+ if (pushbuf->num_fences) {
+ cmdbuf.fences = (uintptr_t)pushbuf->fences;
+ cmdbuf.num_fences = pushbuf->num_fences;
+ }
err = drm_tegra_job_add_cmdbuf(pushbuf->job, &cmdbuf);
if (err < 0)
@@ -82,7 +87,7 @@ int drm_tegra_pushbuf_new(struct drm_tegra_pushbuf **pushbufp,
*pushbufp = &pushbuf->base;
- DRMLISTADD(&pushbuf->list, &job->pushbufs);
+ DRMLISTADDTAIL(&pushbuf->list, &job->pushbufs);
job->pushbuf = pushbuf;
return 0;
@@ -117,6 +122,7 @@ int drm_tegra_pushbuf_prepare(struct drm_tegra_pushbuf *pushbuf,
{
struct drm_tegra_pushbuf_private *priv = pushbuf_priv(pushbuf);
struct drm_tegra_channel *channel = priv->job->channel;
+ struct drm_tegra_buffer buffer;
struct drm_tegra_bo *bo;
void *ptr;
int err;
@@ -148,12 +154,19 @@ int drm_tegra_pushbuf_prepare(struct drm_tegra_pushbuf *pushbuf,
return err;
}
- DRMLISTADD(&bo->list, &priv->bos);
+ DRMLISTADDTAIL(&bo->list, &priv->bos);
priv->start = priv->base.ptr = ptr;
- priv->end = priv->start + bo->size;
+ priv->end = priv->start + bo->size / 4;
priv->bo = bo;
+ memset(&buffer, 0, sizeof(buffer));
+ buffer.handle = bo->handle;
+
+ err = drm_tegra_job_add_buffer(priv->job, &buffer, &priv->index);
+ if (err < 0)
+ return err;
+
return 0;
}
@@ -163,13 +176,22 @@ int drm_tegra_pushbuf_relocate(struct drm_tegra_pushbuf *pushbuf,
unsigned long shift)
{
struct drm_tegra_pushbuf_private *priv = pushbuf_priv(pushbuf);
+ struct drm_tegra_buffer buffer;
struct drm_tegra_reloc reloc;
+ unsigned int index;
int err;
+ memset(&buffer, 0, sizeof(buffer));
+ buffer.handle = target->handle;
+
+ err = drm_tegra_job_add_buffer(priv->job, &buffer, &index);
+ if (err < 0)
+ return err;
+
memset(&reloc, 0, sizeof(reloc));
- reloc.cmdbuf.handle = priv->bo->handle;
+ reloc.cmdbuf.index = priv->index;
reloc.cmdbuf.offset = drm_tegra_pushbuf_get_offset(pushbuf);
- reloc.target.handle = target->handle;
+ reloc.target.index = index;
reloc.target.offset = offset;
reloc.shift = shift;
@@ -182,17 +204,82 @@ int drm_tegra_pushbuf_relocate(struct drm_tegra_pushbuf *pushbuf,
return 0;
}
-int drm_tegra_pushbuf_sync(struct drm_tegra_pushbuf *pushbuf,
- enum drm_tegra_syncpt_cond cond)
+static int drm_tegra_pushbuf_add_fence(struct drm_tegra_pushbuf *pushbuf,
+ const struct drm_tegra_fence *fence)
{
struct drm_tegra_pushbuf_private *priv = pushbuf_priv(pushbuf);
+ struct drm_tegra_fence *fences;
+ size_t size;
+
+ size = (priv->num_fences + 1) * sizeof(*fence);
+
+ fences = realloc(priv->fences, size);
+ if (!fences)
+ return -ENOMEM;
+
+ priv->fences = fences;
+
+ priv->fences[priv->num_fences++] = *fence;
+
+ return 0;
+}
+
+int drm_tegra_pushbuf_wait_fd(struct drm_tegra_pushbuf *pushbuf,
+ int fd)
+{
+ struct drm_tegra_fence fence;
+ int err;
+
+ memset(&fence, 0, sizeof(fence));
+ fence.handle = fd;
+ fence.flags = DRM_TEGRA_FENCE_FD | DRM_TEGRA_FENCE_WAIT;
- if (cond >= DRM_TEGRA_SYNCPT_COND_MAX)
+ err = drm_tegra_pushbuf_add_fence(pushbuf, &fence);
+ if (err < 0)
+ return err;
+
+ return 0;
+}
+
+int drm_tegra_pushbuf_wait_syncobj(struct drm_tegra_pushbuf *pushbuf,
+ uint32_t syncobj)
+{
+ struct drm_tegra_fence fence;
+ int err;
+
+ memset(&fence, 0, sizeof(fence));
+ fence.handle = syncobj;
+ fence.flags = DRM_TEGRA_FENCE_WAIT;
+
+ err = drm_tegra_pushbuf_add_fence(pushbuf, &fence);
+ if (err < 0)
+ return err;
+
+ return 0;
+}
+
+int drm_tegra_pushbuf_sync(struct drm_tegra_pushbuf *pushbuf,
+ unsigned int index, unsigned int value,
+ enum drm_tegra_sync_cond cond)
+{
+ struct drm_tegra_fence fence;
+ int err;
+
+ if (cond >= DRM_TEGRA_SYNC_COND_MAX)
return -EINVAL;
*pushbuf->ptr++ = HOST1X_OPCODE_NONINCR(0x0, 0x1);
- *pushbuf->ptr++ = cond << 8 | priv->job->syncpt;
- priv->job->increments++;
+ *pushbuf->ptr++ = cond;
+
+ memset(&fence, 0, sizeof(fence));
+ fence.flags = DRM_TEGRA_FENCE_EMIT;
+ fence.offset = drm_tegra_pushbuf_get_offset(pushbuf) - 4;
+ fence.index = index;
+ fence.value = value;
+
+ err = drm_tegra_pushbuf_add_fence(pushbuf, &fence);
+ if (err < 0)
+ return err;
return 0;
}
diff --git a/tegra/tegra.c b/tegra/tegra.c
index 78f2fcfd..082a17fd 100644
--- a/tegra/tegra.c
+++ b/tegra/tegra.c
@@ -206,8 +206,8 @@ int drm_tegra_bo_map(struct drm_tegra_bo *bo, void **ptr)
bo->offset = args.offset;
- bo->map = mmap(0, bo->size, PROT_READ | PROT_WRITE, MAP_SHARED,
- drm->fd, bo->offset);
+ bo->map = drm_mmap(NULL, bo->size, PROT_READ | PROT_WRITE, MAP_SHARED,
+ drm->fd, bo->offset);
if (bo->map == MAP_FAILED) {
bo->map = NULL;
return -errno;
@@ -235,96 +235,3 @@ int drm_tegra_bo_unmap(struct drm_tegra_bo *bo)
return 0;
}
-
-int drm_tegra_bo_get_flags(struct drm_tegra_bo *bo, uint32_t *flags)
-{
- struct drm_tegra_gem_get_flags args;
- struct drm_tegra *drm = bo->drm;
- int err;
-
- if (!bo)
- return -EINVAL;
-
- memset(&args, 0, sizeof(args));
- args.handle = bo->handle;
-
- err = drmCommandWriteRead(drm->fd, DRM_TEGRA_GEM_GET_FLAGS, &args,
- sizeof(args));
- if (err < 0)
- return -errno;
-
- if (flags)
- *flags = args.flags;
-
- return 0;
-}
-
-int drm_tegra_bo_set_flags(struct drm_tegra_bo *bo, uint32_t flags)
-{
- struct drm_tegra_gem_get_flags args;
- struct drm_tegra *drm = bo->drm;
- int err;
-
- if (!bo)
- return -EINVAL;
-
- memset(&args, 0, sizeof(args));
- args.handle = bo->handle;
- args.flags = flags;
-
- err = drmCommandWriteRead(drm->fd, DRM_TEGRA_GEM_SET_FLAGS, &args,
- sizeof(args));
- if (err < 0)
- return -errno;
-
- return 0;
-}
-
-int drm_tegra_bo_get_tiling(struct drm_tegra_bo *bo,
- struct drm_tegra_bo_tiling *tiling)
-{
- struct drm_tegra_gem_get_tiling args;
- struct drm_tegra *drm = bo->drm;
- int err;
-
- if (!bo)
- return -EINVAL;
-
- memset(&args, 0, sizeof(args));
- args.handle = bo->handle;
-
- err = drmCommandWriteRead(drm->fd, DRM_TEGRA_GEM_GET_TILING, &args,
- sizeof(args));
- if (err < 0)
- return -errno;
-
- if (tiling) {
- tiling->mode = args.mode;
- tiling->value = args.value;
- }
-
- return 0;
-}
-
-int drm_tegra_bo_set_tiling(struct drm_tegra_bo *bo,
- const struct drm_tegra_bo_tiling *tiling)
-{
- struct drm_tegra_gem_set_tiling args;
- struct drm_tegra *drm = bo->drm;
- int err;
-
- if (!bo)
- return -EINVAL;
-
- memset(&args, 0, sizeof(args));
- args.handle = bo->handle;
- args.mode = tiling->mode;
- args.value = tiling->value;
-
- err = drmCommandWriteRead(drm->fd, DRM_TEGRA_GEM_SET_TILING, &args,
- sizeof(args));
- if (err < 0)
- return -errno;
-
- return 0;
-}
diff --git a/tegra/tegra.h b/tegra/tegra.h
index 01adc5fd..c8576751 100644
--- a/tegra/tegra.h
+++ b/tegra/tegra.h
@@ -31,10 +31,24 @@
#include <tegra_drm.h>
enum drm_tegra_class {
+ DRM_TEGRA_HOST1X,
DRM_TEGRA_GR2D,
DRM_TEGRA_GR3D,
};
+enum drm_fence_type {
+ DRM_FENCE_SYNCOBJ,
+ DRM_FENCE_FD,
+};
+
+struct drm_fence {
+ enum drm_fence_type type;
+ union {
+ uint32_t handle;
+ int fd;
+ } fence;
+};
+
struct drm_tegra_bo;
struct drm_tegra;
@@ -51,19 +65,6 @@ 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);
-int drm_tegra_bo_get_flags(struct drm_tegra_bo *bo, uint32_t *flags);
-int drm_tegra_bo_set_flags(struct drm_tegra_bo *bo, uint32_t flags);
-
-struct drm_tegra_bo_tiling {
- uint32_t mode;
- uint32_t value;
-};
-
-int drm_tegra_bo_get_tiling(struct drm_tegra_bo *bo,
- struct drm_tegra_bo_tiling *tiling);
-int drm_tegra_bo_set_tiling(struct drm_tegra_bo *bo,
- const struct drm_tegra_bo_tiling *tiling);
-
struct drm_tegra_channel;
struct drm_tegra_job;
@@ -71,26 +72,30 @@ 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,
+enum drm_tegra_sync_cond {
+ DRM_TEGRA_SYNC_COND_IMMEDIATE,
+ DRM_TEGRA_SYNC_COND_OP_DONE,
+ DRM_TEGRA_SYNC_COND_RD_DONE,
+ DRM_TEGRA_SYNC_COND_WR_SAFE,
+ DRM_TEGRA_SYNC_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);
+unsigned int drm_tegra_channel_get_syncpoints(struct drm_tegra_channel *channel);
+
+int drm_tegra_fence_wait(struct drm_tegra *drm, struct drm_tegra_fence *fence);
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_job_submit(struct drm_tegra_job *job, unsigned long timeout);
+unsigned int drm_tegra_job_get_fences(struct drm_tegra_job *job,
+ struct drm_fence *fences,
+ unsigned int count);
+int drm_tegra_job_wait(struct drm_tegra_job *job);
int drm_tegra_pushbuf_new(struct drm_tegra_pushbuf **pushbufp,
struct drm_tegra_job *job);
@@ -101,12 +106,11 @@ 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_wait_fd(struct drm_tegra_pushbuf *pushbuf, int fd);
+int drm_tegra_pushbuf_wait_syncobj(struct drm_tegra_pushbuf *pushbuf,
+ uint32_t syncobj);
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);
+ unsigned int index, unsigned int value,
+ enum drm_tegra_sync_cond cond);
#endif /* __DRM_TEGRA_H__ */
diff --git a/tests/tegra/drm-test-tegra.c b/tests/tegra/drm-test-tegra.c
index f5b07de5..0c5a9b80 100644
--- a/tests/tegra/drm-test-tegra.c
+++ b/tests/tegra/drm-test-tegra.c
@@ -69,7 +69,6 @@ int drm_tegra_gr2d_fill(struct drm_tegra_gr2d *gr2d, struct drm_framebuffer *fb,
{
struct drm_tegra_bo *fbo = fb->data;
struct drm_tegra_pushbuf *pushbuf;
- struct drm_tegra_fence *fence;
struct drm_tegra_job *job;
int err;
@@ -117,19 +116,18 @@ int drm_tegra_gr2d_fill(struct drm_tegra_gr2d *gr2d, struct drm_framebuffer *fb,
*pushbuf->ptr++ = height << 16 | width;
*pushbuf->ptr++ = y << 16 | x;
- err = drm_tegra_job_submit(job, &fence);
+ err = drm_tegra_job_submit(job, 1000);
if (err < 0) {
fprintf(stderr, "failed to submit job: %d\n", err);
return err;
}
- err = drm_tegra_fence_wait(fence);
+ err = drm_tegra_job_wait(job);
if (err < 0) {
fprintf(stderr, "failed to wait for fence: %d\n", err);
return err;
}
- drm_tegra_fence_free(fence);
drm_tegra_pushbuf_free(pushbuf);
drm_tegra_job_free(job);
diff --git a/tests/tegra/host1x.h b/tests/tegra/host1x.h
new file mode 100644
index 00000000..902b0c12
--- /dev/null
+++ b/tests/tegra/host1x.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright © 2018 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.
+ */
+
+#ifndef HOST1X_H
+#define HOST1X_H
+
+#define HOST1X_OPCODE_SETCL(offset, classid, mask) \
+ ((0x0 << 28) | (((offset) & 0xfff) << 16) | (((classid) & 0x3ff) << 6) | ((mask) & 0x3f))
+
+#define HOST1X_OPCODE_INCR(offset, count) \
+ ((0x1 << 28) | (((offset) & 0xfff) << 16) | ((count) & 0xffff))
+
+#define HOST1X_CLASS_VIC 0x5d
+
+#endif