Patchwork [RFC,libdrm] Add NVIDIA Tegra support

login
register
mail settings
Submitter Thierry Reding
Date Dec. 4, 2012, 3:13 p.m.
Message ID <1354634032-9986-2-git-send-email-thierry.reding@avionic-design.de>
Download mbox | patch
Permalink /patch/203678/
State Not Applicable, archived
Headers show

Comments

Thierry Reding - Dec. 4, 2012, 3:13 p.m.
Add the libdrm_tegra helper library to encapsulate Tegra-specific
interfaces to the DRM.

Furthermore, Tegra is added to the list of supported chips in the
modetest and vbltest programs.

Signed-off-by: Thierry Reding <thierry.reding@avionic-design.de>
---
 Makefile.am               |   6 +-
 configure.ac              |  15 ++-
 include/drm/Makefile.am   |   1 +
 include/drm/tegra_drm.h   |  48 ++++++++++
 tegra/Makefile.am         |  17 ++++
 tegra/libdrm_tegra.pc.in  |  11 +++
 tegra/tegra.c             | 227 ++++++++++++++++++++++++++++++++++++++++++++++
 tegra/tegra.h             |  51 +++++++++++
 tests/modetest/modetest.c |   2 +-
 tests/vbltest/vbltest.c   |   2 +-
 10 files changed, 376 insertions(+), 4 deletions(-)
 create mode 100644 include/drm/tegra_drm.h
 create mode 100644 tegra/Makefile.am
 create mode 100644 tegra/libdrm_tegra.pc.in
 create mode 100644 tegra/tegra.c
 create mode 100644 tegra/tegra.h
