diff mbox

[RFC,libdrm,2/6] libdrm: Add NVIDIA Tegra support

Message ID 1392825893-7380-3-git-send-email-thierry.reding@gmail.com (mailing list archive)
State New, archived
Headers show

Commit Message

Thierry Reding Feb. 19, 2014, 4:04 p.m. UTC
From: Thierry Reding <thierry.reding@avionic-design.de>

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>
Signed-off-by: Erik Faye-Lund <kusmabite@gmail.com>
Signed-off-by: Thierry Reding <treding@nvidia.com>
---
 Makefile.am               |   6 +-
 configure.ac              |  15 ++-
 include/drm/Makefile.am   |   1 +
 include/drm/tegra_drm.h   | 157 ++++++++++++++++++++++++++++
 tegra/Makefile.am         |  20 ++++
 tegra/libdrm_tegra.pc.in  |  11 ++
 tegra/private.h           |  58 +++++++++++
 tegra/tegra.c             | 253 ++++++++++++++++++++++++++++++++++++++++++++++
 tegra/tegra.h             |  47 +++++++++
 tests/modetest/modetest.c |   2 +-
 tests/vbltest/vbltest.c   |   2 +-
 11 files changed, 568 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/private.h
 create mode 100644 tegra/tegra.c
 create mode 100644 tegra/tegra.h

Comments