Rob Clark - Dec. 4, 2012, 3:28 p.m.
On Tue, Dec 4, 2012 at 9:13 AM, Thierry Reding
<thierry.reding@avionic-design.de> wrote:
> +int drm_tegra_bo_new(struct drm_tegra *device, uint32_t flags, uint32_t size,
> +                    struct drm_tegra_bo **bop)
> +{
> +       struct drm_tegra_gem_create args;
> +       struct drm_tegra_bo *bo;
> +       struct tegra_bo *priv;
> +       int err;
> +
> +       if (!device || size == 0 || !bop)
> +               return -EINVAL;
> +
> +       bo = calloc(1, sizeof(*bo));
> +       if (!bo)
> +               return -ENOMEM;
> +
> +       priv = tegra_bo(bo);
> +
> +       DRMLISTINITHEAD(&priv->list);
> +       atomic_set(&priv->ref, 1);
> +       bo->device = device;
> +       bo->flags = flags;
> +       bo->size = size;
> +
> +       memset(&args, 0, sizeof(args));
> +       args.flags = flags;
> +       args.size = size;
> +
> +       err = drmCommandWriteRead(device->fd, DRM_TEGRA_GEM_CREATE, &args,
> +                                 sizeof(args));
> +       if (err < 0) {
> +               err = -errno;
> +               free(bo);
> +               return err;
> +       }
> +
> +       DRMLISTADD(&priv->list, &device->bo_list);
> +       bo->handle = args.handle;
> +       bo->offset = args.offset;

btw, x11 can rapidly create/destroy temporary pixmaps.. which don't
necessarily need userspace access.  You might prefer to avoid creating
mmap offset on GEM bo creation, and instead do this only if userspace
needs to mmap the bo

BR,
-R

> +
> +       *bop = bo;
> +
> +       return 0;
> +}
--
To unsubscribe from this list: send the line "unsubscribe linux-tegra" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Thierry Reding - Dec. 4, 2012, 3:38 p.m.
On Tue, Dec 04, 2012 at 09:28:25AM -0600, Rob Clark wrote:
> On Tue, Dec 4, 2012 at 9:13 AM, Thierry Reding
> <thierry.reding@avionic-design.de> wrote:
> > +int drm_tegra_bo_new(struct drm_tegra *device, uint32_t flags, uint32_t size,
> > +                    struct drm_tegra_bo **bop)
> > +{
> > +       struct drm_tegra_gem_create args;
> > +       struct drm_tegra_bo *bo;
> > +       struct tegra_bo *priv;
> > +       int err;
> > +
> > +       if (!device || size == 0 || !bop)
> > +               return -EINVAL;
> > +
> > +       bo = calloc(1, sizeof(*bo));
> > +       if (!bo)
> > +               return -ENOMEM;
> > +
> > +       priv = tegra_bo(bo);
> > +
> > +       DRMLISTINITHEAD(&priv->list);
> > +       atomic_set(&priv->ref, 1);
> > +       bo->device = device;
> > +       bo->flags = flags;
> > +       bo->size = size;
> > +
> > +       memset(&args, 0, sizeof(args));
> > +       args.flags = flags;
> > +       args.size = size;
> > +
> > +       err = drmCommandWriteRead(device->fd, DRM_TEGRA_GEM_CREATE, &args,
> > +                                 sizeof(args));
> > +       if (err < 0) {
> > +               err = -errno;
> > +               free(bo);
> > +               return err;
> > +       }
> > +
> > +       DRMLISTADD(&priv->list, &device->bo_list);
> > +       bo->handle = args.handle;
> > +       bo->offset = args.offset;
> 
> btw, x11 can rapidly create/destroy temporary pixmaps.. which don't
> necessarily need userspace access.  You might prefer to avoid creating
> mmap offset on GEM bo creation, and instead do this only if userspace
> needs to mmap the bo

Ah, so that's the reason for the MMAP IOCTL provided by other DRMs. Yes,
that might be better in the long run. For now I don't think it makes
much of a difference since the GEM objects are backed by CMA, and
therefore the offset will be created along with the GEM anyway.

With Terje's upcoming rework that handles all the allocations in host1x
this should become more important, especially when the mapping is done
through the Tegra30's IOMMU.

I'll rework that. Thanks for the quick reply.

Thierry
Arto Merilainen - Dec. 5, 2012, 7:39 a.m.
On 12/04/2012 05:13 PM, Thierry Reding wrote:
> +int drm_tegra_open(const char *path, struct drm_tegra **devicep)
> +{
> +       struct drm_tegra *device;
> +       int err;
> +
> +       if (!path || !devicep)
> +               return -EINVAL;
> +
> +       device = calloc(1, sizeof(*device));
> +       if (!device)
> +               return -ENOMEM;
> +
> +       DRMINITLISTHEAD(&device->bo_list);
> +
> +       device->fd = open(path, O_RDWR);
> +       if (device->fd < 0) {
> +               err = -errno;
> +               free(device);
> +               return err;
> +       }
> +
> +       *devicep = device;
> +
> +       return 0;
> +}

I think you shouldn't ask the path from the application (=DDX) here, but 
use drmOpen() that automatically finds the correct device for you.

I'd also prefer letting the application open and close the device and 
modify drm_tegra_open() to take the fd as a parameter. That way the DDX 
could easily access also all generic libdrm functions.

- Arto
--
To unsubscribe from this list: send the line "unsubscribe linux-tegra" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Thierry Reding - Dec. 5, 2012, 7:46 a.m.
On Wed, Dec 05, 2012 at 09:39:11AM +0200, Arto Merilainen wrote:
> On 12/04/2012 05:13 PM, Thierry Reding wrote:
> >+int drm_tegra_open(const char *path, struct drm_tegra **devicep)
> >+{
> >+       struct drm_tegra *device;
> >+       int err;
> >+
> >+       if (!path || !devicep)
> >+               return -EINVAL;
> >+
> >+       device = calloc(1, sizeof(*device));
> >+       if (!device)
> >+               return -ENOMEM;
> >+
> >+       DRMINITLISTHEAD(&device->bo_list);
> >+
> >+       device->fd = open(path, O_RDWR);
> >+       if (device->fd < 0) {
> >+               err = -errno;
> >+               free(device);
> >+               return err;
> >+       }
> >+
> >+       *devicep = device;
> >+
> >+       return 0;
> >+}
> 
> I think you shouldn't ask the path from the application (=DDX) here,
> but use drmOpen() that automatically finds the correct device for
> you.
> 
> I'd also prefer letting the application open and close the device
> and modify drm_tegra_open() to take the fd as a parameter. That way
> the DDX could easily access also all generic libdrm functions.

Good points, I'll take those into account.

Thanks,
Thierry

Patch

diff --git a/Makefile.am b/Makefile.am
index 8ecd9d9..e90ae43 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -49,7 +49,11 @@  if HAVE_EXYNOS
 EXYNOS_SUBDIR = exynos
 endif
 
-SUBDIRS = . $(LIBKMS_SUBDIR) $(INTEL_SUBDIR) $(NOUVEAU_SUBDIR) $(RADEON_SUBDIR) $(OMAP_SUBDIR) $(EXYNOS_SUBDIR) tests include man
+if HAVE_TEGRA
+TEGRA_SUBDIR = tegra
+endif
+
+SUBDIRS = . $(LIBKMS_SUBDIR) $(INTEL_SUBDIR) $(NOUVEAU_SUBDIR) $(RADEON_SUBDIR) $(OMAP_SUBDIR) $(EXYNOS_SUBDIR) $(TEGRA_SUBDIR) tests include man
 
 libdrm_la_LTLIBRARIES = libdrm.la
 libdrm_ladir = $(libdir)
diff --git a/configure.ac b/configure.ac
index 0c19929..72d6dfa 100644
--- a/configure.ac
+++ b/configure.ac
@@ -114,6 +114,11 @@  AC_ARG_ENABLE(exynos-experimental-api,
 	      [Enable support for EXYNOS's experimental API (default: disabled)]),
 	      [EXYNOS=$enableval], [EXYNOS=no])
 
+AC_ARG_ENABLE(tegra-experimental-api,
+	      AS_HELP_STRING([--enable-tegra-experimental-api],
+	      [Enable support for Tegra's experimental API (default: disabled)]),
+	      [TEGRA=$enableval], [TEGRA=no])
+
 dnl ===========================================================================
 dnl check compiler flags
 AC_DEFUN([LIBDRM_CC_TRY_FLAG], [
@@ -222,6 +227,11 @@  if test "x$EXYNOS" = xyes; then
 	AC_DEFINE(HAVE_EXYNOS, 1, [Have EXYNOS support])
 fi
 
+AM_CONDITIONAL(HAVE_TEGRA, [test "x$TEGRA" = xyes])
+if test "x$TEGRA" = xyes; then
+	AC_DEFINE(HAVE_TEGRA, 1, [Have Tegra support])
+fi
+
 AC_ARG_ENABLE([cairo-tests],
               [AS_HELP_STRING([--enable-cairo-tests],
                               [Enable support for Cairo rendering in tests (default: auto)])],
@@ -247,7 +257,7 @@  if test "x$HAVE_LIBUDEV" = xyes; then
 fi
 AM_CONDITIONAL(HAVE_LIBUDEV, [test "x$HAVE_LIBUDEV" = xyes])
 
-if test "x$INTEL" != "xno" -o "x$RADEON" != "xno" -o "x$NOUVEAU" != "xno" -o "x$OMAP" != "xno"; then
+if test "x$INTEL" != "xno" -o "x$RADEON" != "xno" -o "x$NOUVEAU" != "xno" -o "x$OMAP" != "xno" -o "x$TEGRA" != "xno"; then
     # Check for atomic intrinsics
     AC_CACHE_CHECK([for native atomic primitives], drm_cv_atomic_primitives,
     [
@@ -358,6 +368,8 @@  AC_CONFIG_FILES([
 	omap/libdrm_omap.pc
 	exynos/Makefile
 	exynos/libdrm_exynos.pc
+	tegra/Makefile
+	tegra/libdrm_tegra.pc
 	tests/Makefile
 	tests/modeprint/Makefile
 	tests/modetest/Makefile
@@ -380,4 +392,5 @@  echo "  Radeon API     $RADEON"
 echo "  Nouveau API    $NOUVEAU"
 echo "  OMAP API       $OMAP"
 echo "  EXYNOS API     $EXYNOS"
+echo "  Tegra API      $TEGRA"
 echo ""
diff --git a/include/drm/Makefile.am b/include/drm/Makefile.am
index 2923ab4..3e33ed0 100644
--- a/include/drm/Makefile.am
+++ b/include/drm/Makefile.am
@@ -35,6 +35,7 @@  klibdrminclude_HEADERS = \
 	radeon_drm.h \
 	savage_drm.h \
 	sis_drm.h \
+	tegra_drm.h \
 	via_drm.h \
 	mach64_drm.h
 
diff --git a/include/drm/tegra_drm.h b/include/drm/tegra_drm.h
new file mode 100644
index 0000000..eaec602
--- /dev/null
+++ b/include/drm/tegra_drm.h
@@ -0,0 +1,48 @@ 
+/*
+ * Copyright © 2012 Thierry Reding
+ * All Rights Reserved.
+ *
+ * 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
+ * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS 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 __TEGRA_DRM_H__
+#define __TEGRA_DRM_H__
+
+struct drm_tegra_gem_create {
+	uint32_t handle;
+	uint32_t offset;
+	uint32_t flags;
+	uint32_t size;
+};
+
+struct drm_tegra_gem_info {
+	uint32_t handle;
+	uint32_t offset;
+	uint32_t flags;
+	uint32_t size;
+};
+
+#define DRM_TEGRA_GEM_CREATE		0x40
+#define DRM_TEGRA_GEM_INFO		0x41
+
+#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_INFO	DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_GEM_INFO, struct drm_tegra_gem_info)
+
+#endif /* __TEGRA_DRM_H__ */
diff --git a/tegra/Makefile.am b/tegra/Makefile.am
new file mode 100644
index 0000000..65cd628
--- /dev/null
+++ b/tegra/Makefile.am
@@ -0,0 +1,17 @@ 
+AM_CPPFLAGS = \
+	-I$(top_srcdir) \
+	-I$(top_srcdir)/include/drm
+
+libdrm_tegra_ladir = $(libdir)
+libdrm_tegra_la_LTLIBRARIES = libdrm_tegra.la
+libdrm_tegra_la_LDFLAGS = -version-number 0:0:0 -no-undefined
+libdrm_tegra_la_LIBADD = ../libdrm.la @PTHREADSTUBS_LIBS@
+
+libdrm_tegra_la_SOURCES = \
+	tegra.c
+
+libdrm_tegraincludedir = ${includedir}/libdrm
+libdrm_tegrainclude_HEADERS = tegra.h
+
+pkgconfigdir = @pkgconfigdir@
+pkgconfig_DATA = libdrm_tegra.pc
diff --git a/tegra/libdrm_tegra.pc.in b/tegra/libdrm_tegra.pc.in
new file mode 100644
index 0000000..f83c74c
--- /dev/null
+++ b/tegra/libdrm_tegra.pc.in
@@ -0,0 +1,11 @@ 
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: libdrm_tegra
+Description: Userspace interface to Tegra kernel DRM services
+Version: 2.4.40
+Libs: -L${libdir} -ldrm_tegra
+Cflags: -I${includedir} -I${includedir}/libdrm
+Requires.private: libdrm
diff --git a/tegra/tegra.c b/tegra/tegra.c
new file mode 100644
index 0000000..d92eca5
--- /dev/null
+++ b/tegra/tegra.c
@@ -0,0 +1,227 @@ 
+/*
+ * Copyright © 2012 Thierry Reding
+ *
+ * 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 <fcntl.h>
+#include <string.h>
+
+#include <sys/mman.h>
+
+#include <libdrm_lists.h>
+#include <xf86atomic.h>
+#include <xf86drm.h>
+
+#include <tegra_drm.h>
+
+#include "tegra.h"
+
+struct drm_tegra {
+	drmMMListHead bo_list;
+	int fd;
+};
+struct tegra_bo {
+	struct drm_tegra_bo base;
+	drmMMListHead list;
+	atomic_t ref;
+};
+
+static inline struct tegra_bo *tegra_bo(struct drm_tegra_bo *bo)
+{
+	return (struct tegra_bo *)bo;
+}
+
+static void drm_tegra_bo_free(struct drm_tegra_bo *bo)
+{
+	struct tegra_bo *priv = tegra_bo(bo);
+	struct drm_gem_close args;
+
+	DRMLISTDEL(&priv->list);
+
+	if (bo->map)
+		munmap(bo->map, bo->size);
+
+	memset(&args, 0, sizeof(args));
+	args.handle = bo->handle;
+
+	drmIoctl(bo->device->fd, DRM_IOCTL_GEM_CLOSE, &args);
+
+	free(bo);
+}
+
+int drm_tegra_open(const char *path, struct drm_tegra **devicep)
+{
+	struct drm_tegra *device;
+	int err;
+
+	if (!path || !devicep)
+		return -EINVAL;
+
+	device = calloc(1, sizeof(*device));
+	if (!device)
+		return -ENOMEM;
+
+	DRMINITLISTHEAD(&device->bo_list);
+
+	device->fd = open(path, O_RDWR);
+	if (device->fd < 0) {
+		err = -errno;
+		free(device);
+		return err;
+	}
+
+	*devicep = device;
+
+	return 0;
+}
+
+void drm_tegra_close(struct drm_tegra *device)
+{
+	if (device) {
+		close(device->fd);
+		free(device);
+	}
+}
+
+int drm_tegra_bo_new(struct drm_tegra *device, uint32_t flags, uint32_t size,
+		     struct drm_tegra_bo **bop)
+{
+	struct drm_tegra_gem_create args;
+	struct drm_tegra_bo *bo;
+	struct tegra_bo *priv;
+	int err;
+
+	if (!device || size == 0 || !bop)
+		return -EINVAL;
+
+	bo = calloc(1, sizeof(*bo));
+	if (!bo)
+		return -ENOMEM;
+
+	priv = tegra_bo(bo);
+
+	DRMLISTINITHEAD(&priv->list);
+	atomic_set(&priv->ref, 1);
+	bo->device = device;
+	bo->flags = flags;
+	bo->size = size;
+
+	memset(&args, 0, sizeof(args));
+	args.flags = flags;
+	args.size = size;
+
+	err = drmCommandWriteRead(device->fd, DRM_TEGRA_GEM_CREATE, &args,
+				  sizeof(args));
+	if (err < 0) {
+		err = -errno;
+		free(bo);
+		return err;
+	}
+
+	DRMLISTADD(&priv->list, &device->bo_list);
+	bo->handle = args.handle;
+	bo->offset = args.offset;
+
+	*bop = bo;
+
+	return 0;
+}
+
+int drm_tegra_bo_open(struct drm_tegra *device, uint32_t handle,
+		      struct drm_tegra_bo **bop)
+{
+	struct drm_tegra_gem_info args;
+	struct drm_tegra_bo *bo;
+	struct tegra_bo *priv;
+	int err;
+
+	if (!device || !bop)
+		return -EINVAL;
+
+	bo = calloc(1, sizeof(*bo));
+	if (!bo)
+		return -ENOMEM;
+
+	priv = tegra_bo(bo);
+
+	DRMLISTINITHEAD(&priv->list);
+	atomic_set(&priv->ref, 1);
+	bo->device = device;
+
+	memset(&args, 0, sizeof(args));
+	args.handle = handle;
+
+	err = drmCommandWriteRead(device->fd, DRM_TEGRA_GEM_INFO, &args,
+				  sizeof(args));
+	if (err < 0) {
+		err = -errno;
+		free(bo);
+		return err;
+	}
+
+	DRMLISTADD(&priv->list, &device->bo_list);
+	bo->handle = args.handle;
+	bo->offset = args.offset;
+	bo->flags = args.flags;
+	bo->size = args.size;
+
+	*bop = bo;
+
+	return 0;
+}
+
+struct drm_tegra_bo *drm_tegra_bo_get(struct drm_tegra_bo *bo)
+{
+	if (bo) {
+		struct tegra_bo *priv = tegra_bo(bo);
+		atomic_inc(&priv->ref);
+	}
+
+	return bo;
+}
+
+void drm_tegra_bo_put(struct drm_tegra_bo *bo)
+{
+	if (bo) {
+		struct tegra_bo *priv = tegra_bo(bo);
+
+		if (atomic_dec_and_test(&priv->ref))
+			drm_tegra_bo_free(bo);
+	}
+}
+
+int drm_tegra_bo_map(struct drm_tegra_bo *bo)
+{
+	if (!bo->map) {
+		bo->map = mmap(0, bo->size, PROT_READ | PROT_WRITE,
+			       MAP_SHARED, bo->device->fd, bo->offset);
+		if (bo->map == MAP_FAILED) {
+			bo->map = NULL;
+			return -errno;
+		}
+	}
+
+	return 0;
+}
diff --git a/tegra/tegra.h b/tegra/tegra.h
new file mode 100644
index 0000000..619090c
--- /dev/null
+++ b/tegra/tegra.h
@@ -0,0 +1,51 @@ 
+/*
+ * Copyright © 2012 Thierry Reding
+ *
+ * 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 __DRM_TEGRA_H__
+#define __DRM_TEGRA_H__ 1
+
+#include <stdint.h>
+#include <stdlib.h>
+
+struct drm_tegra;
+
+struct drm_tegra_bo {
+	struct drm_tegra *device;
+	uint32_t handle;
+	uint32_t offset;
+	uint32_t flags;
+	uint32_t size;
+	void *map;
+};
+
+int drm_tegra_open(const char *path, struct drm_tegra **devicep);
+void drm_tegra_close(struct drm_tegra *device);
+
+int drm_tegra_bo_new(struct drm_tegra *device, uint32_t flags, uint32_t size,
+		     struct drm_tegra_bo **bop);
+int drm_tegra_bo_open(struct drm_tegra *device, uint32_t handle,
+		      struct drm_tegra_bo **bop);
+int drm_tegra_bo_map(struct drm_tegra_bo *bo);
+struct drm_tegra_bo *drm_tegra_bo_get(struct drm_tegra_bo *bo);
+void drm_tegra_bo_put(struct drm_tegra_bo *bo);
+
+#endif /* __DRM_TEGRA_H__ */
diff --git a/tests/modetest/modetest.c b/tests/modetest/modetest.c
index c91bb9d..913ede8 100644
--- a/tests/modetest/modetest.c
+++ b/tests/modetest/modetest.c
@@ -939,7 +939,7 @@  int main(int argc, char **argv)
 	int c;
 	int encoders = 0, connectors = 0, crtcs = 0, planes = 0, framebuffers = 0;
 	int test_vsync = 0;
-	char *modules[] = { "i915", "radeon", "nouveau", "vmwgfx", "omapdrm", "exynos" };
+	char *modules[] = { "i915", "radeon", "nouveau", "vmwgfx", "omapdrm", "exynos", "tegra" };
 	unsigned int i;
 	int count = 0, plane_count = 0;
 	struct connector con_args[2];
diff --git a/tests/vbltest/vbltest.c b/tests/vbltest/vbltest.c
index 4fccd59..22a5339 100644
--- a/tests/vbltest/vbltest.c
+++ b/tests/vbltest/vbltest.c
@@ -103,7 +103,7 @@  static void usage(char *name)
 int main(int argc, char **argv)
 {
 	int i, c, fd, ret;
-	char *modules[] = { "i915", "radeon", "nouveau", "vmwgfx", "exynos" };
+	char *modules[] = { "i915", "radeon", "nouveau", "vmwgfx", "exynos", "tegra" };
 	drmVBlank vbl;
 	drmEventContext evctx;
 	struct vbl_info handler_info;