Rémi Cardona Feb. 19, 2014, 7:59 p.m. UTC | #1
Le mercredi 19 février 2014 à 17:04 +0100, Thierry Reding a écrit :
> --- /dev/null
> +++ b/include/drm/tegra_drm.h
> @@ -0,0 +1,157 @@
> +/*
> + * Copyright (c) 2012-2013, NVIDIA CORPORATION.  All rights reserved.
                               ^^^^^^
[...]
> + * 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 NON-INFRINGEMENT.
> + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
                        ^^^^^^^^^^^^^^^^^

So whose code is this? Wouldn't it be better to say "the above copyright
owners" instead?

Other than that, I have no valuable review to offer.

Cheers,

Rémi
Erik Faye-Lund Feb. 19, 2014, 8:03 p.m. UTC | #2
On Wed, Feb 19, 2014 at 5:04 PM, Thierry Reding
<thierry.reding@gmail.com> wrote:
> +#ifndef __DRM_TEGRA_PRIVATE_H__
> +#define __DRM_TEGRA_PRIVATE_H__ 1
> +
> +#include <stdbool.h>
> +#include <stdint.h>
> +
> +#include <xf86atomic.h>
> +
> +#include "tegra.h"
> +
> +#if defined(HAVE_VISIBILITY)
> +#  define drm_private __attribute__((visibility("hidden")))
> +#  define drm_public __attribute__((visibility("default")))
> +#else
> +#  define drm_private
> +#  define drm_public
> +#endif
> +

Perhaps you could put this where it's visible to other drivers as
well, like xf86drm.h?
Erik Faye-Lund Feb. 19, 2014, 8:13 p.m. UTC | #3
On Wed, Feb 19, 2014 at 5:04 PM, Thierry Reding
<thierry.reding@gmail.com> wrote:
> diff --git a/tegra/Makefile.am b/tegra/Makefile.am
> new file mode 100644
> index 000000000000..1b83145b120d
> --- /dev/null
> +++ b/tegra/Makefile.am
> @@ -0,0 +1,20 @@
> +AM_CPPFLAGS = \
> +       -I$(top_srcdir) \
> +       -I$(top_srcdir)/include/drm
> +
> +AM_CFLAGS = \
> +       $(VISIBILITY_CFLAGS)
> +
> +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

You should probably also add libdrm_tegra.pc to .gitignore also.
Thierry Reding Feb. 19, 2014, 9:32 p.m. UTC | #4
On Wed, Feb 19, 2014 at 09:13:31PM +0100, Erik Faye-Lund wrote:
> On Wed, Feb 19, 2014 at 5:04 PM, Thierry Reding
> <thierry.reding@gmail.com> wrote:
> > diff --git a/tegra/Makefile.am b/tegra/Makefile.am
> > new file mode 100644
> > index 000000000000..1b83145b120d
> > --- /dev/null
> > +++ b/tegra/Makefile.am
> > @@ -0,0 +1,20 @@
> > +AM_CPPFLAGS = \
> > +       -I$(top_srcdir) \
> > +       -I$(top_srcdir)/include/drm
> > +
> > +AM_CFLAGS = \
> > +       $(VISIBILITY_CFLAGS)
> > +
> > +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
> 
> You should probably also add libdrm_tegra.pc to .gitignore also.

Done. Thanks,
Thierry
Thierry Reding Feb. 19, 2014, 9:33 p.m. UTC | #5
On Wed, Feb 19, 2014 at 09:03:51PM +0100, Erik Faye-Lund wrote:
> On Wed, Feb 19, 2014 at 5:04 PM, Thierry Reding
> <thierry.reding@gmail.com> wrote:
> > +#ifndef __DRM_TEGRA_PRIVATE_H__
> > +#define __DRM_TEGRA_PRIVATE_H__ 1
> > +
> > +#include <stdbool.h>
> > +#include <stdint.h>
> > +
> > +#include <xf86atomic.h>
> > +
> > +#include "tegra.h"
> > +
> > +#if defined(HAVE_VISIBILITY)
> > +#  define drm_private __attribute__((visibility("hidden")))
> > +#  define drm_public __attribute__((visibility("default")))
> > +#else
> > +#  define drm_private
> > +#  define drm_public
> > +#endif
> > +
> 
> Perhaps you could put this where it's visible to other drivers as
> well, like xf86drm.h?

I'd prefer to keep this here for now. We can move it to a more central
location when another module starts using it.

Thierry
diff mbox

Patch

diff --git a/Makefile.am b/Makefile.am
index 826c30d0c0d9..14c402dce74f 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -51,7 +51,11 @@  if HAVE_FREEDRENO
 FREEDRENO_SUBDIR = freedreno
 endif
 
-SUBDIRS = . $(LIBKMS_SUBDIR) $(INTEL_SUBDIR) $(NOUVEAU_SUBDIR) $(RADEON_SUBDIR) $(OMAP_SUBDIR) $(EXYNOS_SUBDIR) $(FREEDRENO_SUBDIR) tests include man
+if HAVE_TEGRA
+TEGRA_SUBDIR = tegra
+endif
+
+SUBDIRS = . $(LIBKMS_SUBDIR) $(INTEL_SUBDIR) $(NOUVEAU_SUBDIR) $(RADEON_SUBDIR) $(OMAP_SUBDIR) $(EXYNOS_SUBDIR) $(FREEDRENO_SUBDIR) $(TEGRA_SUBDIR) tests include man
 
 libdrm_la_LTLIBRARIES = libdrm.la
 libdrm_ladir = $(libdir)
diff --git a/configure.ac b/configure.ac
index 3f4164238494..752a70592933 100644
--- a/configure.ac
+++ b/configure.ac
@@ -98,6 +98,11 @@  AC_ARG_ENABLE(freedreno-experimental-api,
 	      [Enable support for freedreno's experimental API (default: disabled)]),
 	      [FREEDRENO=$enableval], [FREEDRENO=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])
+
 AC_ARG_ENABLE(install-test-programs,
 		  AS_HELP_STRING([--enable-install-test-programs],
 		  [Install test programs (default: no)]),
@@ -218,6 +223,11 @@  if test "x$FREEDRENO" = xyes; then
 	AC_DEFINE(HAVE_FREEDRENO, 1, [Have freedreno 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
+
 AM_CONDITIONAL(HAVE_INSTALL_TESTS, [test "x$INSTALL_TESTS" = xyes])
 if test "x$INSTALL_TESTS" = xyes; then
 	AC_DEFINE(HAVE_INSTALL_TESTS, 1, [Install test programs])
@@ -269,7 +279,7 @@  else
 fi
 AM_CONDITIONAL([HAVE_MANPAGES_STYLESHEET], [test "x$HAVE_MANPAGES_STYLESHEET" = "xyes"])
 
-if test "x$INTEL" != "xno" -o "x$RADEON" != "xno" -o "x$NOUVEAU" != "xno" -o "x$OMAP" != "xno" -o "x$FREEDRENO" != "xno"; then
+if test "x$INTEL" != "xno" -o "x$RADEON" != "xno" -o "x$NOUVEAU" != "xno" -o "x$OMAP" != "xno" -o "x$FREEDRENO" != "xno" -o "x$TEGRA" != "xno"; then
     # Check for atomic intrinsics
     AC_CACHE_CHECK([for native atomic primitives], drm_cv_atomic_primitives,
     [
@@ -402,6 +412,8 @@  AC_CONFIG_FILES([
 	exynos/libdrm_exynos.pc
 	freedreno/Makefile
 	freedreno/libdrm_freedreno.pc
+	tegra/Makefile
+	tegra/libdrm_tegra.pc
 	tests/Makefile
 	tests/modeprint/Makefile
 	tests/modetest/Makefile
@@ -426,4 +438,5 @@  echo "  Nouveau API    $NOUVEAU"
 echo "  OMAP API       $OMAP"
 echo "  EXYNOS API     $EXYNOS"
 echo "  Freedreno API  $FREEDRENO"
+echo "  Tegra API      $TEGRA"
 echo ""
diff --git a/include/drm/Makefile.am b/include/drm/Makefile.am
index 2bc34d2ffd9f..f591abc45152 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 \
 	qxl_drm.h
diff --git a/include/drm/tegra_drm.h b/include/drm/tegra_drm.h
new file mode 100644
index 000000000000..956ed8aa9d98
--- /dev/null
+++ b/include/drm/tegra_drm.h
@@ -0,0 +1,157 @@ 
+/*
+ * Copyright (c) 2012-2013, NVIDIA CORPORATION.  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, sub license, 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 NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS 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 _UAPI_TEGRA_DRM_H_
+#define _UAPI_TEGRA_DRM_H_
+
+#include <drm/drm.h>
+
+#define DRM_TEGRA_GEM_CREATE_TILED     (1 << 0)
+#define DRM_TEGRA_GEM_CREATE_BOTTOM_UP (1 << 1)
+
+struct drm_tegra_gem_create {
+	__u64 size;
+	__u32 flags;
+	__u32 handle;
+};
+
+struct drm_tegra_gem_mmap {
+	__u32 handle;
+	__u32 offset;
+};
+
+struct drm_tegra_syncpt_read {
+	__u32 id;
+	__u32 value;
+};
+
+struct drm_tegra_syncpt_incr {
+	__u32 id;
+	__u32 pad;
+};
+
+struct drm_tegra_syncpt_wait {
+	__u32 id;
+	__u32 thresh;
+	__u32 timeout;
+	__u32 value;
+};
+
+#define DRM_TEGRA_NO_TIMEOUT	(0xffffffff)
+
+struct drm_tegra_open_channel {
+	__u32 client;
+	__u32 pad;
+	__u64 context;
+};
+
+struct drm_tegra_close_channel {
+	__u64 context;
+};
+
+struct drm_tegra_get_syncpt {
+	__u64 context;
+	__u32 index;
+	__u32 id;
+};
+
+struct drm_tegra_get_syncpt_base {
+	__u64 context;
+	__u32 syncpt;
+	__u32 id;
+};
+
+struct drm_tegra_syncpt {
+	__u32 id;
+	__u32 incrs;
+};
+
+struct drm_tegra_cmdbuf {
+	__u32 handle;
+	__u32 offset;
+	__u32 words;
+	__u32 pad;
+};
+
+struct drm_tegra_reloc {
+	struct {
+		__u32 handle;
+		__u32 offset;
+	} cmdbuf;
+	struct {
+		__u32 handle;
+		__u32 offset;
+	} target;
+	__u32 shift;
+	__u32 pad;
+};
+
+struct drm_tegra_waitchk {
+	__u32 handle;
+	__u32 offset;
+	__u32 syncpt;
+	__u32 thresh;
+};
+
+struct drm_tegra_submit {
+	__u64 context;
+	__u32 num_syncpts;
+	__u32 num_cmdbufs;
+	__u32 num_relocs;
+	__u32 num_waitchks;
+	__u32 waitchk_mask;
+	__u32 timeout;
+	__u32 pad;
+	__u64 syncpts;
+	__u64 cmdbufs;
+	__u64 relocs;
+	__u64 waitchks;
+	__u32 fence;		/* Return value */
+
+	__u32 reserved[5];	/* 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_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_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)
+
+#endif
diff --git a/tegra/Makefile.am b/tegra/Makefile.am
new file mode 100644
index 000000000000..1b83145b120d
--- /dev/null
+++ b/tegra/Makefile.am
@@ -0,0 +1,20 @@ 
+AM_CPPFLAGS = \
+	-I$(top_srcdir) \
+	-I$(top_srcdir)/include/drm
+
+AM_CFLAGS = \
+	$(VISIBILITY_CFLAGS)
+
+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 000000000000..2e06f49c6fba
--- /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: @PACKAGE_VERSION@
+Libs: -L${libdir} -ldrm_tegra
+Cflags: -I${includedir} -I${includedir}/libdrm
+Requires.private: libdrm
diff --git a/tegra/private.h b/tegra/private.h
new file mode 100644
index 000000000000..ec69295c2cf8
--- /dev/null
+++ b/tegra/private.h
@@ -0,0 +1,58 @@ 
+/*
+ * 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.
+ */
+
+#ifndef __DRM_TEGRA_PRIVATE_H__
+#define __DRM_TEGRA_PRIVATE_H__ 1
+
+#include <stdbool.h>
+#include <stdint.h>
+
+#include <xf86atomic.h>
+
+#include "tegra.h"
+
+#if defined(HAVE_VISIBILITY)
+#  define drm_private __attribute__((visibility("hidden")))
+#  define drm_public __attribute__((visibility("default")))
+#else
+#  define drm_private
+#  define drm_public
+#endif
+
+struct drm_tegra {
+	bool close;
+	int fd;
+};
+
+struct drm_tegra_bo {
+	struct drm_tegra *drm;
+	uint32_t handle;
+	uint32_t offset;
+	uint32_t flags;
+	uint32_t size;
+	atomic_t ref;
+	void *map;
+};
+
+#endif /* __DRM_TEGRA_PRIVATE_H__ */
diff --git a/tegra/tegra.c b/tegra/tegra.c
new file mode 100644
index 000000000000..8c48ae7c30a1
--- /dev/null
+++ b/tegra/tegra.c
@@ -0,0 +1,253 @@ 
+/*
+ * 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 <fcntl.h>
+#include <string.h>
+
+#include <sys/mman.h>
+
+#include <xf86drm.h>
+
+#include <tegra_drm.h>
+
+#include "private.h"
+
+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 drm_tegra *drm = bo->drm;
+	struct drm_gem_close args;
+
+	if (bo->map)
+		munmap(bo->map, bo->size);
+
+	memset(&args, 0, sizeof(args));
+	args.handle = bo->handle;
+
+	drmIoctl(drm->fd, DRM_IOCTL_GEM_CLOSE, &args);
+
+	free(bo);
+}
+
+static int drm_tegra_wrap(struct drm_tegra **drmp, int fd, bool close)
+{
+	struct drm_tegra *drm;
+	int err;
+
+	if (fd < 0 || !drmp)
+		return -EINVAL;
+
+	drm = calloc(1, sizeof(*drm));
+	if (!drm)
+		return -ENOMEM;
+
+	drm->close = close;
+	drm->fd = fd;
+
+	*drmp = drm;
+
+	return 0;
+}
+
+drm_public
+int drm_tegra_new(struct drm_tegra **drmp, int fd)
+{
+	bool supported = false;
+	drmVersionPtr version;
+
+	version = drmGetVersion(fd);
+	if (!version)
+		return -ENOMEM;
+
+	if (!strncmp(version->name, "tegra", version->name_len))
+		supported = true;
+
+	drmFreeVersion(version);
+
+	if (!supported)
+		return -ENOTSUP;
+
+	return drm_tegra_wrap(drmp, fd, false);
+}
+
+drm_public
+void drm_tegra_close(struct drm_tegra *drm)
+{
+	if (!drm)
+		return;
+
+	if (drm->close)
+		close(drm->fd);
+
+	free(drm);
+}
+
+drm_public
+int drm_tegra_bo_new(struct drm_tegra_bo **bop, struct drm_tegra *drm,
+		     uint32_t flags, uint32_t size)
+{
+	struct drm_tegra_gem_create args;
+	struct drm_tegra_bo *bo;
+	int err;
+
+	if (!drm || size == 0 || !bop)
+		return -EINVAL;
+
+	bo = calloc(1, sizeof(*bo));
+	if (!bo)
+		return -ENOMEM;
+
+	atomic_set(&bo->ref, 1);
+	bo->flags = flags;
+	bo->size = size;
+	bo->drm = drm;
+
+	memset(&args, 0, sizeof(args));
+	args.flags = flags;
+	args.size = size;
+
+	err = drmCommandWriteRead(drm->fd, DRM_TEGRA_GEM_CREATE, &args,
+				  sizeof(args));
+	if (err < 0) {
+		err = -errno;
+		free(bo);
+		return err;
+	}
+
+	bo->handle = args.handle;
+
+	*bop = bo;
+
+	return 0;
+}
+
+drm_public
+int drm_tegra_bo_wrap(struct drm_tegra_bo **bop, struct drm_tegra *drm,
+		      uint32_t handle, uint32_t flags, size_t size)
+{
+	struct drm_tegra_bo *bo;
+
+	if (!drm || !bop)
+		return -EINVAL;
+
+	bo = calloc(1, sizeof(*bo));
+	if (!bo)
+		return -ENOMEM;
+
+	atomic_set(&bo->ref, 1);
+	bo->handle = handle;
+	bo->flags = flags;
+	bo->size = size;
+	bo->drm = drm;
+
+	*bop = bo;
+
+	return 0;
+}
+
+drm_public
+struct drm_tegra_bo *drm_tegra_bo_get(struct drm_tegra_bo *bo)
+{
+	if (bo)
+		atomic_inc(&bo->ref);
+
+	return bo;
+}
+
+drm_public
+void drm_tegra_bo_put(struct drm_tegra_bo *bo)
+{
+	if (bo && atomic_dec_and_test(&bo->ref))
+		drm_tegra_bo_free(bo);
+}
+
+drm_public
+int drm_tegra_bo_get_handle(struct drm_tegra_bo *bo, uint32_t *handle)
+{
+	if (!bo || !handle)
+		return -EINVAL;
+
+	*handle = bo->handle;
+
+	return 0;
+}
+
+drm_public
+int drm_tegra_bo_map(struct drm_tegra_bo *bo, void **ptr)
+{
+	struct drm_tegra *drm = bo->drm;
+
+	if (!bo->map) {
+		struct drm_tegra_gem_mmap args;
+		int err;
+
+		memset(&args, 0, sizeof(args));
+		args.handle = bo->handle;
+
+		err = drmCommandWriteRead(drm->fd, DRM_TEGRA_GEM_MMAP, &args,
+					  sizeof(args));
+		if (err < 0)
+			return -errno;
+
+		bo->offset = args.offset;
+
+		bo->map = mmap(0, bo->size, PROT_READ | PROT_WRITE, MAP_SHARED,
+			       drm->fd, bo->offset);
+		if (bo->map == MAP_FAILED) {
+			bo->map = NULL;
+			return -errno;
+		}
+	}
+
+	if (ptr)
+		*ptr = bo->map;
+
+	return 0;
+}
+
+drm_public
+int drm_tegra_bo_unmap(struct drm_tegra_bo *bo)
+{
+	if (!bo)
+		return -EINVAL;
+
+	if (!bo->map)
+		return 0;
+
+	if (munmap(bo->map, bo->size))
+		return -errno;
+
+	bo->map = NULL;
+
+	return 0;
+}
diff --git a/tegra/tegra.h b/tegra/tegra.h
new file mode 100644
index 000000000000..0731cb3bd4dc
--- /dev/null
+++ b/tegra/tegra.h
@@ -0,0 +1,47 @@ 
+/*
+ * 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.
+ */
+
+#ifndef __DRM_TEGRA_H__
+#define __DRM_TEGRA_H__ 1
+
+#include <stdint.h>
+#include <stdlib.h>
+
+struct drm_tegra_bo;
+struct drm_tegra;
+
+int drm_tegra_new(struct drm_tegra **drmp, int fd);
+void drm_tegra_close(struct drm_tegra *drm);
+
+int drm_tegra_bo_new(struct drm_tegra_bo **bop, struct drm_tegra *drm,
+		     uint32_t flags, uint32_t size);
+int drm_tegra_bo_wrap(struct drm_tegra_bo **bop, struct drm_tegra *drm,
+		      uint32_t handle, uint32_t flags, uint32_t size);
+struct drm_tegra_bo *drm_tegra_bo_get(struct drm_tegra_bo *bo);
+void drm_tegra_bo_put(struct drm_tegra_bo *bo);
+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);
+
+#endif /* __DRM_TEGRA_H__ */
diff --git a/tests/modetest/modetest.c b/tests/modetest/modetest.c
index bc9c9988dec7..4212963f8ff0 100644
--- a/tests/modetest/modetest.c
+++ b/tests/modetest/modetest.c
@@ -1386,7 +1386,7 @@  int main(int argc, char **argv)
 	int encoders = 0, connectors = 0, crtcs = 0, planes = 0, framebuffers = 0;
 	int drop_master = 0;
 	int test_vsync = 0;
-	const char *modules[] = { "i915", "radeon", "nouveau", "vmwgfx", "omapdrm", "exynos", "tilcdc", "msm" };
+	const char *modules[] = { "i915", "radeon", "nouveau", "vmwgfx", "omapdrm", "exynos", "tilcdc", "msm", "tegra" };
 	char *device = NULL;
 	char *module = NULL;
 	unsigned int i;
diff --git a/tests/vbltest/vbltest.c b/tests/vbltest/vbltest.c
index 2a09d28ed00a..e4b200bf0c3c 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", "omapdrm", "tilcdc", "msm" };
+	char *modules[] = { "i915", "radeon", "nouveau", "vmwgfx", "exynos", "omapdrm", "tilcdc", "msm", "tegra" };
 	drmVBlank vbl;
 	drmEventContext evctx;
 	struct vbl_info handler_info;