[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#696665: unblock: libdrm/2.4.40-1~deb7u1 (pre-approval, hw support)



Package: release.debian.org
Severity: normal
User: release.debian.org@packages.debian.org
Usertags: unblock

Hi,

I'm considering an update to libdrm for wheezy, to get newer hw support
on radeon and intel.  Upstream changed the libdrm_nouveau API/ABI in the
mean time, so this update would revert nouveau to the current state in
wheezy (2.4.33-3).

diff below comes from "git diff libdrm-2.4.33-3 | filterdiff -x
'*nouveau*' -x '*tests*' -x '*ChangeLog' -x '*exynos*'"
Excluded files:
- per the above, debian/patches/revert-nouveau-rewrite.diff means
  nouveau doesn't actually change
- exynos is new in this release, but not built; it will be added in
  jessie
- tests and changelog should be self-explanatory

Cheers,
Julien

 b/.gitignore                                            |    4 
 b/Makefile.am                                           |    6 
 b/autogen.sh                                            |    2 
 b/configure.ac                                          |   88 ++-
 b/debian/changelog                                      |   29 +
 b/debian/control                                        |    2 
 b/debian/libdrm-dev.install                             |    1 
 b/debian/libdrm-intel1.symbols                          |    8 
 b/debian/libdrm-omap1.symbols                           |    4 
 b/debian/libdrm-radeon1.symbols                         |    2 
 b/debian/libdrm2.symbols                                |    5 
 b/debian/patches/series                                 |    2 
 b/debian/rules                                          |   16 
 b/include/drm/drm.h                                     |   22 
 b/include/drm/drm_mode.h                                |   25 
 b/include/drm/i915_drm.h                                |   71 ++
 b/intel/Makefile.am                                     |    2 
 b/intel/intel_bufmgr.h                                  |   24 
 b/intel/intel_bufmgr_gem.c                              |  364 +++++++++++-
 b/intel/intel_bufmgr_priv.h                             |    5 
 b/intel/intel_chipset.h                                 |   79 ++
 b/intel/intel_decode.c                                  |  106 +++
 b/intel/test_decode.c                                   |    2 
 b/libdrm_lists.h                                        |   29 +
 b/libkms/Makefile.am                                    |    2 
 b/man/Makefile.am                                       |   11 
 b/man/drmAvailable.man                                  |   25 
 b/man/drmHandleEvent.man                                |   45 +
 b/man/drmModeGetResources.man                           |   79 ++
 b/omap/omap_drm.c                                       |  199 ++++++
 b/omap/omap_drm.h                                       |   36 -
 b/omap/omap_drmif.h                                     |    4 
 b/radeon/Makefile.am                                    |    2 
 b/radeon/r600_pci_ids.h                                 |   83 ++
 b/radeon/radeon_bo_gem.c                                |   48 +
 b/radeon/radeon_bo_gem.h                                |    4 
 b/radeon/radeon_cs_gem.c                                |    2 
 b/radeon/radeon_surface.c                               |  460 ++++++++++++----
 b/radeon/radeon_surface.h                               |    2 
 b/xf86drm.c                                             |   31 +
 b/xf86drm.h                                             |    3 
 b/xf86drmMode.c                                         |   92 +++
 b/xf86drmMode.h                                         |   14 
 debian/patches/02_build_libkms_against_in_tree_drm.diff |   17 
 44 files changed, 1830 insertions(+), 227 deletions(-)


diff --git a/.gitignore b/.gitignore
index 243457e..28c77c5 100644
--- a/.gitignore
+++ b/.gitignore
@@ -42,6 +42,8 @@ libdrm.pc
 libdrm_intel.pc
 libdrm_nouveau.pc
 libdrm_radeon.pc
+libdrm_omap.pc
+libdrm_exynos.pc
 libkms.pc
 libtool
 ltmain.sh
@@ -76,3 +78,5 @@ tests/modeprint/modeprint
 tests/modetest/modetest
 tests/kmstest/kmstest
 tests/vbltest/vbltest
+tests/radeon/radeon_ttm
+man/*.3
diff --git a/ChangeLog b/ChangeLog
index b36beb3..53b397c 100644
diff --git a/Makefile.am b/Makefile.am
index 4f625a1..8ecd9d9 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -45,7 +45,11 @@ if HAVE_OMAP
 OMAP_SUBDIR = omap
 endif
 
-SUBDIRS = . $(LIBKMS_SUBDIR) $(INTEL_SUBDIR) $(NOUVEAU_SUBDIR) $(RADEON_SUBDIR) $(OMAP_SUBDIR) tests include
+if HAVE_EXYNOS
+EXYNOS_SUBDIR = exynos
+endif
+
+SUBDIRS = . $(LIBKMS_SUBDIR) $(INTEL_SUBDIR) $(NOUVEAU_SUBDIR) $(RADEON_SUBDIR) $(OMAP_SUBDIR) $(EXYNOS_SUBDIR) tests include man
 
 libdrm_la_LTLIBRARIES = libdrm.la
 libdrm_ladir = $(libdir)
diff --git a/autogen.sh b/autogen.sh
index 30d679f..3f190ba 100755
--- a/autogen.sh
+++ b/autogen.sh
@@ -3,4 +3,4 @@
 test -n "$srcdir" || srcdir=`dirname "$0"`
 test -n "$srcdir" || srcdir=.
 autoreconf --force --install --verbose "$srcdir"
-test -n "$NOCONFIGURE" || "$srcdir/configure" "$@"
+test -n "$NOCONFIGURE" || "$srcdir/configure" --enable-maintainer-mode "$@"
diff --git a/configure.ac b/configure.ac
index 1ba7eba..0c19929 100644
--- a/configure.ac
+++ b/configure.ac
@@ -20,7 +20,7 @@
 
 AC_PREREQ([2.63])
 AC_INIT([libdrm],
-        [2.4.33],
+        [2.4.40],
         [https://bugs.freedesktop.org/enter_bug.cgi?product=DRI],
         [libdrm])
 
@@ -35,6 +35,27 @@ AM_MAINTAINER_MODE([enable])
 # Enable quiet compiles on automake 1.11.
 m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
 
+if test x$LIB_MAN_SUFFIX = x    ; then
+    LIB_MAN_SUFFIX=3
+fi
+if test x$LIB_MAN_DIR = x    ; then
+    LIB_MAN_DIR='$(mandir)/man$(LIB_MAN_SUFFIX)'
+fi
+AC_SUBST([LIB_MAN_SUFFIX])
+AC_SUBST([LIB_MAN_DIR])
+
+MAN_SUBSTS="\
+	-e 's|__vendorversion__|\"\$(PACKAGE_STRING)\" |' \
+	-e 's|__projectroot__|\$(prefix)|g' \
+	-e 's|__apploaddir__|\$(appdefaultdir)|g' \
+	-e 's|__appmansuffix__|\$(APP_MAN_SUFFIX)|g' \
+	-e 's|__drivermansuffix__|\$(DRIVER_MAN_SUFFIX)|g' \
+	-e 's|__adminmansuffix__|\$(ADMIN_MAN_SUFFIX)|g' \
+	-e 's|__libmansuffix__|\$(LIB_MAN_SUFFIX)|g' \
+	-e 's|__miscmansuffix__|\$(MISC_MAN_SUFFIX)|g' \
+	-e 's|__filemansuffix__|\$(FILE_MAN_SUFFIX)|g'"
+AC_SUBST([MAN_SUBSTS])
+
 # Check for programs
 AC_PROG_CC
 
@@ -73,21 +94,26 @@ AC_ARG_ENABLE(radeon,
 	      [Enable support for radeon's KMS API (default: auto)]),
 	      [RADEON=$enableval], [RADEON=auto])
 
-AC_ARG_ENABLE(vmwgfx-experimental-api,
-	      AS_HELP_STRING([--enable-vmwgfx-experimental-api],
-	      [Install vmwgfx's experimental kernel API header (default: disabled)]),
-	      [VMWGFX=$enableval], [VMWGFX=no])
+AC_ARG_ENABLE(nouveau,
+	      AS_HELP_STRING([--disable-nouveau],
+	      [Enable support for nouveau's KMS API (default: auto)]),
+	      [NOUVEAU=$enableval], [NOUVEAU=auto])
 
-AC_ARG_ENABLE(nouveau-experimental-api,
-	      AS_HELP_STRING([--enable-nouveau-experimental-api],
-	      [Enable support for nouveau's experimental API (default: disabled)]),
-	      [NOUVEAU=$enableval], [NOUVEAU=no])
+AC_ARG_ENABLE(vmwgfx,
+	      AS_HELP_STRING([--disable-vmwgfx],
+	      [Enable support for vmwgfx's KMS API (default: yes)]),
+	      [VMWGFX=$enableval], [VMWGFX=yes])
 
 AC_ARG_ENABLE(omap-experimental-api,
 	      AS_HELP_STRING([--enable-omap-experimental-api],
 	      [Enable support for OMAP's experimental API (default: disabled)]),
 	      [OMAP=$enableval], [OMAP=no])
 
+AC_ARG_ENABLE(exynos-experimental-api,
+	      AS_HELP_STRING([--enable-exynos-experimental-api],
+	      [Enable support for EXYNOS's experimental API (default: disabled)]),
+	      [EXYNOS=$enableval], [EXYNOS=no])
+
 dnl ===========================================================================
 dnl check compiler flags
 AC_DEFUN([LIBDRM_CC_TRY_FLAG], [
@@ -128,7 +154,7 @@ MAYBE_WARN="-Wall -Wextra \
 -Wpointer-arith -Wwrite-strings -Wstrict-prototypes \
 -Wmissing-prototypes -Wmissing-declarations -Wnested-externs \
 -Wpacked -Wswitch-enum -Wmissing-format-attribute \
--Wstrict-aliasing=2 -Winit-self -Wunsafe-loop-optimizations \
+-Wstrict-aliasing=2 -Winit-self \
 -Wdeclaration-after-statement -Wold-style-definition \
 -Wno-missing-field-initializers -Wno-unused-parameter \
 -Wno-attributes -Wno-long-long -Winline"
@@ -191,11 +217,28 @@ if test "x$OMAP" = xyes; then
 	AC_DEFINE(HAVE_OMAP, 1, [Have OMAP support])
 fi
 
+AM_CONDITIONAL(HAVE_EXYNOS, [test "x$EXYNOS" = xyes])
+if test "x$EXYNOS" = xyes; then
+	AC_DEFINE(HAVE_EXYNOS, 1, [Have EXYNOS support])
+fi
+
+AC_ARG_ENABLE([cairo-tests],
+              [AS_HELP_STRING([--enable-cairo-tests],
+                              [Enable support for Cairo rendering in tests (default: auto)])],
+              [CAIRO=$enableval], [CAIRO=auto])
 PKG_CHECK_MODULES(CAIRO, cairo, [HAVE_CAIRO=yes], [HAVE_CAIRO=no])
-if test "x$HAVE_CAIRO" = xyes; then
-	AC_DEFINE(HAVE_CAIRO, 1, [Have cairo support])
+AC_MSG_CHECKING([whether to enable Cairo tests])
+if test "x$CAIRO" = xauto; then
+	CAIRO="$HAVE_CAIRO"
 fi
-AM_CONDITIONAL(HAVE_CAIRO, [test "x$HAVE_CAIRO" = xyes])
+if test "x$CAIRO" = xyes; then
+	if ! test "x$HAVE_CAIRO" = xyes; then
+		AC_MSG_ERROR([Cairo support required but not present])
+	fi
+	AC_DEFINE(HAVE_CAIRO, 1, [Have Cairo support])
+fi
+AC_MSG_RESULT([$CAIRO])
+AM_CONDITIONAL(HAVE_CAIRO, [test "x$CAIRO" = xyes])
 
 # For enumerating devices in test case
 PKG_CHECK_MODULES(LIBUDEV, libudev, [HAVE_LIBUDEV=yes], [HAVE_LIBUDEV=no])
@@ -204,7 +247,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"; then
+if test "x$INTEL" != "xno" -o "x$RADEON" != "xno" -o "x$NOUVEAU" != "xno" -o "x$OMAP" != "xno"; then
     # Check for atomic intrinsics
     AC_CACHE_CHECK([for native atomic primitives], drm_cv_atomic_primitives,
     [
@@ -252,7 +295,14 @@ if test "x$INTEL" != "xno" -o "x$RADEON" != "xno"; then
                    AC_MSG_WARN([Disabling libdrm_radeon. It depends on atomic operations, which were not found for your compiler/cpu. Try compiling with -march=native, or install the libatomics-op-dev package.])
                    RADEON=no
            fi
-
+           if test "x$NOUVEAU" != "xauto"; then
+                   if test "x$NOUVEAU" != "xno"; then
+                        AC_MSG_ERROR([libdrm_nouveau depends upon atomic operations, which were not found for your compiler/cpu. Try compiling with -march=native, or install the libatomics-op-dev package, or, failing both of those, disable support for NVIDIA GPUs by passing --disable-nouveau to ./configure])
+                   fi
+           else
+                   AC_MSG_WARN([Disabling libdrm_nouveau. It depends on atomic operations, which were not found for your compiler/cpu. Try compiling with -march=native, or install the libatomics-op-dev package.])
+                   NOUVEAU=no
+           fi
     else
            if test "x$INTEL" != "xno"; then
                    case $host_cpu in
@@ -263,6 +313,9 @@ if test "x$INTEL" != "xno" -o "x$RADEON" != "xno"; then
            if test "x$RADEON" != "xno"; then
                    RADEON=yes
            fi
+           if test "x$NOUVEAU" != "xno"; then
+                   NOUVEAU=yes
+           fi
     fi
 fi
 
@@ -279,6 +332,7 @@ fi
 
 AM_CONDITIONAL(HAVE_INTEL, [test "x$INTEL" != "xno"])
 AM_CONDITIONAL(HAVE_RADEON, [test "x$RADEON" != "xno"])
+AM_CONDITIONAL(HAVE_NOUVEAU, [test "x$NOUVEAU" != "xno"])
 if test "x$RADEON" = xyes; then
 	AC_DEFINE(HAVE_RADEON, 1, [Have radeon support])
 fi
@@ -302,6 +356,8 @@ AC_CONFIG_FILES([
 	nouveau/libdrm_nouveau.pc
 	omap/Makefile
 	omap/libdrm_omap.pc
+	exynos/Makefile
+	exynos/libdrm_exynos.pc
 	tests/Makefile
 	tests/modeprint/Makefile
 	tests/modetest/Makefile
@@ -310,6 +366,7 @@ AC_CONFIG_FILES([
 	tests/vbltest/Makefile
 	include/Makefile
 	include/drm/Makefile
+	man/Makefile
 	libdrm.pc])
 AC_OUTPUT
 
@@ -322,4 +379,5 @@ echo "  vmwgfx API     $VMWGFX"
 echo "  Radeon API     $RADEON"
 echo "  Nouveau API    $NOUVEAU"
 echo "  OMAP API       $OMAP"
+echo "  EXYNOS API     $EXYNOS"
 echo ""
diff --git a/debian/changelog b/debian/changelog
index 6408491..fe51436 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,32 @@
+libdrm (2.4.40-1~deb7u1) UNRELEASED; urgency=low
+
+  * Revert nouveau to the 2.4.33 state (ie before the rewrite).
+  * Revert addition of libdrm2-udeb.
+  * Bump libdrm2 shlibs to 2.4.38.
+
+ -- Julien Cristau <jcristau@debian.org>  Tue, 25 Dec 2012 13:08:50 +0100
+
+libdrm (2.4.40-1) experimental; urgency=low
+
+  [ Maarten Lankhorst ]
+  * New upstream release.
+    - Nouveau ABI change, replace libdrm-nouveau1a with libdrm-nouveau2.
+
+  [ Timo Aaltonen ]
+  * Bump libdrm-intel1's and libdrm-nouveau2's shlibs due to new symbols.
+  * Hardcode the version for libdrm-omap1's shlibs.
+
+  [ Christopher James Halse Rogers ]
+  * Add libdrm2-udeb; Xserver 1.13 wants libdrm for hotplug config, so
+    will be needed for the 1.13 xserver-xorg-core-udeb.
+
+  [ Sven Joachim ]
+  * Bump libdrm-radeon1's symbols and shlibs.
+  * Mark some internal libdrm-nouveau2 symbols as private.
+  * Drop patch 02_build_libkms_against_in_tree_drm.diff, applied upstream.
+
+ -- Julien Cristau <jcristau@debian.org>  Sat, 17 Nov 2012 18:50:33 +0100
+
 libdrm (2.4.33-3) unstable; urgency=low
 
   * Add missing dependency on libdrm-omap1 to libdrm-dev (thanks, Robert
diff --git a/debian/control b/debian/control
index 5b5d9f6..354f97d 100644
--- a/debian/control
+++ b/debian/control
@@ -3,7 +3,7 @@ Priority: optional
 Maintainer: Debian X Strike Force <debian-x@lists.debian.org>
 Uploaders: Cyril Brulebois <kibi@debian.org>
 Build-Depends:
- debhelper (>= 8.1.2ubuntu2),
+ debhelper (>= 9),
  dh-autoreconf,
  quilt,
  libx11-dev,
diff --git a/debian/libdrm-dev.install b/debian/libdrm-dev.install
index 76f28fa..e1ca993 100644
--- a/debian/libdrm-dev.install
+++ b/debian/libdrm-dev.install
@@ -2,3 +2,4 @@ usr/include/*
 usr/lib/*/lib*.a
 usr/lib/*/lib*.so
 usr/lib/*/pkgconfig/*
+usr/share/man/man3
diff --git a/debian/libdrm-intel1.symbols b/debian/libdrm-intel1.symbols
index a381740..8f5b9fe 100644
--- a/debian/libdrm-intel1.symbols
+++ b/debian/libdrm-intel1.symbols
@@ -11,6 +11,8 @@ libdrm_intel.so.1 libdrm-intel1 #MINVER#
  drm_intel_bo_fake_disable_backing_store@Base 2.4.1
  drm_intel_bo_flink@Base 2.4.1
  drm_intel_bo_gem_create_from_name@Base 2.4.1
+ drm_intel_bo_gem_create_from_prime@Base 2.4.38
+ drm_intel_bo_gem_export_to_prime@Base 2.4.38
  drm_intel_bo_get_subdata@Base 2.4.1
  drm_intel_bo_get_tiling@Base 2.4.1
  drm_intel_bo_is_reusable@Base 2.4.21
@@ -39,6 +41,7 @@ libdrm_intel.so.1 libdrm-intel1 #MINVER#
  drm_intel_bufmgr_gem_get_devid@Base 2.4.32
  drm_intel_bufmgr_gem_init@Base 2.4.1
  drm_intel_bufmgr_gem_set_aub_dump@Base 2.4.32
+ drm_intel_bufmgr_gem_set_aub_annotations@Base 2.4.34
  drm_intel_bufmgr_gem_set_vma_cache_size@Base 2.4.29
  drm_intel_bufmgr_set_debug@Base 2.4.1
  drm_intel_decode@Base 2.4.30
@@ -50,13 +53,18 @@ libdrm_intel.so.1 libdrm-intel1 #MINVER#
  drm_intel_decode_set_output_file@Base 2.4.30
  drm_intel_gem_bo_aub_dump_bmp@Base 2.4.32
  drm_intel_gem_bo_clear_relocs@Base 2.4.27
+ drm_intel_gem_bo_context_exec@Base 2.4.36
  drm_intel_gem_bo_get_reloc_count@Base 2.4.27
  drm_intel_gem_bo_map_gtt@Base 2.4.3
  drm_intel_gem_bo_map_unsynchronized@Base 2.4.32
  drm_intel_gem_bo_start_gtt_access@Base 2.4.3
  drm_intel_gem_bo_unmap_gtt@Base 2.4.9
+ drm_intel_gem_bo_wait@Base 2.4.36
+ drm_intel_gem_context_create@Base 2.4.37
+ drm_intel_gem_context_destroy@Base 2.4.37
  drm_intel_get_aperture_sizes@Base 2.4.26
  drm_intel_get_pipe_from_crtc_id@Base 2.4.11
+ drm_intel_reg_read@Base 2.4.38
  drm_mmAllocMem@Base 2.4.1
  drm_mmDestroy@Base 2.4.1
  drm_mmDumpMemInfo@Base 2.4.1
diff --git a/debian/libdrm-omap1.symbols b/debian/libdrm-omap1.symbols
index 5ad0f17..0c12475 100644
--- a/debian/libdrm-omap1.symbols
+++ b/debian/libdrm-omap1.symbols
@@ -2,14 +2,18 @@ libdrm_omap.so.1 libdrm-omap1 #MINVER#
  omap_bo_cpu_fini@Base 2.4.33
  omap_bo_cpu_prep@Base 2.4.33
  omap_bo_del@Base 2.4.33
+ omap_bo_dmabuf@Base 2.4.34
+ omap_bo_from_dmabuf@Base 2.4.38
  omap_bo_from_name@Base 2.4.33
  omap_bo_get_name@Base 2.4.33
  omap_bo_handle@Base 2.4.33
  omap_bo_map@Base 2.4.33
  omap_bo_new@Base 2.4.33
  omap_bo_new_tiled@Base 2.4.33
+ omap_bo_ref@Base 2.4.38
  omap_bo_size@Base 2.4.33
  omap_device_del@Base 2.4.33
  omap_device_new@Base 2.4.33
+ omap_device_ref@Base 2.4.38
  omap_get_param@Base 2.4.33
  omap_set_param@Base 2.4.33
diff --git a/debian/libdrm-radeon1.symbols b/debian/libdrm-radeon1.symbols
index 557be89..e9578a6 100644
--- a/debian/libdrm-radeon1.symbols
+++ b/debian/libdrm-radeon1.symbols
@@ -52,9 +52,11 @@ libdrm_radeon.so.1 libdrm-radeon1 #MINVER#
  radeon_cs_space_reset_bos@Base 2.4.17
  radeon_cs_space_set_flush@Base 2.4.17
  radeon_cs_write_reloc@Base 2.4.17
+ radeon_gem_bo_open_prime@Base 2.4.39
  radeon_gem_get_kernel_name@Base 2.4.17
  radeon_gem_get_reloc_in_cs@Base 2.4.20
  radeon_gem_name_bo@Base 2.4.17
+ radeon_gem_prime_share_bo@Base 2.4.39
  radeon_gem_set_domain@Base 2.4.17
  radeon_surface_best@Base 2.4.31
  radeon_surface_init@Base 2.4.31
diff --git a/debian/libdrm2.symbols b/debian/libdrm2.symbols
index 0f70434..c4047c4 100644
--- a/debian/libdrm2.symbols
+++ b/debian/libdrm2.symbols
@@ -89,6 +89,7 @@ libdrm.so.2 libdrm2 #MINVER#
  drmModeFreeEncoder@Base 2.4.3
  drmModeFreeFB@Base 2.4.3
  drmModeFreeModeInfo@Base 2.4.3
+ drmModeFreeObjectProperties@Base 2.4.36
  drmModeFreePlane@Base 2.4.30
  drmModeFreePlaneResources@Base 2.4.31
  drmModeFreeProperty@Base 2.4.3
@@ -104,6 +105,8 @@ libdrm.so.2 libdrm2 #MINVER#
  drmModeGetPropertyBlob@Base 2.4.3
  drmModeGetResources@Base 2.4.3
  drmModeMoveCursor@Base 2.4.3
+ drmModeObjectGetProperties@Base 2.4.36
+ drmModeObjectSetProperty@Base 2.4.36
  drmModePageFlip@Base 2.4.17
  drmModeRmFB@Base 2.4.3
  drmModeSetCrtc@Base 2.4.3
@@ -113,6 +116,8 @@ libdrm.so.2 libdrm2 #MINVER#
  drmOpen@Base 2.3.1
  drmOpenControl@Base 2.4.3
  drmOpenOnce@Base 2.3.1
+ drmPrimeFDToHandle@Base 2.4.38
+ drmPrimeHandleToFD@Base 2.4.38
  drmRandom@Base 2.3.1
  drmRandomCreate@Base 2.3.1
  drmRandomDestroy@Base 2.3.1
diff --git a/debian/patches/02_build_libkms_against_in_tree_drm.diff b/debian/patches/02_build_libkms_against_in_tree_drm.diff
deleted file mode 100644
index 25f8e43..0000000
--- a/debian/patches/02_build_libkms_against_in_tree_drm.diff
+++ /dev/null
@@ -1,17 +0,0 @@
-Description: Add libdrm to LIBADD as libkms uses symbols from libdrm
-Author: Christopher Halse Rogers <christopher.halse.rogers@canonical.com>
-Bug: https://bugs.freedesktop.org/show_bug.cgi?id=26852
-
-Index: libdrm/libkms/Makefile.am
-===================================================================
---- libdrm.orig/libkms/Makefile.am
-+++ libdrm/libkms/Makefile.am
-@@ -6,7 +6,7 @@ AM_CFLAGS = \
- libkms_la_LTLIBRARIES = libkms.la
- libkms_ladir = $(libdir)
- libkms_la_LDFLAGS = -version-number 1:0:0 -no-undefined
--libkms_la_LIBADD =
-+libkms_la_LIBADD = ../libdrm.la
- 
- #if HAVE_LIBUDEV
- #libkms_la_LIBADD += $(LIBUDEV_LIBS)
diff --git a/debian/patches/revert-nouveau-rewrite.diff b/debian/patches/revert-nouveau-rewrite.diff
new file mode 100644
index 0000000..76bec4b
diff --git a/debian/patches/series b/debian/patches/series
index b1a73f8..c20e4b9 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -1,3 +1,3 @@
 01_default_perms.diff
-02_build_libkms_against_in_tree_drm.diff
 03_build_against_librt.diff
+revert-nouveau-rewrite.diff
diff --git a/debian/rules b/debian/rules
index 44926b1..bb23d84 100755
--- a/debian/rules
+++ b/debian/rules
@@ -13,8 +13,8 @@ ifeq (linux, $(DEB_HOST_ARCH_OS))
 	confflags += --enable-udev
 	confflags += --enable-libkms
 	LIBKMS = yes
-	confflags += --enable-vmwgfx-experimental-api
-	confflags += --enable-nouveau-experimental-api
+	confflags += --enable-vmwgfx
+	confflags += --enable-nouveau
 	NOUVEAU = yes
 	confflags += --enable-radeon
 	RADEON = yes
@@ -22,8 +22,8 @@ else
 	confflags += --disable-udev
 	confflags += --disable-libkms
 	LIBKMS = no
-	confflags += --disable-vmwgfx-experimental-api
-	confflags += --disable-nouveau-experimental-api
+	confflags += --disable-vmwgfx
+	confflags += --disable-nouveau
 	NOUVEAU = no
 	confflags += --disable-radeon
 	RADEON = no
@@ -88,18 +88,18 @@ endif
 	dh_strip -s --remaining-packages
 
 override_dh_makeshlibs:
-	dh_makeshlibs -plibdrm2 -V'libdrm2 (>= 2.4.31)' -- -c4
+	dh_makeshlibs -plibdrm2 -V'libdrm2 (>= 2.4.38)' -- -c4
 ifeq ($(INTEL), yes)
-	dh_makeshlibs -plibdrm-intel1 -V'libdrm-intel1 (>= 2.4.32)' -- -c4
+	dh_makeshlibs -plibdrm-intel1 -V'libdrm-intel1 (>= 2.4.38)' -- -c4
 endif
 ifeq ($(NOUVEAU), yes)
 	dh_makeshlibs -plibdrm-nouveau1a -V'libdrm-nouveau1a (>= 2.4.23)' -- -c4
 endif
 ifeq ($(RADEON), yes)
-	dh_makeshlibs -plibdrm-radeon1 -V'libdrm-radeon1 (>= 2.4.31)' -- -c4
+	dh_makeshlibs -plibdrm-radeon1 -V'libdrm-radeon1 (>= 2.4.39)' -- -c4
 endif
 ifeq ($(OMAP), yes)
-	dh_makeshlibs -plibdrm-omap1 -V'libdrm-omap1' -- -c4
+	dh_makeshlibs -plibdrm-omap1 -V'libdrm-omap1 (>= 2.4.38)' -- -c4
 endif
 ifeq ($(LIBKMS), yes)
 	dh_makeshlibs -plibkms1 -V'libkms1' -- -c4
diff --git a/exynos/Makefile.am b/exynos/Makefile.am
new file mode 100644
index 0000000..e782d34
diff --git a/exynos/exynos_drm.c b/exynos/exynos_drm.c
new file mode 100644
index 0000000..4db755e
diff --git a/exynos/exynos_drm.h b/exynos/exynos_drm.h
new file mode 100644
index 0000000..aa97b22
diff --git a/exynos/exynos_drmif.h b/exynos/exynos_drmif.h
new file mode 100644
index 0000000..92f613e
diff --git a/exynos/libdrm_exynos.pc.in b/exynos/libdrm_exynos.pc.in
new file mode 100644
index 0000000..5ce9118
diff --git a/include/drm/drm.h b/include/drm/drm.h
index 8adb9d5..a847689 100644
--- a/include/drm/drm.h
+++ b/include/drm/drm.h
@@ -618,6 +618,17 @@ struct drm_get_cap {
 	__u64 value;
 };
 
+#define DRM_CLOEXEC O_CLOEXEC
+struct drm_prime_handle {
+	__u32 handle;
+
+	/** Flags.. only applicable for handle->fd */
+	__u32 flags;
+
+	/** Returned dmabuf file descriptor */
+	__s32 fd;
+};
+
 #include "drm_mode.h"
 
 #define DRM_IOCTL_BASE			'd'
@@ -674,6 +685,9 @@ struct drm_get_cap {
 #define DRM_IOCTL_UNLOCK		DRM_IOW( 0x2b, struct drm_lock)
 #define DRM_IOCTL_FINISH		DRM_IOW( 0x2c, struct drm_lock)
 
+#define DRM_IOCTL_PRIME_HANDLE_TO_FD    DRM_IOWR(0x2d, struct drm_prime_handle)
+#define DRM_IOCTL_PRIME_FD_TO_HANDLE    DRM_IOWR(0x2e, struct drm_prime_handle)
+
 #define DRM_IOCTL_AGP_ACQUIRE		DRM_IO(  0x30)
 #define DRM_IOCTL_AGP_RELEASE		DRM_IO(  0x31)
 #define DRM_IOCTL_AGP_ENABLE		DRM_IOW( 0x32, struct drm_agp_mode)
@@ -717,6 +731,8 @@ struct drm_get_cap {
 #define DRM_IOCTL_MODE_GETPLANE	DRM_IOWR(0xB6, struct drm_mode_get_plane)
 #define DRM_IOCTL_MODE_SETPLANE	DRM_IOWR(0xB7, struct drm_mode_set_plane)
 #define DRM_IOCTL_MODE_ADDFB2		DRM_IOWR(0xB8, struct drm_mode_fb_cmd2)
+#define DRM_IOCTL_MODE_OBJ_GETPROPERTIES	DRM_IOWR(0xB9, struct drm_mode_obj_get_properties)
+#define DRM_IOCTL_MODE_OBJ_SETPROPERTY	DRM_IOWR(0xBA, struct drm_mode_obj_set_property)
 
 /**
  * Device specific ioctls should only be in their respective headers
@@ -760,6 +776,12 @@ struct drm_event_vblank {
 
 #define DRM_CAP_DUMB_BUFFER 0x1
 #define DRM_CAP_VBLANK_HIGH_CRTC   0x2
+#define DRM_CAP_DUMB_PREFERRED_DEPTH 0x3
+#define DRM_CAP_DUMB_PREFER_SHADOW 0x4
+#define DRM_CAP_PRIME 0x5
+
+#define DRM_PRIME_CAP_IMPORT 0x1
+#define DRM_PRIME_CAP_EXPORT 0x2
 
 /* typedef area */
 typedef struct drm_clip_rect drm_clip_rect_t;
diff --git a/include/drm/drm_mode.h b/include/drm/drm_mode.h
index f36c61a..62ba997 100644
--- a/include/drm/drm_mode.h
+++ b/include/drm/drm_mode.h
@@ -226,6 +226,7 @@ struct drm_mode_get_connector {
 #define DRM_MODE_PROP_IMMUTABLE	(1<<2)
 #define DRM_MODE_PROP_ENUM	(1<<3) /* enumerated type with text strings */
 #define DRM_MODE_PROP_BLOB	(1<<4)
+#define DRM_MODE_PROP_BITMASK	(1<<5) /* bitmask of enumerated types */
 
 struct drm_mode_property_enum {
 	__u64 value;
@@ -250,6 +251,30 @@ struct drm_mode_connector_set_property {
 	__u32 connector_id;
 };
 
+#define DRM_MODE_OBJECT_CRTC 0xcccccccc
+#define DRM_MODE_OBJECT_CONNECTOR 0xc0c0c0c0
+#define DRM_MODE_OBJECT_ENCODER 0xe0e0e0e0
+#define DRM_MODE_OBJECT_MODE 0xdededede
+#define DRM_MODE_OBJECT_PROPERTY 0xb0b0b0b0
+#define DRM_MODE_OBJECT_FB 0xfbfbfbfb
+#define DRM_MODE_OBJECT_BLOB 0xbbbbbbbb
+#define DRM_MODE_OBJECT_PLANE 0xeeeeeeee
+
+struct drm_mode_obj_get_properties {
+	__u64 props_ptr;
+	__u64 prop_values_ptr;
+	__u32 count_props;
+	__u32 obj_id;
+	__u32 obj_type;
+};
+
+struct drm_mode_obj_set_property {
+	__u64 value;
+	__u32 prop_id;
+	__u32 obj_id;
+	__u32 obj_type;
+};
+
 struct drm_mode_get_blob {
 	__u32 blob_id;
 	__u32 length;
diff --git a/include/drm/i915_drm.h b/include/drm/i915_drm.h
index af3ce17..7e9e9bd 100644
--- a/include/drm/i915_drm.h
+++ b/include/drm/i915_drm.h
@@ -33,6 +33,7 @@
  * subject to backwards-compatibility constraints.
  */
 
+
 /* Each region is a minimum of 16k, and there are at most 255 of them.
  */
 #define I915_NR_TEX_REGIONS 255	/* table size 2k - maximum due to use
@@ -191,6 +192,12 @@ typedef struct _drm_i915_sarea {
 #define DRM_I915_GEM_EXECBUFFER2	0x29
 #define DRM_I915_GET_SPRITE_COLORKEY	0x2a
 #define DRM_I915_SET_SPRITE_COLORKEY	0x2b
+#define DRM_I915_GEM_WAIT	0x2c
+#define DRM_I915_GEM_CONTEXT_CREATE	0x2d
+#define DRM_I915_GEM_CONTEXT_DESTROY	0x2e
+#define DRM_I915_GEM_SET_CACHEING	0x2f
+#define DRM_I915_GEM_GET_CACHEING	0x30
+#define DRM_I915_REG_READ		0x31
 
 #define DRM_IOCTL_I915_INIT		DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT, drm_i915_init_t)
 #define DRM_IOCTL_I915_FLUSH		DRM_IO ( DRM_COMMAND_BASE + DRM_I915_FLUSH)
@@ -215,6 +222,8 @@ typedef struct _drm_i915_sarea {
 #define DRM_IOCTL_I915_GEM_PIN		DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_PIN, struct drm_i915_gem_pin)
 #define DRM_IOCTL_I915_GEM_UNPIN	DRM_IOW(DRM_COMMAND_BASE + DRM_I915_GEM_UNPIN, struct drm_i915_gem_unpin)
 #define DRM_IOCTL_I915_GEM_BUSY		DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_BUSY, struct drm_i915_gem_busy)
+#define DRM_IOCTL_I915_GEM_SET_CACHEING		DRM_IOW(DRM_COMMAND_BASE + DRM_I915_GEM_SET_CACHEING, struct drm_i915_gem_cacheing)
+#define DRM_IOCTL_I915_GEM_GET_CACHEING		DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_GET_CACHEING, struct drm_i915_gem_cacheing)
 #define DRM_IOCTL_I915_GEM_THROTTLE	DRM_IO ( DRM_COMMAND_BASE + DRM_I915_GEM_THROTTLE)
 #define DRM_IOCTL_I915_GEM_ENTERVT	DRM_IO(DRM_COMMAND_BASE + DRM_I915_GEM_ENTERVT)
 #define DRM_IOCTL_I915_GEM_LEAVEVT	DRM_IO(DRM_COMMAND_BASE + DRM_I915_GEM_LEAVEVT)
@@ -234,6 +243,10 @@ typedef struct _drm_i915_sarea {
 #define DRM_IOCTL_I915_OVERLAY_ATTRS	DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_OVERLAY_ATTRS, struct drm_intel_overlay_attrs)
 #define DRM_IOCTL_I915_SET_SPRITE_COLORKEY DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_SET_SPRITE_COLORKEY, struct drm_intel_sprite_colorkey)
 #define DRM_IOCTL_I915_GET_SPRITE_COLORKEY DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_SET_SPRITE_COLORKEY, struct drm_intel_sprite_colorkey)
+#define DRM_IOCTL_I915_GEM_WAIT		DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_WAIT, struct drm_i915_gem_wait)
+#define DRM_IOCTL_I915_GEM_CONTEXT_CREATE	DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GEM_CONTEXT_CREATE, struct drm_i915_gem_context_create)
+#define DRM_IOCTL_I915_GEM_CONTEXT_DESTROY	DRM_IOW (DRM_COMMAND_BASE + DRM_I915_GEM_CONTEXT_DESTROY, struct drm_i915_gem_context_destroy)
+#define DRM_IOCTL_I915_REG_READ			DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_REG_READ, struct drm_i915_reg_read)
 
 /* Allow drivers to submit batchbuffers directly to hardware, relying
  * on the security mechanisms provided by hardware.
@@ -287,7 +300,9 @@ typedef struct drm_i915_irq_wait {
 #define I915_PARAM_HAS_EXEC_CONSTANTS	 14
 #define I915_PARAM_HAS_RELAXED_DELTA	 15
 #define I915_PARAM_HAS_GEN7_SOL_RESET	 16
-#define I915_PARAM_HAS_LLC		 17
+#define I915_PARAM_HAS_LLC     	 	 17
+#define I915_PARAM_HAS_ALIASING_PPGTT	 18
+#define I915_PARAM_HAS_WAIT_TIMEOUT	 19
 
 typedef struct drm_i915_getparam {
 	int param;
@@ -646,13 +661,19 @@ struct drm_i915_gem_execbuffer2 {
 #define I915_EXEC_CONSTANTS_ABSOLUTE 	(1<<6)
 #define I915_EXEC_CONSTANTS_REL_SURFACE (2<<6) /* gen4/5 only */
 	__u64 flags;
-	__u64 rsvd1;
+	__u64 rsvd1; /* now used for context info */
 	__u64 rsvd2;
 };
 
 /** Resets the SO write offset registers for transform feedback on gen7. */
 #define I915_EXEC_GEN7_SOL_RESET	(1<<8)
 
+#define I915_EXEC_CONTEXT_ID_MASK	(0xffffffff)
+#define i915_execbuffer2_set_context_id(eb2, context) \
+	(eb2).rsvd1 = context & I915_EXEC_CONTEXT_ID_MASK
+#define i915_execbuffer2_get_context_id(eb2) \
+	((eb2).rsvd1 & I915_EXEC_CONTEXT_ID_MASK)
+
 struct drm_i915_gem_pin {
 	/** Handle of the buffer to be pinned. */
 	__u32 handle;
@@ -675,10 +696,31 @@ struct drm_i915_gem_busy {
 	/** Handle of the buffer to check for busy */
 	__u32 handle;
 
-	/** Return busy status (1 if busy, 0 if idle) */
+	/** Return busy status (1 if busy, 0 if idle).
+	 * The high word is used to indicate on which rings the object
+	 * currently resides:
+	 *  16:31 - busy (r or r/w) rings (16 render, 17 bsd, 18 blt, etc)
+	 */
 	__u32 busy;
 };
 
+#define I915_CACHEING_NONE		0
+#define I915_CACHEING_CACHED		1
+
+struct drm_i915_gem_cacheing {
+	/**
+	 * Handle of the buffer to set/get the cacheing level of. */
+	__u32 handle;
+
+	/**
+	 * Cacheing level to apply or return value
+	 *
+	 * bits0-15 are for generic cacheing control (i.e. the above defined
+	 * values). bits16-31 are reserved for platform-specific variations
+	 * (e.g. l3$ caching on gen7). */
+	__u32 cacheing;
+};
+
 #define I915_TILING_NONE	0
 #define I915_TILING_X		1
 #define I915_TILING_Y		2
@@ -876,4 +918,27 @@ struct drm_intel_sprite_colorkey {
 	__u32 flags;
 };
 
+struct drm_i915_gem_wait {
+	/** Handle of BO we shall wait on */
+	__u32 bo_handle;
+	__u32 flags;
+	/** Number of nanoseconds to wait, Returns time remaining. */
+	__s64 timeout_ns;
+};
+
+struct drm_i915_gem_context_create {
+	/*  output: id of new context*/
+	__u32 ctx_id;
+	__u32 pad;
+};
+
+struct drm_i915_gem_context_destroy {
+	__u32 ctx_id;
+	__u32 pad;
+};
+
+struct drm_i915_reg_read {
+	__u64 offset;
+	__u64 val; /* Return value */
+};
 #endif				/* _I915_DRM_H_ */
diff --git a/intel/Makefile.am b/intel/Makefile.am
index dc01a96..f49b099 100644
--- a/intel/Makefile.am
+++ b/intel/Makefile.am
@@ -77,6 +77,6 @@ EXTRA_DIST = \
 	$(BATCHES:.batch=.batch-ref.txt) \
 	tests/test-batch.sh
 
-test_decode_LDADD = libdrm_intel.la
+test_decode_LDADD = libdrm_intel.la ../libdrm.la
 
 pkgconfig_DATA = libdrm_intel.pc
diff --git a/intel/intel_bufmgr.h b/intel/intel_bufmgr.h
index 45389e1..8d7f239 100644
--- a/intel/intel_bufmgr.h
+++ b/intel/intel_bufmgr.h
@@ -41,6 +41,7 @@
 struct drm_clip_rect;
 
 typedef struct _drm_intel_bufmgr drm_intel_bufmgr;
+typedef struct _drm_intel_context drm_intel_context;
 typedef struct _drm_intel_bo drm_intel_bo;
 
 struct _drm_intel_bo {
@@ -92,6 +93,12 @@ enum aub_dump_bmp_format {
 	AUB_DUMP_BMP_FORMAT_ARGB_8888 = 7,
 };
 
+typedef struct _drm_intel_aub_annotation {
+	uint32_t type;
+	uint32_t subtype;
+	uint32_t ending_offset;
+} drm_intel_aub_annotation;
+
 #define BO_ALLOC_FOR_RENDER (1<<0)
 
 drm_intel_bo *drm_intel_bo_alloc(drm_intel_bufmgr *bufmgr, const char *name,
@@ -169,11 +176,25 @@ void drm_intel_gem_bo_aub_dump_bmp(drm_intel_bo *bo,
 				   int x1, int y1, int width, int height,
 				   enum aub_dump_bmp_format format,
 				   int pitch, int offset);
+void
+drm_intel_bufmgr_gem_set_aub_annotations(drm_intel_bo *bo,
+					 drm_intel_aub_annotation *annotations,
+					 unsigned count);
 
 int drm_intel_get_pipe_from_crtc_id(drm_intel_bufmgr *bufmgr, int crtc_id);
 
 int drm_intel_get_aperture_sizes(int fd, size_t *mappable, size_t *total);
 int drm_intel_bufmgr_gem_get_devid(drm_intel_bufmgr *bufmgr);
+int drm_intel_gem_bo_wait(drm_intel_bo *bo, int64_t timeout_ns);
+
+drm_intel_context *drm_intel_gem_context_create(drm_intel_bufmgr *bufmgr);
+void drm_intel_gem_context_destroy(drm_intel_context *ctx);
+int drm_intel_gem_bo_context_exec(drm_intel_bo *bo, drm_intel_context *ctx,
+				  int used, unsigned int flags);
+
+int drm_intel_bo_gem_export_to_prime(drm_intel_bo *bo, int *prime_fd);
+drm_intel_bo *drm_intel_bo_gem_create_from_prime(drm_intel_bufmgr *bufmgr,
+						int prime_fd, int size);
 
 /* drm_intel_bufmgr_fake.c */
 drm_intel_bufmgr *drm_intel_bufmgr_fake_init(int fd,
@@ -220,6 +241,9 @@ void drm_intel_decode_set_head_tail(struct drm_intel_decode *ctx,
 void drm_intel_decode_set_output_file(struct drm_intel_decode *ctx, FILE *out);
 void drm_intel_decode(struct drm_intel_decode *ctx);
 
+int drm_intel_reg_read(drm_intel_bufmgr *bufmgr,
+		       uint32_t offset,
+		       uint64_t *result);
 
 /** @{ Compatibility defines to keep old code building despite the symbol rename
  * from dri_* to drm_intel_*
diff --git a/intel/intel_bufmgr_gem.c b/intel/intel_bufmgr_gem.c
index 3c91090..8d45839 100644
--- a/intel/intel_bufmgr_gem.c
+++ b/intel/intel_bufmgr_gem.c
@@ -119,6 +119,7 @@ typedef struct _drm_intel_bufmgr_gem {
 	unsigned int has_blt : 1;
 	unsigned int has_relaxed_fencing : 1;
 	unsigned int has_llc : 1;
+	unsigned int has_wait_timeout : 1;
 	unsigned int bo_reuse : 1;
 	unsigned int no_exec : 1;
 	bool fenced_relocs;
@@ -221,6 +222,9 @@ struct _drm_intel_bo_gem {
 	bool mapped_cpu_write;
 
 	uint32_t aub_offset;
+
+	drm_intel_aub_annotation *aub_annotations;
+	unsigned aub_annotation_count;
 };
 
 static unsigned int
@@ -735,6 +739,8 @@ retry:
 	bo_gem->used_as_reloc_target = false;
 	bo_gem->has_error = false;
 	bo_gem->reusable = true;
+	bo_gem->aub_annotations = NULL;
+	bo_gem->aub_annotation_count = 0;
 
 	drm_intel_bo_gem_set_in_aperture_size(bufmgr_gem, bo_gem);
 
@@ -926,6 +932,7 @@ drm_intel_gem_bo_free(drm_intel_bo *bo)
 		DBG("DRM_IOCTL_GEM_CLOSE %d failed (%s): %s\n",
 		    bo_gem->gem_handle, bo_gem->name, strerror(errno));
 	}
+	free(bo_gem->aub_annotations);
 	free(bo);
 }
 
@@ -1473,6 +1480,58 @@ drm_intel_gem_bo_wait_rendering(drm_intel_bo *bo)
 }
 
 /**
+ * Waits on a BO for the given amount of time.
+ *
+ * @bo: buffer object to wait for
+ * @timeout_ns: amount of time to wait in nanoseconds.
+ *   If value is less than 0, an infinite wait will occur.
+ *
+ * Returns 0 if the wait was successful ie. the last batch referencing the
+ * object has completed within the allotted time. Otherwise some negative return
+ * value describes the error. Of particular interest is -ETIME when the wait has
+ * failed to yield the desired result.
+ *
+ * Similar to drm_intel_gem_bo_wait_rendering except a timeout parameter allows
+ * the operation to give up after a certain amount of time. Another subtle
+ * difference is the internal locking semantics are different (this variant does
+ * not hold the lock for the duration of the wait). This makes the wait subject
+ * to a larger userspace race window.
+ *
+ * The implementation shall wait until the object is no longer actively
+ * referenced within a batch buffer at the time of the call. The wait will
+ * not guarantee that the buffer is re-issued via another thread, or an flinked
+ * handle. Userspace must make sure this race does not occur if such precision
+ * is important.
+ */
+int drm_intel_gem_bo_wait(drm_intel_bo *bo, int64_t timeout_ns)
+{
+	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr;
+	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
+	struct drm_i915_gem_wait wait;
+	int ret;
+
+	if (!bufmgr_gem->has_wait_timeout) {
+		DBG("%s:%d: Timed wait is not supported. Falling back to "
+		    "infinite wait\n", __FILE__, __LINE__);
+		if (timeout_ns) {
+			drm_intel_gem_bo_wait_rendering(bo);
+			return 0;
+		} else {
+			return drm_intel_gem_bo_busy(bo) ? -ETIME : 0;
+		}
+	}
+
+	wait.bo_handle = bo_gem->gem_handle;
+	wait.timeout_ns = timeout_ns;
+	wait.flags = 0;
+	ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GEM_WAIT, &wait);
+	if (ret == -1)
+		return -errno;
+
+	return ret;
+}
+
+/**
  * Sets the object to the GTT read and possibly write domain, used by the X
  * 2D driver in the absence of kernel support to do drm_intel_gem_bo_map_gtt().
  *
@@ -1880,26 +1939,58 @@ aub_write_trace_block(drm_intel_bo *bo, uint32_t type, uint32_t subtype,
 	aub_write_bo_data(bo, offset, size);
 }
 
+/**
+ * Break up large objects into multiple writes.  Otherwise a 128kb VBO
+ * would overflow the 16 bits of size field in the packet header and
+ * everything goes badly after that.
+ */
 static void
-aub_write_bo(drm_intel_bo *bo)
+aub_write_large_trace_block(drm_intel_bo *bo, uint32_t type, uint32_t subtype,
+			    uint32_t offset, uint32_t size)
 {
 	uint32_t block_size;
-	uint32_t offset;
+	uint32_t sub_offset;
 
-	aub_bo_get_address(bo);
-
-	/* Break up large objects into multiple writes.  Otherwise a
-	 * 128kb VBO would overflow the 16 bits of size field in the
-	 * packet header and everything goes badly after that.
-	 */
-	for (offset = 0; offset < bo->size; offset += block_size) {
-		block_size = bo->size - offset;
+	for (sub_offset = 0; sub_offset < size; sub_offset += block_size) {
+		block_size = size - sub_offset;
 
 		if (block_size > 8 * 4096)
 			block_size = 8 * 4096;
 
-		aub_write_trace_block(bo, AUB_TRACE_TYPE_NOTYPE, 0,
-				      offset, block_size);
+		aub_write_trace_block(bo, type, subtype, offset + sub_offset,
+				      block_size);
+	}
+}
+
+static void
+aub_write_bo(drm_intel_bo *bo)
+{
+	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
+	uint32_t offset = 0;
+	unsigned i;
+
+	aub_bo_get_address(bo);
+
+	/* Write out each annotated section separately. */
+	for (i = 0; i < bo_gem->aub_annotation_count; ++i) {
+		drm_intel_aub_annotation *annotation =
+			&bo_gem->aub_annotations[i];
+		uint32_t ending_offset = annotation->ending_offset;
+		if (ending_offset > bo->size)
+			ending_offset = bo->size;
+		if (ending_offset > offset) {
+			aub_write_large_trace_block(bo, annotation->type,
+						    annotation->subtype,
+						    offset,
+						    ending_offset - offset);
+			offset = ending_offset;
+		}
+	}
+
+	/* Write out any remaining unannotated data */
+	if (offset < bo->size) {
+		aub_write_large_trace_block(bo, AUB_TRACE_TYPE_NOTYPE, 0,
+					    offset, bo->size - offset);
 	}
 }
 
@@ -1989,23 +2080,31 @@ aub_exec(drm_intel_bo *bo, int ring_flag, int used)
 	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr;
 	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
 	int i;
+	bool batch_buffer_needs_annotations;
 
 	if (!bufmgr_gem->aub_file)
 		return;
 
-	/* Write out all but the batchbuffer to AUB memory */
-	for (i = 0; i < bufmgr_gem->exec_count - 1; i++) {
-		if (bufmgr_gem->exec_bos[i] != bo)
-			aub_write_bo(bufmgr_gem->exec_bos[i]);
+	/* If batch buffer is not annotated, annotate it the best we
+	 * can.
+	 */
+	batch_buffer_needs_annotations = bo_gem->aub_annotation_count == 0;
+	if (batch_buffer_needs_annotations) {
+		drm_intel_aub_annotation annotations[2] = {
+			{ AUB_TRACE_TYPE_BATCH, 0, used },
+			{ AUB_TRACE_TYPE_NOTYPE, 0, bo->size }
+		};
+		drm_intel_bufmgr_gem_set_aub_annotations(bo, annotations, 2);
 	}
 
-	aub_bo_get_address(bo);
+	/* Write out all buffers to AUB memory */
+	for (i = 0; i < bufmgr_gem->exec_count; i++) {
+		aub_write_bo(bufmgr_gem->exec_bos[i]);
+	}
 
-	/* Dump the batchbuffer. */
-	aub_write_trace_block(bo, AUB_TRACE_TYPE_BATCH, 0,
-			      0, used);
-	aub_write_trace_block(bo, AUB_TRACE_TYPE_NOTYPE, 0,
-			      used, bo->size - used);
+	/* Remove any annotations we added */
+	if (batch_buffer_needs_annotations)
+		drm_intel_bufmgr_gem_set_aub_annotations(bo, NULL, 0);
 
 	/* Dump ring buffer */
 	aub_build_dump_ringbuffer(bufmgr_gem, bo_gem->aub_offset, ring_flag);
@@ -2088,9 +2187,9 @@ drm_intel_gem_bo_exec(drm_intel_bo *bo, int used,
 }
 
 static int
-drm_intel_gem_bo_mrb_exec2(drm_intel_bo *bo, int used,
-			drm_clip_rect_t *cliprects, int num_cliprects, int DR4,
-			unsigned int flags)
+do_exec2(drm_intel_bo *bo, int used, drm_intel_context *ctx,
+	 drm_clip_rect_t *cliprects, int num_cliprects, int DR4,
+	 unsigned int flags)
 {
 	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *)bo->bufmgr;
 	struct drm_i915_gem_execbuffer2 execbuf;
@@ -2132,7 +2231,10 @@ drm_intel_gem_bo_mrb_exec2(drm_intel_bo *bo, int used,
 	execbuf.DR1 = 0;
 	execbuf.DR4 = DR4;
 	execbuf.flags = flags;
-	execbuf.rsvd1 = 0;
+	if (ctx == NULL)
+		i915_execbuffer2_set_context_id(execbuf, 0);
+	else
+		i915_execbuffer2_set_context_id(execbuf, ctx->ctx_id);
 	execbuf.rsvd2 = 0;
 
 	aub_exec(bo, flags, used);
@@ -2180,9 +2282,24 @@ drm_intel_gem_bo_exec2(drm_intel_bo *bo, int used,
 		       drm_clip_rect_t *cliprects, int num_cliprects,
 		       int DR4)
 {
-	return drm_intel_gem_bo_mrb_exec2(bo, used,
-					cliprects, num_cliprects, DR4,
-					I915_EXEC_RENDER);
+	return do_exec2(bo, used, NULL, cliprects, num_cliprects, DR4,
+			I915_EXEC_RENDER);
+}
+
+static int
+drm_intel_gem_bo_mrb_exec2(drm_intel_bo *bo, int used,
+			drm_clip_rect_t *cliprects, int num_cliprects, int DR4,
+			unsigned int flags)
+{
+	return do_exec2(bo, used, NULL, cliprects, num_cliprects, DR4,
+			flags);
+}
+
+int
+drm_intel_gem_bo_context_exec(drm_intel_bo *bo, drm_intel_context *ctx,
+			      int used, unsigned int flags)
+{
+	return do_exec2(bo, used, ctx, NULL, 0, 0, flags);
 }
 
 static int
@@ -2296,6 +2413,75 @@ drm_intel_gem_bo_get_tiling(drm_intel_bo *bo, uint32_t * tiling_mode,
 	return 0;
 }
 
+drm_intel_bo *
+drm_intel_bo_gem_create_from_prime(drm_intel_bufmgr *bufmgr, int prime_fd, int size)
+{
+	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bufmgr;
+	int ret;
+	uint32_t handle;
+	drm_intel_bo_gem *bo_gem;
+	struct drm_i915_gem_get_tiling get_tiling;
+
+	ret = drmPrimeFDToHandle(bufmgr_gem->fd, prime_fd, &handle);
+	if (ret) {
+	  fprintf(stderr,"ret is %d %d\n", ret, errno);
+		return NULL;
+	}
+
+	bo_gem = calloc(1, sizeof(*bo_gem));
+	if (!bo_gem)
+		return NULL;
+
+	bo_gem->bo.size = size;
+	bo_gem->bo.handle = handle;
+	bo_gem->bo.bufmgr = bufmgr;
+
+	bo_gem->gem_handle = handle;
+
+	atomic_set(&bo_gem->refcount, 1);
+
+	bo_gem->name = "prime";
+	bo_gem->validate_index = -1;
+	bo_gem->reloc_tree_fences = 0;
+	bo_gem->used_as_reloc_target = false;
+	bo_gem->has_error = false;
+	bo_gem->reusable = false;
+
+	DRMINITLISTHEAD(&bo_gem->name_list);
+	DRMINITLISTHEAD(&bo_gem->vma_list);
+
+	VG_CLEAR(get_tiling);
+	get_tiling.handle = bo_gem->gem_handle;
+	ret = drmIoctl(bufmgr_gem->fd,
+		       DRM_IOCTL_I915_GEM_GET_TILING,
+		       &get_tiling);
+	if (ret != 0) {
+		drm_intel_gem_bo_unreference(&bo_gem->bo);
+		return NULL;
+	}
+	bo_gem->tiling_mode = get_tiling.tiling_mode;
+	bo_gem->swizzle_mode = get_tiling.swizzle_mode;
+	/* XXX stride is unknown */
+	drm_intel_bo_gem_set_in_aperture_size(bufmgr_gem, bo_gem);
+
+	return &bo_gem->bo;
+}
+
+int
+drm_intel_bo_gem_export_to_prime(drm_intel_bo *bo, int *prime_fd)
+{
+	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr;
+	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
+
+	if (drmPrimeHandleToFD(bufmgr_gem->fd, bo_gem->gem_handle,
+			       DRM_CLOEXEC, prime_fd) != 0)
+		return -errno;
+
+	bo_gem->reusable = false;
+
+	return 0;
+}
+
 static int
 drm_intel_gem_bo_flink(drm_intel_bo *bo, uint32_t * name)
 {
@@ -2723,6 +2909,112 @@ drm_intel_bufmgr_gem_set_aub_dump(drm_intel_bufmgr *bufmgr, int enable)
 	}
 }
 
+drm_intel_context *
+drm_intel_gem_context_create(drm_intel_bufmgr *bufmgr)
+{
+	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *)bufmgr;
+	struct drm_i915_gem_context_create create;
+	drm_intel_context *context = NULL;
+	int ret;
+
+	VG_CLEAR(create);
+	ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GEM_CONTEXT_CREATE, &create);
+	if (ret != 0) {
+		DBG("DRM_IOCTL_I915_GEM_CONTEXT_CREATE failed: %s\n",
+		    strerror(errno));
+		return NULL;
+	}
+
+	context = calloc(1, sizeof(*context));
+	context->ctx_id = create.ctx_id;
+	context->bufmgr = bufmgr;
+
+	return context;
+}
+
+void
+drm_intel_gem_context_destroy(drm_intel_context *ctx)
+{
+	drm_intel_bufmgr_gem *bufmgr_gem;
+	struct drm_i915_gem_context_destroy destroy;
+	int ret;
+
+	if (ctx == NULL)
+		return;
+
+	VG_CLEAR(destroy);
+
+	bufmgr_gem = (drm_intel_bufmgr_gem *)ctx->bufmgr;
+	destroy.ctx_id = ctx->ctx_id;
+	ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GEM_CONTEXT_DESTROY,
+		       &destroy);
+	if (ret != 0)
+		fprintf(stderr, "DRM_IOCTL_I915_GEM_CONTEXT_DESTROY failed: %s\n",
+			strerror(errno));
+
+	free(ctx);
+}
+
+int
+drm_intel_reg_read(drm_intel_bufmgr *bufmgr,
+		   uint32_t offset,
+		   uint64_t *result)
+{
+	drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *)bufmgr;
+	struct drm_i915_reg_read reg_read;
+	int ret;
+
+	VG_CLEAR(reg_read);
+	reg_read.offset = offset;
+
+	ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_REG_READ, &reg_read);
+
+	*result = reg_read.val;
+	return ret;
+}
+
+
+/**
+ * Annotate the given bo for use in aub dumping.
+ *
+ * \param annotations is an array of drm_intel_aub_annotation objects
+ * describing the type of data in various sections of the bo.  Each
+ * element of the array specifies the type and subtype of a section of
+ * the bo, and the past-the-end offset of that section.  The elements
+ * of \c annotations must be sorted so that ending_offset is
+ * increasing.
+ *
+ * \param count is the number of elements in the \c annotations array.
+ * If \c count is zero, then \c annotations will not be dereferenced.
+ *
+ * Annotations are copied into a private data structure, so caller may
+ * re-use the memory pointed to by \c annotations after the call
+ * returns.
+ *
+ * Annotations are stored for the lifetime of the bo; to reset to the
+ * default state (no annotations), call this function with a \c count
+ * of zero.
+ */
+void
+drm_intel_bufmgr_gem_set_aub_annotations(drm_intel_bo *bo,
+					 drm_intel_aub_annotation *annotations,
+					 unsigned count)
+{
+	drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
+	unsigned size = sizeof(*annotations) * count;
+	drm_intel_aub_annotation *new_annotations =
+		count > 0 ? realloc(bo_gem->aub_annotations, size) : NULL;
+	if (new_annotations == NULL) {
+		free(bo_gem->aub_annotations);
+		bo_gem->aub_annotations = NULL;
+		bo_gem->aub_annotation_count = 0;
+		return;
+	}
+	memcpy(new_annotations, annotations, size);
+	bo_gem->aub_annotations = new_annotations;
+	bo_gem->aub_annotation_count = count;
+}
+
 /**
  * Initializes the GEM buffer manager, which uses the kernel to allocate, map,
  * and manage map buffer objections.
@@ -2778,9 +3070,11 @@ drm_intel_bufmgr_gem_init(int fd, int batch_size)
 	else if (IS_GEN6(bufmgr_gem->pci_device))
 		bufmgr_gem->gen = 6;
 	else if (IS_GEN7(bufmgr_gem->pci_device))
-        	bufmgr_gem->gen = 7;
-	else
-        	assert(0);
+		bufmgr_gem->gen = 7;
+	else {
+		free(bufmgr_gem);
+		return NULL;
+	}
 
 	if (IS_GEN3(bufmgr_gem->pci_device) &&
 	    bufmgr_gem->gtt_size > 256*1024*1024) {
@@ -2811,6 +3105,10 @@ drm_intel_bufmgr_gem_init(int fd, int batch_size)
 	ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GETPARAM, &gp);
 	bufmgr_gem->has_relaxed_fencing = ret == 0;
 
+	gp.param = I915_PARAM_HAS_WAIT_TIMEOUT;
+	ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GETPARAM, &gp);
+	bufmgr_gem->has_wait_timeout = ret == 0;
+
 	gp.param = I915_PARAM_HAS_LLC;
 	ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GETPARAM, &gp);
 	if (ret != 0) {
@@ -2820,7 +3118,7 @@ drm_intel_bufmgr_gem_init(int fd, int batch_size)
 		bufmgr_gem->has_llc = (IS_GEN6(bufmgr_gem->pci_device) |
 				IS_GEN7(bufmgr_gem->pci_device));
 	} else
-		bufmgr_gem->has_llc = ret == 0;
+		bufmgr_gem->has_llc = *gp.value;
 
 	if (bufmgr_gem->gen < 4) {
 		gp.param = I915_PARAM_NUM_FENCES_AVAIL;
diff --git a/intel/intel_bufmgr_priv.h b/intel/intel_bufmgr_priv.h
index 0b62520..2592d42 100644
--- a/intel/intel_bufmgr_priv.h
+++ b/intel/intel_bufmgr_priv.h
@@ -280,6 +280,11 @@ struct _drm_intel_bufmgr {
 	int debug;
 };
 
+struct _drm_intel_context {
+	unsigned int ctx_id;
+	struct _drm_intel_bufmgr *bufmgr;
+};
+
 #define ALIGN(value, alignment)	((value + alignment - 1) & ~(alignment - 1))
 #define ROUND_UP_TO(x, y)	(((x) + (y) - 1) / (y) * (y))
 #define ROUND_UP_TO_MB(x)	ROUND_UP_TO((x), 1024*1024)
diff --git a/intel/intel_chipset.h b/intel/intel_chipset.h
index 435d01a..a2eb894 100644
--- a/intel/intel_chipset.h
+++ b/intel/intel_chipset.h
@@ -44,12 +44,46 @@
 #define PCI_CHIP_IVYBRIDGE_M_GT1	0x0156 /* mobile */
 #define PCI_CHIP_IVYBRIDGE_M_GT2	0x0166
 #define PCI_CHIP_IVYBRIDGE_S		0x015a /* server */
+#define PCI_CHIP_IVYBRIDGE_S_GT2	0x016a /* server */
 
 #define PCI_CHIP_HASWELL_GT1            0x0402 /* Desktop */
 #define PCI_CHIP_HASWELL_GT2            0x0412
+#define PCI_CHIP_HASWELL_GT2_PLUS       0x0422
 #define PCI_CHIP_HASWELL_M_GT1          0x0406 /* Mobile */
 #define PCI_CHIP_HASWELL_M_GT2          0x0416
-#define PCI_CHIP_HASWELL_M_ULT_GT2      0x0A16 /* Mobile ULT */
+#define PCI_CHIP_HASWELL_M_GT2_PLUS     0x0426
+#define PCI_CHIP_HASWELL_S_GT1          0x040A /* Server */
+#define PCI_CHIP_HASWELL_S_GT2          0x041A
+#define PCI_CHIP_HASWELL_S_GT2_PLUS     0x042A
+#define PCI_CHIP_HASWELL_SDV_GT1        0x0C02 /* Desktop */
+#define PCI_CHIP_HASWELL_SDV_GT2        0x0C12
+#define PCI_CHIP_HASWELL_SDV_GT2_PLUS   0x0C22
+#define PCI_CHIP_HASWELL_SDV_M_GT1      0x0C06 /* Mobile */
+#define PCI_CHIP_HASWELL_SDV_M_GT2      0x0C16
+#define PCI_CHIP_HASWELL_SDV_M_GT2_PLUS 0x0C26
+#define PCI_CHIP_HASWELL_SDV_S_GT1      0x0C0A /* Server */
+#define PCI_CHIP_HASWELL_SDV_S_GT2      0x0C1A
+#define PCI_CHIP_HASWELL_SDV_S_GT2_PLUS 0x0C2A
+#define PCI_CHIP_HASWELL_ULT_GT1        0x0A02 /* Desktop */
+#define PCI_CHIP_HASWELL_ULT_GT2        0x0A12
+#define PCI_CHIP_HASWELL_ULT_GT2_PLUS   0x0A22
+#define PCI_CHIP_HASWELL_ULT_M_GT1      0x0A06 /* Mobile */
+#define PCI_CHIP_HASWELL_ULT_M_GT2      0x0A16
+#define PCI_CHIP_HASWELL_ULT_M_GT2_PLUS 0x0A26
+#define PCI_CHIP_HASWELL_ULT_S_GT1      0x0A0A /* Server */
+#define PCI_CHIP_HASWELL_ULT_S_GT2      0x0A1A
+#define PCI_CHIP_HASWELL_ULT_S_GT2_PLUS 0x0A2A
+#define PCI_CHIP_HASWELL_CRW_GT1        0x0D12 /* Desktop */
+#define PCI_CHIP_HASWELL_CRW_GT2        0x0D22
+#define PCI_CHIP_HASWELL_CRW_GT2_PLUS   0x0D32
+#define PCI_CHIP_HASWELL_CRW_M_GT1      0x0D16 /* Mobile */
+#define PCI_CHIP_HASWELL_CRW_M_GT2      0x0D26
+#define PCI_CHIP_HASWELL_CRW_M_GT2_PLUS 0x0D36
+#define PCI_CHIP_HASWELL_CRW_S_GT1      0x0D1A /* Server */
+#define PCI_CHIP_HASWELL_CRW_S_GT2      0x0D2A
+#define PCI_CHIP_HASWELL_CRW_S_GT2_PLUS 0x0D3A
+
+#define PCI_CHIP_VALLEYVIEW_PO		0x0f30 /* power on board */
 
 #define IS_830(dev) (dev == 0x3577)
 #define IS_845(dev) (dev == 0x2562)
@@ -90,6 +124,8 @@
 
 #define IS_I965GM(dev) (dev == 0x2A02)
 
+#define IS_VALLEYVIEW(dev) (dev == 0xf30)
+
 #define IS_GEN4(dev) (dev == 0x2972 ||	\
 		      dev == 0x2982 ||	\
 		      dev == 0x2992 ||	\
@@ -122,19 +158,52 @@
 			 dev == PCI_CHIP_SANDYBRIDGE_S)
 
 #define IS_GEN7(devid)          (IS_IVYBRIDGE(devid) || \
-                                 IS_HASWELL(devid))
+                                 IS_HASWELL(devid) || \
+				 IS_VALLEYVIEW(devid))
 
 #define IS_IVYBRIDGE(dev)	(dev == PCI_CHIP_IVYBRIDGE_GT1 || \
 				 dev == PCI_CHIP_IVYBRIDGE_GT2 || \
 				 dev == PCI_CHIP_IVYBRIDGE_M_GT1 || \
 				 dev == PCI_CHIP_IVYBRIDGE_M_GT2 || \
-				 dev == PCI_CHIP_IVYBRIDGE_S)
+				 dev == PCI_CHIP_IVYBRIDGE_S || \
+				 dev == PCI_CHIP_IVYBRIDGE_S_GT2)
 
 #define IS_HSW_GT1(devid)       (devid == PCI_CHIP_HASWELL_GT1 || \
-                                 devid == PCI_CHIP_HASWELL_M_GT1)
+				 devid == PCI_CHIP_HASWELL_M_GT1 || \
+				 devid == PCI_CHIP_HASWELL_S_GT1 || \
+				 devid == PCI_CHIP_HASWELL_SDV_GT1 || \
+				 devid == PCI_CHIP_HASWELL_SDV_M_GT1 || \
+				 devid == PCI_CHIP_HASWELL_SDV_S_GT1 || \
+				 devid == PCI_CHIP_HASWELL_ULT_GT1 || \
+				 devid == PCI_CHIP_HASWELL_ULT_M_GT1 || \
+				 devid == PCI_CHIP_HASWELL_ULT_S_GT1 || \
+				 devid == PCI_CHIP_HASWELL_CRW_GT1 || \
+				 devid == PCI_CHIP_HASWELL_CRW_M_GT1 || \
+				 devid == PCI_CHIP_HASWELL_CRW_S_GT1)
 #define IS_HSW_GT2(devid)       (devid == PCI_CHIP_HASWELL_GT2 || \
                                  devid == PCI_CHIP_HASWELL_M_GT2 || \
-                                 devid == PCI_CHIP_HASWELL_M_ULT_GT2)
+				 devid == PCI_CHIP_HASWELL_S_GT2 || \
+				 devid == PCI_CHIP_HASWELL_SDV_GT2 || \
+				 devid == PCI_CHIP_HASWELL_SDV_M_GT2 || \
+				 devid == PCI_CHIP_HASWELL_SDV_S_GT2 || \
+				 devid == PCI_CHIP_HASWELL_ULT_GT2 || \
+				 devid == PCI_CHIP_HASWELL_ULT_M_GT2 || \
+				 devid == PCI_CHIP_HASWELL_ULT_S_GT2 || \
+				 devid == PCI_CHIP_HASWELL_CRW_GT2 || \
+				 devid == PCI_CHIP_HASWELL_CRW_M_GT2 || \
+				 devid == PCI_CHIP_HASWELL_CRW_S_GT2 || \
+				 devid == PCI_CHIP_HASWELL_GT2_PLUS || \
+				 devid == PCI_CHIP_HASWELL_M_GT2_PLUS || \
+				 devid == PCI_CHIP_HASWELL_S_GT2_PLUS || \
+				 devid == PCI_CHIP_HASWELL_SDV_GT2_PLUS || \
+				 devid == PCI_CHIP_HASWELL_SDV_M_GT2_PLUS || \
+				 devid == PCI_CHIP_HASWELL_SDV_S_GT2_PLUS || \
+				 devid == PCI_CHIP_HASWELL_ULT_GT2_PLUS || \
+				 devid == PCI_CHIP_HASWELL_ULT_M_GT2_PLUS || \
+				 devid == PCI_CHIP_HASWELL_ULT_S_GT2_PLUS || \
+				 devid == PCI_CHIP_HASWELL_CRW_GT2_PLUS || \
+				 devid == PCI_CHIP_HASWELL_CRW_M_GT2_PLUS || \
+				 devid == PCI_CHIP_HASWELL_CRW_S_GT2_PLUS)
 
 #define IS_HASWELL(devid)       (IS_HSW_GT1(devid) || \
                                  IS_HSW_GT2(devid))
diff --git a/intel/intel_decode.c b/intel/intel_decode.c
index df9b704..a4b045a 100644
--- a/intel/intel_decode.c
+++ b/intel/intel_decode.c
@@ -139,6 +139,90 @@ instr_out(struct drm_intel_decode *ctx, unsigned int index,
 }
 
 static int
+decode_MI_SET_CONTEXT(struct drm_intel_decode *ctx)
+{
+	uint32_t data = ctx->data[1];
+	if (ctx->gen > 7)
+		return 1;
+
+	instr_out(ctx, 0, "MI_SET_CONTEXT\n");
+	instr_out(ctx, 1, "gtt offset = 0x%x%s%s\n",
+		  data & ~0xfff,
+		  data & (1<<1)? ", Force Restore": "",
+		  data & (1<<0)? ", Restore Inhibit": "");
+
+	return 2;
+}
+
+static int
+decode_MI_WAIT_FOR_EVENT(struct drm_intel_decode *ctx)
+{
+	const char *cc_wait;
+	int cc_shift = 0;
+	uint32_t data = ctx->data[0];
+
+	if (ctx->gen <= 5)
+		cc_shift = 9;
+	else
+		cc_shift = 16;
+
+	switch ((data >> cc_shift) & 0x1f) {
+	case 1:
+		cc_wait = ", cc wait 1";
+		break;
+	case 2:
+		cc_wait = ", cc wait 2";
+		break;
+	case 3:
+		cc_wait = ", cc wait 3";
+		break;
+	case 4:
+		cc_wait = ", cc wait 4";
+		break;
+	case 5:
+		cc_wait = ", cc wait 4";
+		break;
+	default:
+		cc_wait = "";
+		break;
+	}
+
+	if (ctx->gen <= 5) {
+		instr_out(ctx, 0, "MI_WAIT_FOR_EVENT%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n",
+			  data & (1<<18)? ", pipe B start vblank wait": "",
+			  data & (1<<17)? ", pipe A start vblank wait": "",
+			  data & (1<<16)? ", overlay flip pending wait": "",
+			  data & (1<<14)? ", pipe B hblank wait": "",
+			  data & (1<<13)? ", pipe A hblank wait": "",
+			  cc_wait,
+			  data & (1<<8)? ", plane C pending flip wait": "",
+			  data & (1<<7)? ", pipe B vblank wait": "",
+			  data & (1<<6)? ", plane B pending flip wait": "",
+			  data & (1<<5)? ", pipe B scan line wait": "",
+			  data & (1<<4)? ", fbc idle wait": "",
+			  data & (1<<3)? ", pipe A vblank wait": "",
+			  data & (1<<2)? ", plane A pending flip wait": "",
+			  data & (1<<1)? ", plane A scan line wait": "");
+	} else {
+		instr_out(ctx, 0, "MI_WAIT_FOR_EVENT%s%s%s%s%s%s%s%s%s%s%s%s\n",
+			  data & (1<<20)? ", sprite C pending flip wait": "", /* ivb */
+			  cc_wait,
+			  data & (1<<13)? ", pipe B hblank wait": "",
+			  data & (1<<11)? ", pipe B vblank wait": "",
+			  data & (1<<10)? ", sprite B pending flip wait": "",
+			  data & (1<<9)? ", plane B pending flip wait": "",
+			  data & (1<<8)? ", plane B scan line wait": "",
+			  data & (1<<5)? ", pipe A hblank wait": "",
+			  data & (1<<3)? ", pipe A vblank wait": "",
+			  data & (1<<2)? ", sprite A pending flip wait": "",
+			  data & (1<<1)? ", plane A pending flip wait": "",
+			  data & (1<<0)? ", plane A scan line wait": "");
+	}
+
+	return 1;
+}
+
+static int
 decode_mi(struct drm_intel_decode *ctx)
 {
 	unsigned int opcode, len = -1;
@@ -151,6 +235,7 @@ decode_mi(struct drm_intel_decode *ctx)
 		unsigned int min_len;
 		unsigned int max_len;
 		const char *name;
+		int (*func)(struct drm_intel_decode *ctx);
 	} opcodes_mi[] = {
 		{ 0x08, 0, 1, 1, "MI_ARB_ON_OFF" },
 		{ 0x0a, 0, 1, 1, "MI_BATCH_BUFFER_END" },
@@ -164,16 +249,16 @@ decode_mi(struct drm_intel_decode *ctx)
 		{ 0x00, 0, 1, 1, "MI_NOOP" },
 		{ 0x11, 0x3f, 2, 2, "MI_OVERLAY_FLIP" },
 		{ 0x07, 0, 1, 1, "MI_REPORT_HEAD" },
-		{ 0x18, 0x3f, 2, 2, "MI_SET_CONTEXT" },
+		{ 0x18, 0x3f, 2, 2, "MI_SET_CONTEXT", decode_MI_SET_CONTEXT },
 		{ 0x20, 0x3f, 3, 4, "MI_STORE_DATA_IMM" },
 		{ 0x21, 0x3f, 3, 4, "MI_STORE_DATA_INDEX" },
 		{ 0x24, 0x3f, 3, 3, "MI_STORE_REGISTER_MEM" },
 		{ 0x02, 0, 1, 1, "MI_USER_INTERRUPT" },
-		{ 0x03, 0, 1, 1, "MI_WAIT_FOR_EVENT" },
+		{ 0x03, 0, 1, 1, "MI_WAIT_FOR_EVENT", decode_MI_WAIT_FOR_EVENT },
 		{ 0x16, 0x7f, 3, 3, "MI_SEMAPHORE_MBOX" },
 		{ 0x26, 0x1f, 3, 4, "MI_FLUSH_DW" },
 		{ 0x0b, 0, 1, 1, "MI_SUSPEND_FLUSH"},
-	};
+	}, *opcode_mi = NULL;
 
 	/* check instruction length */
 	for (opcode = 0; opcode < sizeof(opcodes_mi) / sizeof(opcodes_mi[0]);
@@ -192,10 +277,14 @@ decode_mi(struct drm_intel_decode *ctx)
 						opcodes_mi[opcode].max_len);
 				}
 			}
+			opcode_mi = &opcodes_mi[opcode];
 			break;
 		}
 	}
 
+	if (opcode_mi && opcode_mi->func)
+		return opcode_mi->func(ctx);
+
 	switch ((data[0] & 0x1f800000) >> 23) {
 	case 0x0a:
 		instr_out(ctx, 0, "MI_BATCH_BUFFER_END\n");
@@ -1625,7 +1714,7 @@ decode_3d_1d(struct drm_intel_decode *ctx)
 					}
 				} else {
 					instr_out(ctx, i,
-						  "S%d: 0x%08x\n", i, data[i]);
+						  "S%d: 0x%08x\n", word, data[i]);
 				}
 				i++;
 			}
@@ -3115,6 +3204,8 @@ decode_3d_965(struct drm_intel_decode *ctx)
 		{ 0x7829, 0x00ff, 2, 2, "3DSTATE_BINDING_TABLE_POINTERS_GS" },
 		{ 0x782a, 0x00ff, 2, 2, "3DSTATE_BINDING_TABLE_POINTERS_PS" },
 		{ 0x782b, 0x00ff, 2, 2, "3DSTATE_SAMPLER_STATE_POINTERS_VS" },
+		{ 0x782c, 0x00ff, 2, 2, "3DSTATE_SAMPLER_STATE_POINTERS_HS" },
+		{ 0x782d, 0x00ff, 2, 2, "3DSTATE_SAMPLER_STATE_POINTERS_DS" },
 		{ 0x782e, 0x00ff, 2, 2, "3DSTATE_SAMPLER_STATE_POINTERS_GS" },
 		{ 0x782f, 0x00ff, 2, 2, "3DSTATE_SAMPLER_STATE_POINTERS_PS" },
 		{ 0x7830, 0x00ff, 2, 2, NULL, 7, gen7_3DSTATE_URB_VS },
@@ -3135,6 +3226,9 @@ decode_3d_965(struct drm_intel_decode *ctx)
 		{ 0x790d, 0xffff, 4, 4, "3DSTATE_MULTISAMPLE", 7 },
 		{ 0x7910, 0xffff, 2, 2, "3DSTATE_CLEAR_PARAMS" },
 		{ 0x7912, 0x00ff, 2, 2, "3DSTATE_PUSH_CONSTANT_ALLOC_VS" },
+		{ 0x7913, 0x00ff, 2, 2, "3DSTATE_PUSH_CONSTANT_ALLOC_HS" },
+		{ 0x7914, 0x00ff, 2, 2, "3DSTATE_PUSH_CONSTANT_ALLOC_DS" },
+		{ 0x7915, 0x00ff, 2, 2, "3DSTATE_PUSH_CONSTANT_ALLOC_GS" },
 		{ 0x7916, 0x00ff, 2, 2, "3DSTATE_PUSH_CONSTANT_ALLOC_PS" },
 		{ 0x7917, 0x00ff, 2, 2+128*2, "3DSTATE_SO_DECL_LIST" },
 		{ 0x7918, 0x00ff, 4, 4, "3DSTATE_SO_BUFFER" },
@@ -3312,8 +3406,8 @@ decode_3d_965(struct drm_intel_decode *ctx)
 			instr_out(ctx, i,
 				  "buffer %d: %svalid, type 0x%04x, "
 				  "src offset 0x%04x bytes\n",
-				  data[i] >> (IS_GEN6(devid) ? 26 : 27),
-				  data[i] & (1 << (IS_GEN6(devid) ? 25 : 26)) ?
+				  data[i] >> ((IS_GEN6(devid) || IS_GEN7(devid)) ? 26 : 27),
+				  data[i] & (1 << ((IS_GEN6(devid) || IS_GEN7(devid)) ? 25 : 26)) ?
 				  "" : "in", (data[i] >> 16) & 0x1ff,
 				  data[i] & 0x07ff);
 			i++;
diff --git a/intel/test_decode.c b/intel/test_decode.c
index c9ab7ad..0fcdf3b 100644
--- a/intel/test_decode.c
+++ b/intel/test_decode.c
@@ -21,6 +21,8 @@
  * IN THE SOFTWARE.
  */
 
+#define _GNU_SOURCE
+
 #include <string.h>
 #include <stdlib.h>
 #include <stdio.h>
diff --git a/intel/tests/gen7-3d.batch-ref.txt b/intel/tests/gen7-3d.batch-ref.txt
index be3c85e..cd2dfc4 100644
diff --git a/libdrm_lists.h b/libdrm_lists.h
index 6410f57..8926d8d 100644
--- a/libdrm_lists.h
+++ b/libdrm_lists.h
@@ -78,6 +78,13 @@ typedef struct _drmMMListHead
 
 #define DRMLISTEMPTY(__item) ((__item)->next == (__item))
 
+#define DRMLISTSINGLE(__list) \
+	(!DRMLISTEMPTY(__list) && ((__list)->next == (__list)->prev))
+
+#define DRMLISTFOREACH(__item, __list)					\
+	for ((__item) = (__list)->next;					\
+	     (__item) != (__list); (__item) = (__item)->next)
+
 #define DRMLISTFOREACHSAFE(__item, __temp, __list)			\
 	for ((__item) = (__list)->next, (__temp) = (__item)->next;	\
 	     (__item) != (__list);					\
@@ -87,3 +94,25 @@ typedef struct _drmMMListHead
 	for ((__item) = (__list)->prev, (__temp) = (__item)->prev;	\
 	     (__item) != (__list);					\
 	     (__item) = (__temp), (__temp) = (__item)->prev)
+
+#define DRMLISTFOREACHENTRY(__item, __list, __head)                            \
+	for ((__item) = DRMLISTENTRY(typeof(*__item), (__list)->next, __head); \
+	     &(__item)->__head != (__list);                                    \
+	     (__item) = DRMLISTENTRY(typeof(*__item),                          \
+				     (__item)->__head.next, __head))
+
+#define DRMLISTFOREACHENTRYSAFE(__item, __temp, __list, __head)                \
+	for ((__item) = DRMLISTENTRY(typeof(*__item), (__list)->next, __head), \
+	     (__temp) = DRMLISTENTRY(typeof(*__item),                          \
+				     (__item)->__head.next, __head);           \
+	     &(__item)->__head != (__list);                                    \
+	     (__item) = (__temp),                                              \
+	     (__temp) = DRMLISTENTRY(typeof(*__item),                          \
+				     (__temp)->__head.next, __head))
+
+#define DRMLISTJOIN(__list, __join) if (!DRMLISTEMPTY(__list)) {	\
+	(__list)->next->prev = (__join);				\
+	(__list)->prev->next = (__join)->next;				\
+	(__join)->next->prev = (__list)->prev;				\
+	(__join)->next = (__list)->next;				\
+}
diff --git a/libkms/Makefile.am b/libkms/Makefile.am
index fa379a4..215450a 100644
--- a/libkms/Makefile.am
+++ b/libkms/Makefile.am
@@ -6,7 +6,7 @@ AM_CFLAGS = \
 libkms_la_LTLIBRARIES = libkms.la
 libkms_ladir = $(libdir)
 libkms_la_LDFLAGS = -version-number 1:0:0 -no-undefined
-libkms_la_LIBADD =
+libkms_la_LIBADD = ../libdrm.la
 
 #if HAVE_LIBUDEV
 #libkms_la_LIBADD += $(LIBUDEV_LIBS)
diff --git a/man/Makefile.am b/man/Makefile.am
new file mode 100644
index 0000000..ccd6545
--- /dev/null
+++ b/man/Makefile.am
@@ -0,0 +1,11 @@
+libmandir = $(LIB_MAN_DIR)
+libman_PRE = drmAvailable.man \
+	drmHandleEvent.man \
+	drmModeGetResources.man
+libman_DATA = $(libman_PRE:man=@LIB_MAN_SUFFIX@)
+EXTRA_DIST = $(libman_PRE)
+CLEANFILES = $(libman_DATA)
+SUFFIXES = .$(LIB_MAN_SUFFIX) .man
+
+.man.$(LIB_MAN_SUFFIX):
+	$(AM_V_GEN)$(SED) $(MAN_SUBSTS) < $< > $@
diff --git a/man/drmAvailable.man b/man/drmAvailable.man
new file mode 100644
index 0000000..e1bb8dc
--- /dev/null
+++ b/man/drmAvailable.man
@@ -0,0 +1,25 @@
+.\" shorthand for double quote that works everywhere.
+.ds q \N'34'
+.TH drmAvailable  __drivermansuffix__ __vendorversion__
+.SH NAME
+drmAvailable \- determine whether a DRM kernel driver has been loaded
+.SH SYNOPSIS
+.nf
+.B "#include <xf86drm.h>"
+
+.B "int drmAvailable(void);"
+.fi
+.SH DESCRIPTION
+This function allows the caller to determine whether a kernel DRM driver is
+loaded.
+
+.SH RETURN VALUE
+If a DRM driver is currently loaded, this function returns 1.  Otherwise 0
+is returned.
+
+.SH REPORTING BUGS
+Bugs in this function should be reported to http://bugs.freedesktop.org under
+the "Mesa" product, with "Other" or "libdrm" as the component.
+
+.SH "SEE ALSO"
+drmOpen(__libmansuffix__)
diff --git a/man/drmHandleEvent.man b/man/drmHandleEvent.man
new file mode 100644
index 0000000..b98f417
--- /dev/null
+++ b/man/drmHandleEvent.man
@@ -0,0 +1,45 @@
+.\" shorthand for double quote that works everywhere.
+.ds q \N'34'
+.TH drmHandleEvent  __drivermansuffix__ __vendorversion__
+.SH NAME
+drmHandleEvent \- read and process pending DRM events
+.SH SYNOPSIS
+.nf
+.B "#include <xf86drm.h>"
+
+.B "typedef struct _drmEventContext {"
+.BI "	int version;"
+.BI "	void (*vblank_handler)(int fd,"
+.BI "			       unsigned int sequence,"
+.BI "			       unsigned int tv_sec,"
+.BI "			       unsigned int tv_usec,"
+.BI "			       void *user_data);"
+.BI "	void (*page_flip_handler)(int fd,"
+.BI "				  unsigned int sequence,"
+.BI "				  unsigned int tv_sec,"
+.BI "				  unsigned int tv_usec,"
+.BI "				  void *user_data);"
+.B "} drmEventContext, *drmEventContextPtr;"
+
+.B "int drmHandleEvent(int fd, drmEventContextPtr evctx);"
+.fi
+.SH DESCRIPTION
+This function will process outstanding DRM events on
+.I fd
+, which must be an open DRM device.  This function should be called after
+the DRM file descriptor has polled readable; it will read the events and
+use the passed-in
+.I evctx
+structure to call function pointers with the parameters noted above.
+
+.SH RETURN VALUE
+Returns 0 on success, or if there is no data to read from the file descriptor.
+Returns -1 if the read on the file descriptor fails or returns less than a
+full event record.
+
+.SH REPORTING BUGS
+Bugs in this function should be reported to http://bugs.freedesktop.org under
+the "Mesa" product, with "Other" or "libdrm" as the component.
+
+.SH "SEE ALSO"
+drmModePageFlip(__libmansuffix__), drmWaitVBlank(__libmansuffix__)
diff --git a/man/drmModeGetResources.man b/man/drmModeGetResources.man
new file mode 100644
index 0000000..369bf7d
--- /dev/null
+++ b/man/drmModeGetResources.man
@@ -0,0 +1,79 @@
+.\" shorthand for double quote that works everywhere.
+.ds q \N'34'
+.TH drmModeGetResources  __drivermansuffix__ __vendorversion__
+.SH NAME
+drmModeGetResources \- retrieve current display configuration information
+.SH SYNOPSIS
+.nf
+.B "#include <xf86drmMode.h>"
+
+.BI "typedef struct _drmModeRes {"
+
+.BI "	int count_fbs;"
+.BI "	uint32_t *fbs;"
+
+.BI "	int count_crtcs;"
+.BI "	uint32_t *crtcs;"
+
+.BI "	int count_connectors;"
+.BI "	uint32_t *connectors;"
+
+.BI "	int count_encoders;"
+.BI "	uint32_t *encoders;"
+
+.BI "	uint32_t min_width, max_width;"
+.BI "	uint32_t min_height, max_height;"
+.B "} drmModeRes, *drmModeResPtr;"
+
+.B "drmModeResPtr drmModeGetResources(int fd);"
+.fi
+.SH DESCRIPTION
+This function will allocate, populate, and return a drmModeRes structure
+containing information about the current display configuration.
+
+The
+.I count_fbs
+and
+.I fbs
+fields indicate the number of currently allocated framebuffer objects (i.e.
+objects that can be attached to a given CRTC or sprite for display).
+
+The
+.I count_crtcs
+and
+.I crtcs
+fields list the available CRTCs in the configuration.  A CRTC is simply
+an object that can scan out a framebuffer to a display sink, and contains
+mode timing and relative position information.  CRTCs drive encoders, which
+are responsible for converting the pixel stream into a specific display
+protocol (e.g. MIPI or HDMI).
+
+The
+.I count_connectors
+and
+.I connectors
+fields list the available physical connectors on the system.  Note that
+some of these may not be exposed from the chassis (e.g. LVDS or eDP).
+Connectors are attached to encoders and contain information about the
+attached display sink (e.g. width and height in mm, subpixel ordering, and
+various other properties).
+
+The
+.I count_encoders
+and
+.I encoders
+fields list the available encoders on the device.  Each encoder may be
+associated with a CRTC, and may be used to drive a particular encoder.
+
+The min and max height fields indicate the maximum size of a framebuffer
+for this device (i.e. the scanout size limit).
+
+.SH RETURN VALUE
+Returns a drmModeRes structure pointer on success, 0 on failure.
+
+.SH REPORTING BUGS
+Bugs in this function should be reported to http://bugs.freedesktop.org under
+the "Mesa" product, with "Other" or "libdrm" as the component.
+
+.SH "SEE ALSO"
+drmModeGetFB(__libmansuffix__), drmModeAddFB(__libmansuffix__), drmModeAddFB2(__libmansuffix__), drmModeRmFB(__libmansuffix__), drmModeDirtyFB(__libmansuffix__), drmModeGetCrtc(__libmansuffix__), drmModeSetCrtc(__libmansuffix__), drmModeGetEncoder(__libmansuffix__), drmModeGetConnector(__libmansuffix__)
diff --git a/nouveau/Makefile.am b/nouveau/Makefile.am
index 8b89916..206e892 100644
diff --git a/nouveau/abi16.c b/nouveau/abi16.c
new file mode 100644
index 0000000..a67fbc1
diff --git a/nouveau/bufctx.c b/nouveau/bufctx.c
new file mode 100644
index 0000000..23d6f09
diff --git a/nouveau/libdrm_nouveau.pc.in b/nouveau/libdrm_nouveau.pc.in
index c78a28a..6170613 100644
diff --git a/nouveau/nouveau.c b/nouveau/nouveau.c
new file mode 100644
index 0000000..940d933
diff --git a/nouveau/nouveau.h b/nouveau/nouveau.h
new file mode 100644
index 0000000..c42eea7
diff --git a/nouveau/nouveau_bo.c b/nouveau/nouveau_bo.c
deleted file mode 100644
index d6bb22d..0000000
diff --git a/nouveau/nouveau_bo.h b/nouveau/nouveau_bo.h
deleted file mode 100644
index 3a1f2d4..0000000
diff --git a/nouveau/nouveau_channel.c b/nouveau/nouveau_channel.c
deleted file mode 100644
index 96fa03b..0000000
diff --git a/nouveau/nouveau_channel.h b/nouveau/nouveau_channel.h
deleted file mode 100644
index d61a4c0..0000000
diff --git a/nouveau/nouveau_device.c b/nouveau/nouveau_device.c
deleted file mode 100644
index 425c5d2..0000000
diff --git a/nouveau/nouveau_device.h b/nouveau/nouveau_device.h
deleted file mode 100644
index c0d9333..0000000
diff --git a/nouveau/nouveau_drmif.h b/nouveau/nouveau_drmif.h
deleted file mode 100644
index ec226a2..0000000
diff --git a/nouveau/nouveau_grobj.c b/nouveau/nouveau_grobj.c
deleted file mode 100644
index 36344b9..0000000
diff --git a/nouveau/nouveau_grobj.h b/nouveau/nouveau_grobj.h
deleted file mode 100644
index 51ac7d9..0000000
diff --git a/nouveau/nouveau_notifier.c b/nouveau/nouveau_notifier.c
deleted file mode 100644
index 513fa63..0000000
diff --git a/nouveau/nouveau_notifier.h b/nouveau/nouveau_notifier.h
deleted file mode 100644
index dbc6a3b..0000000
diff --git a/nouveau/nouveau_private.h b/nouveau/nouveau_private.h
deleted file mode 100644
index 124fe87..0000000
diff --git a/nouveau/nouveau_pushbuf.c b/nouveau/nouveau_pushbuf.c
deleted file mode 100644
index 59f60d9..0000000
diff --git a/nouveau/nouveau_pushbuf.h b/nouveau/nouveau_pushbuf.h
deleted file mode 100644
index 2a98789..0000000
diff --git a/nouveau/nouveau_reloc.c b/nouveau/nouveau_reloc.c
deleted file mode 100644
index cd219db..0000000
diff --git a/nouveau/nouveau_reloc.h b/nouveau/nouveau_reloc.h
deleted file mode 100644
index 24ddb52..0000000
diff --git a/nouveau/nouveau_resource.c b/nouveau/nouveau_resource.c
deleted file mode 100644
index 7acaf7d..0000000
diff --git a/nouveau/nouveau_resource.h b/nouveau/nouveau_resource.h
deleted file mode 100644
index b760dfb..0000000
diff --git a/nouveau/nv04_pushbuf.h b/nouveau/nv04_pushbuf.h
deleted file mode 100644
index 586b284..0000000
diff --git a/nouveau/nvc0_pushbuf.h b/nouveau/nvc0_pushbuf.h
deleted file mode 100644
index 40dc7e6..0000000
diff --git a/nouveau/private.h b/nouveau/private.h
new file mode 100644
index 0000000..b409cc8
diff --git a/nouveau/pushbuf.c b/nouveau/pushbuf.c
new file mode 100644
index 0000000..0e37ce3
diff --git a/omap/omap_drm.c b/omap/omap_drm.c
index e611806..89f1491 100644
--- a/omap/omap_drm.c
+++ b/omap/omap_drm.c
@@ -32,10 +32,15 @@
 
 #include <stdlib.h>
 #include <linux/stddef.h>
+#include <linux/types.h>
 #include <errno.h>
 #include <sys/mman.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <pthread.h>
 
 #include <xf86drm.h>
+#include <xf86atomic.h>
 
 #include "omap_drm.h"
 #include "omap_drmif.h"
@@ -44,8 +49,23 @@
 #define round_up(x, y) ((((x)-1) | __round_mask(x, y))+1)
 #define PAGE_SIZE 4096
 
+static pthread_mutex_t table_lock = PTHREAD_MUTEX_INITIALIZER;
+static void * dev_table;
+
 struct omap_device {
 	int fd;
+	atomic_t refcnt;
+
+	/* The handle_table is used to track GEM bo handles associated w/
+	 * this fd.  This is needed, in particular, when importing
+	 * dmabuf's because we don't want multiple 'struct omap_bo's
+	 * floating around with the same handle.  Otherwise, when the
+	 * first one is omap_bo_del()'d the handle becomes no longer
+	 * valid, and the remaining 'struct omap_bo's are left pointing
+	 * to an invalid handle (and possible a GEM bo that is already
+	 * free'd).
+	 */
+	void *handle_table;
 };
 
 /* a GEM buffer object allocated from the DRM device */
@@ -56,19 +76,58 @@ struct omap_bo {
 	uint32_t	handle;
 	uint32_t	name;		/* flink global handle (DRI2 name) */
 	uint64_t	offset;		/* offset to mmap() */
+	int		fd;		/* dmabuf handle */
+	atomic_t	refcnt;
 };
 
-struct omap_device * omap_device_new(int fd)
+static struct omap_device * omap_device_new_impl(int fd)
 {
 	struct omap_device *dev = calloc(sizeof(*dev), 1);
 	if (!dev)
 		return NULL;
 	dev->fd = fd;
+	atomic_set(&dev->refcnt, 1);
+	dev->handle_table = drmHashCreate();
+	return dev;
+}
+
+struct omap_device * omap_device_new(int fd)
+{
+	struct omap_device *dev = NULL;
+
+	pthread_mutex_lock(&table_lock);
+
+	if (!dev_table)
+		dev_table = drmHashCreate();
+
+	if (drmHashLookup(dev_table, fd, (void **)&dev)) {
+		/* not found, create new device */
+		dev = omap_device_new_impl(fd);
+		drmHashInsert(dev_table, fd, dev);
+	} else {
+		/* found, just incr refcnt */
+		dev = omap_device_ref(dev);
+	}
+
+	pthread_mutex_unlock(&table_lock);
+
+	return dev;
+}
+
+struct omap_device * omap_device_ref(struct omap_device *dev)
+{
+	atomic_inc(&dev->refcnt);
 	return dev;
 }
 
 void omap_device_del(struct omap_device *dev)
 {
+	if (!atomic_dec_and_test(&dev->refcnt))
+		return;
+	pthread_mutex_lock(&table_lock);
+	drmHashDestroy(dev->handle_table);
+	drmHashDelete(dev_table, dev->fd);
+	pthread_mutex_unlock(&table_lock);
 	free(dev);
 }
 
@@ -98,11 +157,43 @@ int omap_set_param(struct omap_device *dev, uint64_t param, uint64_t value)
 	return drmCommandWrite(dev->fd, DRM_OMAP_SET_PARAM, &req, sizeof(req));
 }
 
+/* lookup a buffer from it's handle, call w/ table_lock held: */
+static struct omap_bo * lookup_bo(struct omap_device *dev,
+		uint32_t handle)
+{
+	struct omap_bo *bo = NULL;
+	if (!drmHashLookup(dev->handle_table, handle, (void **)&bo)) {
+		/* found, incr refcnt and return: */
+		bo = omap_bo_ref(bo);
+	}
+	return bo;
+}
+
+/* allocate a new buffer object, call w/ table_lock held */
+static struct omap_bo * bo_from_handle(struct omap_device *dev,
+		uint32_t handle)
+{
+	struct omap_bo *bo = calloc(sizeof(*bo), 1);
+	if (!bo) {
+		struct drm_gem_close req = {
+				.handle = handle,
+		};
+		drmIoctl(dev->fd, DRM_IOCTL_GEM_CLOSE, &req);
+		return NULL;
+	}
+	bo->dev = omap_device_ref(dev);
+	bo->handle = handle;
+	atomic_set(&bo->refcnt, 1);
+	/* add ourselves to the handle table: */
+	drmHashInsert(dev->handle_table, handle, bo);
+	return bo;
+}
+
 /* allocate a new buffer object */
 static struct omap_bo * omap_bo_new_impl(struct omap_device *dev,
 		union omap_gem_size size, uint32_t flags)
 {
-	struct omap_bo *bo;
+	struct omap_bo *bo = NULL;
 	struct drm_omap_gem_new req = {
 			.size = size,
 			.flags = flags,
@@ -112,12 +203,13 @@ static struct omap_bo * omap_bo_new_impl(struct omap_device *dev,
 		goto fail;
 	}
 
-	bo = calloc(sizeof(*bo), 1);
-	if (!bo) {
+	if (drmCommandWriteRead(dev->fd, DRM_OMAP_GEM_NEW, &req, sizeof(req))) {
 		goto fail;
 	}
 
-	bo->dev = dev;
+	pthread_mutex_lock(&table_lock);
+	bo = bo_from_handle(dev, req.handle);
+	pthread_mutex_unlock(&table_lock);
 
 	if (flags & OMAP_BO_TILED) {
 		bo->size = round_up(size.tiled.width, PAGE_SIZE) * size.tiled.height;
@@ -125,12 +217,6 @@ static struct omap_bo * omap_bo_new_impl(struct omap_device *dev,
 		bo->size = size.bytes;
 	}
 
-	if (drmCommandWriteRead(dev->fd, DRM_OMAP_GEM_NEW, &req, sizeof(req))) {
-		goto fail;
-	}
-
-	bo->handle = req.handle;
-
 	return bo;
 
 fail:
@@ -168,6 +254,12 @@ struct omap_bo * omap_bo_new_tiled(struct omap_device *dev,
 	return omap_bo_new_impl(dev, gsize, flags);
 }
 
+struct omap_bo * omap_bo_ref(struct omap_bo *bo)
+{
+	atomic_inc(&bo->refcnt);
+	return bo;
+}
+
 /* get buffer info */
 static int get_buffer_info(struct omap_bo *bo)
 {
@@ -190,27 +282,63 @@ static int get_buffer_info(struct omap_bo *bo)
 /* import a buffer object from DRI2 name */
 struct omap_bo * omap_bo_from_name(struct omap_device *dev, uint32_t name)
 {
-	struct omap_bo *bo;
+	struct omap_bo *bo = NULL;
 	struct drm_gem_open req = {
 			.name = name,
 	};
 
-	bo = calloc(sizeof(*bo), 1);
-	if (!bo) {
+	pthread_mutex_lock(&table_lock);
+
+	if (drmIoctl(dev->fd, DRM_IOCTL_GEM_OPEN, &req)) {
 		goto fail;
 	}
 
-	if (drmIoctl(dev->fd, DRM_IOCTL_GEM_OPEN, &req)) {
+	bo = lookup_bo(dev, req.handle);
+	if (!bo) {
+		bo = bo_from_handle(dev, req.handle);
+		bo->name = name;
+	}
+
+	pthread_mutex_unlock(&table_lock);
+
+	return bo;
+
+fail:
+	pthread_mutex_unlock(&table_lock);
+	free(bo);
+	return NULL;
+}
+
+/* import a buffer from dmabuf fd, does not take ownership of the
+ * fd so caller should close() the fd when it is otherwise done
+ * with it (even if it is still using the 'struct omap_bo *')
+ */
+struct omap_bo * omap_bo_from_dmabuf(struct omap_device *dev, int fd)
+{
+	struct omap_bo *bo = NULL;
+	struct drm_prime_handle req = {
+			.fd = fd,
+	};
+	int ret;
+
+	pthread_mutex_lock(&table_lock);
+
+	ret = drmIoctl(dev->fd, DRM_IOCTL_PRIME_FD_TO_HANDLE, &req);
+	if (ret) {
 		goto fail;
 	}
 
-	bo->dev = dev;
-	bo->name = name;
-	bo->handle = req.handle;
+	bo = lookup_bo(dev, req.handle);
+	if (!bo) {
+		bo = bo_from_handle(dev, req.handle);
+	}
+
+	pthread_mutex_unlock(&table_lock);
 
 	return bo;
 
 fail:
+	pthread_mutex_unlock(&table_lock);
 	free(bo);
 	return NULL;
 }
@@ -222,18 +350,29 @@ void omap_bo_del(struct omap_bo *bo)
 		return;
 	}
 
+	if (!atomic_dec_and_test(&bo->refcnt))
+		return;
+
 	if (bo->map) {
 		munmap(bo->map, bo->size);
 	}
 
+	if (bo->fd) {
+		close(bo->fd);
+	}
+
 	if (bo->handle) {
 		struct drm_gem_close req = {
 				.handle = bo->handle,
 		};
-
+		pthread_mutex_lock(&table_lock);
+		drmHashDelete(bo->dev->handle_table, bo->handle);
 		drmIoctl(bo->dev->fd, DRM_IOCTL_GEM_CLOSE, &req);
+		pthread_mutex_unlock(&table_lock);
 	}
 
+	omap_device_del(bo->dev);
+
 	free(bo);
 }
 
@@ -264,6 +403,28 @@ uint32_t omap_bo_handle(struct omap_bo *bo)
 	return bo->handle;
 }
 
+/* caller owns the dmabuf fd that is returned and is responsible
+ * to close() it when done
+ */
+int omap_bo_dmabuf(struct omap_bo *bo)
+{
+	if (!bo->fd) {
+		struct drm_prime_handle req = {
+				.handle = bo->handle,
+				.flags = DRM_CLOEXEC,
+		};
+		int ret;
+
+		ret = drmIoctl(bo->dev->fd, DRM_IOCTL_PRIME_HANDLE_TO_FD, &req);
+		if (ret) {
+			return ret;
+		}
+
+		bo->fd = req.fd;
+	}
+	return dup(bo->fd);
+}
+
 uint32_t omap_bo_size(struct omap_bo *bo)
 {
 	if (!bo->size) {
diff --git a/omap/omap_drm.h b/omap/omap_drm.h
index f277cea..9c6c0e4 100644
--- a/omap/omap_drm.h
+++ b/omap/omap_drm.h
@@ -1,26 +1,36 @@
+/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
+
 /*
- * include/drm/omap_drm.h
+ * Copyright (C) 2011 Texas Instruments, Inc
  *
- * Copyright (C) 2011 Texas Instruments
- * Author: Rob Clark <rob@ti.com>
+ * 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:
  *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published by
- * the Free Software Foundation.
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
  *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
+ * 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 AUTHORS OR COPYRIGHT HOLDERS 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.
  *
- * You should have received a copy of the GNU General Public License along with
- * this program.  If not, see <http://www.gnu.org/licenses/>.
+ * Authors:
+ *    Rob Clark <rob@ti.com>
  */
 
 #ifndef __OMAP_DRM_H__
 #define __OMAP_DRM_H__
 
-#include "drm.h"
+#include <stdint.h>
+#include <drm.h>
 
 /* Please note that modifications to all structs defined here are
  * subject to backwards-compatibility constraints.
diff --git a/omap/omap_drmif.h b/omap/omap_drmif.h
index eb75a80..e62d127 100644
--- a/omap/omap_drmif.h
+++ b/omap/omap_drmif.h
@@ -38,6 +38,7 @@ struct omap_device;
  */
 
 struct omap_device * omap_device_new(int fd);
+struct omap_device * omap_device_ref(struct omap_device *dev);
 void omap_device_del(struct omap_device *dev);
 int omap_get_param(struct omap_device *dev, uint64_t param, uint64_t *value);
 int omap_set_param(struct omap_device *dev, uint64_t param, uint64_t value);
@@ -49,10 +50,13 @@ struct omap_bo * omap_bo_new(struct omap_device *dev,
 		uint32_t size, uint32_t flags);
 struct omap_bo * omap_bo_new_tiled(struct omap_device *dev,
 		uint32_t width, uint32_t height, uint32_t flags);
+struct omap_bo * omap_bo_ref(struct omap_bo *bo);
 struct omap_bo * omap_bo_from_name(struct omap_device *dev, uint32_t name);
+struct omap_bo * omap_bo_from_dmabuf(struct omap_device *dev, int fd);
 void omap_bo_del(struct omap_bo *bo);
 int omap_bo_get_name(struct omap_bo *bo, uint32_t *name);
 uint32_t omap_bo_handle(struct omap_bo *bo);
+int omap_bo_dmabuf(struct omap_bo *bo);
 uint32_t omap_bo_size(struct omap_bo *bo);
 void * omap_bo_map(struct omap_bo *bo);
 int omap_bo_cpu_prep(struct omap_bo *bo, enum omap_gem_op op);
diff --git a/radeon/Makefile.am b/radeon/Makefile.am
index 37be8cc..a8cd100 100644
--- a/radeon/Makefile.am
+++ b/radeon/Makefile.am
@@ -31,7 +31,7 @@ AM_CFLAGS = \
 
 libdrm_radeon_la_LTLIBRARIES = libdrm_radeon.la
 libdrm_radeon_ladir = $(libdir)
-libdrm_radeon_la_LDFLAGS = -version-number 1:0:0 -no-undefined
+libdrm_radeon_la_LDFLAGS = -version-number 1:0:1 -no-undefined
 libdrm_radeon_la_LIBADD = ../libdrm.la @PTHREADSTUBS_LIBS@
 
 libdrm_radeon_la_SOURCES = \
diff --git a/radeon/r600_pci_ids.h b/radeon/r600_pci_ids.h
index 8fbd749..b9a85db 100644
--- a/radeon/r600_pci_ids.h
+++ b/radeon/r600_pci_ids.h
@@ -152,10 +152,12 @@ CHIPSET(0x68F1, CEDAR_68F1, CEDAR)
 CHIPSET(0x68F2, CEDAR_68F2, CEDAR)
 CHIPSET(0x68F8, CEDAR_68F8, CEDAR)
 CHIPSET(0x68F9, CEDAR_68F9, CEDAR)
+CHIPSET(0x68FA, CEDAR_68FA, CEDAR)
 CHIPSET(0x68FE, CEDAR_68FE, CEDAR)
 
 CHIPSET(0x68C0, REDWOOD_68C0, REDWOOD)
 CHIPSET(0x68C1, REDWOOD_68C1, REDWOOD)
+CHIPSET(0x68C7, REDWOOD_68C7, REDWOOD)
 CHIPSET(0x68C8, REDWOOD_68C8, REDWOOD)
 CHIPSET(0x68C9, REDWOOD_68C9, REDWOOD)
 CHIPSET(0x68D8, REDWOOD_68D8, REDWOOD)
@@ -178,6 +180,8 @@ CHIPSET(0x6880, CYPRESS_6880, CYPRESS)
 CHIPSET(0x6888, CYPRESS_6888, CYPRESS)
 CHIPSET(0x6889, CYPRESS_6889, CYPRESS)
 CHIPSET(0x688A, CYPRESS_688A, CYPRESS)
+CHIPSET(0x688C, CYPRESS_688C, CYPRESS)
+CHIPSET(0x688D, CYPRESS_688D, CYPRESS)
 CHIPSET(0x6898, CYPRESS_6898, CYPRESS)
 CHIPSET(0x6899, CYPRESS_6899, CYPRESS)
 CHIPSET(0x689B, CYPRESS_689B, CYPRESS)
@@ -192,6 +196,9 @@ CHIPSET(0x9804, PALM_9804, PALM)
 CHIPSET(0x9805, PALM_9805, PALM)
 CHIPSET(0x9806, PALM_9806, PALM)
 CHIPSET(0x9807, PALM_9807, PALM)
+CHIPSET(0x9808, PALM_9808, PALM)
+CHIPSET(0x9809, PALM_9809, PALM)
+CHIPSET(0x980A, PALM_980A, PALM)
 
 CHIPSET(0x9640, SUMO_9640,  SUMO)
 CHIPSET(0x9641, SUMO_9641,  SUMO)
@@ -201,7 +208,10 @@ CHIPSET(0x9644, SUMO2_9644, SUMO2)
 CHIPSET(0x9645, SUMO2_9645, SUMO2)
 CHIPSET(0x9647, SUMO_9647,  SUMO)
 CHIPSET(0x9648, SUMO_9648,  SUMO)
+CHIPSET(0x9649, SUMO_9649,  SUMO)
 CHIPSET(0x964a, SUMO_964A,  SUMO)
+CHIPSET(0x964b, SUMO_964B,  SUMO)
+CHIPSET(0x964c, SUMO_964C,  SUMO)
 CHIPSET(0x964e, SUMO_964E,  SUMO)
 CHIPSET(0x964f, SUMO_964F,  SUMO)
 
@@ -234,6 +244,7 @@ CHIPSET(0x6729, BARTS_6729, BARTS)
 CHIPSET(0x6738, BARTS_6738, BARTS)
 CHIPSET(0x6739, BARTS_6739, BARTS)
 CHIPSET(0x673E, BARTS_673E, BARTS)
+
 CHIPSET(0x6740, TURKS_6740, TURKS)
 CHIPSET(0x6741, TURKS_6741, TURKS)
 CHIPSET(0x6742, TURKS_6742, TURKS)
@@ -244,9 +255,13 @@ CHIPSET(0x6746, TURKS_6746, TURKS)
 CHIPSET(0x6747, TURKS_6747, TURKS)
 CHIPSET(0x6748, TURKS_6748, TURKS)
 CHIPSET(0x6749, TURKS_6749, TURKS)
+CHIPSET(0x674A, TURKS_674A, TURKS)
 CHIPSET(0x6750, TURKS_6750, TURKS)
+CHIPSET(0x6751, TURKS_6751, TURKS)
 CHIPSET(0x6758, TURKS_6758, TURKS)
 CHIPSET(0x6759, TURKS_6759, TURKS)
+CHIPSET(0x675B, TURKS_675B, TURKS)
+CHIPSET(0x675D, TURKS_675D, TURKS)
 CHIPSET(0x675F, TURKS_675F, TURKS)
 CHIPSET(0x6840, TURKS_6840, TURKS)
 CHIPSET(0x6841, TURKS_6841, TURKS)
@@ -267,13 +282,81 @@ CHIPSET(0x6766, CAICOS_6766, CAICOS)
 CHIPSET(0x6767, CAICOS_6767, CAICOS)
 CHIPSET(0x6768, CAICOS_6768, CAICOS)
 CHIPSET(0x6770, CAICOS_6770, CAICOS)
+CHIPSET(0x6771, CAICOS_6771, CAICOS)
+CHIPSET(0x6772, CAICOS_6772, CAICOS)
 CHIPSET(0x6778, CAICOS_6778, CAICOS)
 CHIPSET(0x6779, CAICOS_6779, CAICOS)
+CHIPSET(0x677B, CAICOS_677B, CAICOS)
 
 CHIPSET(0x9900, ARUBA_9900, ARUBA)
 CHIPSET(0x9901, ARUBA_9901, ARUBA)
 CHIPSET(0x9903, ARUBA_9903, ARUBA)
 CHIPSET(0x9904, ARUBA_9904, ARUBA)
+CHIPSET(0x9905, ARUBA_9905, ARUBA)
+CHIPSET(0x9906, ARUBA_9906, ARUBA)
+CHIPSET(0x9907, ARUBA_9907, ARUBA)
+CHIPSET(0x9908, ARUBA_9908, ARUBA)
+CHIPSET(0x9909, ARUBA_9909, ARUBA)
+CHIPSET(0x990A, ARUBA_990A, ARUBA)
 CHIPSET(0x990F, ARUBA_990F, ARUBA)
+CHIPSET(0x9910, ARUBA_9910, ARUBA)
+CHIPSET(0x9913, ARUBA_9913, ARUBA)
+CHIPSET(0x9917, ARUBA_9917, ARUBA)
+CHIPSET(0x9918, ARUBA_9918, ARUBA)
+CHIPSET(0x9919, ARUBA_9919, ARUBA)
 CHIPSET(0x9990, ARUBA_9990, ARUBA)
 CHIPSET(0x9991, ARUBA_9991, ARUBA)
+CHIPSET(0x9992, ARUBA_9992, ARUBA)
+CHIPSET(0x9993, ARUBA_9993, ARUBA)
+CHIPSET(0x9994, ARUBA_9994, ARUBA)
+CHIPSET(0x99A0, ARUBA_99A0, ARUBA)
+CHIPSET(0x99A2, ARUBA_99A2, ARUBA)
+CHIPSET(0x99A4, ARUBA_99A4, ARUBA)
+
+CHIPSET(0x6780, TAHITI_6780, TAHITI)
+CHIPSET(0x6784, TAHITI_6784, TAHITI)
+CHIPSET(0x6788, TAHITI_6788, TAHITI)
+CHIPSET(0x678A, TAHITI_678A, TAHITI)
+CHIPSET(0x6790, TAHITI_6790, TAHITI)
+CHIPSET(0x6791, TAHITI_6791, TAHITI)
+CHIPSET(0x6792, TAHITI_6792, TAHITI)
+CHIPSET(0x6798, TAHITI_6798, TAHITI)
+CHIPSET(0x6799, TAHITI_6799, TAHITI)
+CHIPSET(0x679A, TAHITI_679A, TAHITI)
+CHIPSET(0x679E, TAHITI_679E, TAHITI)
+CHIPSET(0x679F, TAHITI_679F, TAHITI)
+
+CHIPSET(0x6800, PITCAIRN_6800, PITCAIRN)
+CHIPSET(0x6801, PITCAIRN_6801, PITCAIRN)
+CHIPSET(0x6802, PITCAIRN_6802, PITCAIRN)
+CHIPSET(0x6806, PITCAIRN_6806, PITCAIRN)
+CHIPSET(0x6808, PITCAIRN_6808, PITCAIRN)
+CHIPSET(0x6809, PITCAIRN_6809, PITCAIRN)
+CHIPSET(0x6810, PITCAIRN_6810, PITCAIRN)
+CHIPSET(0x6811, PITCAIRN_6811, PITCAIRN)
+CHIPSET(0x6816, PITCAIRN_6816, PITCAIRN)
+CHIPSET(0x6817, PITCAIRN_6817, PITCAIRN)
+CHIPSET(0x6818, PITCAIRN_6818, PITCAIRN)
+CHIPSET(0x6819, PITCAIRN_6819, PITCAIRN)
+CHIPSET(0x684C, PITCAIRN_684C, PITCAIRN)
+
+CHIPSET(0x6820, VERDE_6820, VERDE)
+CHIPSET(0x6821, VERDE_6821, VERDE)
+CHIPSET(0x6823, VERDE_6823, VERDE)
+CHIPSET(0x6824, VERDE_6824, VERDE)
+CHIPSET(0x6825, VERDE_6825, VERDE)
+CHIPSET(0x6826, VERDE_6826, VERDE)
+CHIPSET(0x6827, VERDE_6827, VERDE)
+CHIPSET(0x6828, VERDE_6828, VERDE)
+CHIPSET(0x6829, VERDE_6829, VERDE)
+CHIPSET(0x682B, VERDE_682B, VERDE)
+CHIPSET(0x682D, VERDE_682D, VERDE)
+CHIPSET(0x682F, VERDE_682F, VERDE)
+CHIPSET(0x6830, VERDE_6830, VERDE)
+CHIPSET(0x6831, VERDE_6831, VERDE)
+CHIPSET(0x6837, VERDE_6837, VERDE)
+CHIPSET(0x6838, VERDE_6838, VERDE)
+CHIPSET(0x6839, VERDE_6839, VERDE)
+CHIPSET(0x683B, VERDE_683B, VERDE)
+CHIPSET(0x683D, VERDE_683D, VERDE)
+CHIPSET(0x683F, VERDE_683F, VERDE)
diff --git a/radeon/radeon_bo_gem.c b/radeon/radeon_bo_gem.c
index 719fba7..265f177 100644
--- a/radeon/radeon_bo_gem.c
+++ b/radeon/radeon_bo_gem.c
@@ -45,7 +45,7 @@
 #include "radeon_bo.h"
 #include "radeon_bo_int.h"
 #include "radeon_bo_gem.h"
-
+#include <fcntl.h>
 struct radeon_bo_gem {
     struct radeon_bo_int base;
     uint32_t            name;
@@ -349,3 +349,49 @@ int radeon_gem_set_domain(struct radeon_bo *bo, uint32_t read_domains, uint32_t
                             sizeof(args));
     return r;
 }
+
+int radeon_gem_prime_share_bo(struct radeon_bo *bo, int *handle)
+{
+    struct radeon_bo_gem *bo_gem = (struct radeon_bo_gem*)bo;
+    int ret;
+
+    ret = drmPrimeHandleToFD(bo_gem->base.bom->fd, bo->handle, DRM_CLOEXEC, handle);
+    return ret;
+}
+
+struct radeon_bo *radeon_gem_bo_open_prime(struct radeon_bo_manager *bom,
+					   int fd_handle,
+					   uint32_t size)
+{
+    struct radeon_bo_gem *bo;
+    int r;
+    uint32_t handle;
+
+    bo = (struct radeon_bo_gem*)calloc(1, sizeof(struct radeon_bo_gem));
+    if (bo == NULL) {
+        return NULL;
+    }
+
+    bo->base.bom = bom;
+    bo->base.handle = 0;
+    bo->base.size = size;
+    bo->base.alignment = 0;
+    bo->base.domains = RADEON_GEM_DOMAIN_GTT;
+    bo->base.flags = 0;
+    bo->base.ptr = NULL;
+    atomic_set(&bo->reloc_in_cs, 0);
+    bo->map_count = 0;
+
+    r = drmPrimeFDToHandle(bom->fd, fd_handle, &handle);
+    if (r != 0) {
+	free(bo);
+	return NULL;
+    }
+
+    bo->base.handle = handle;
+    bo->name = handle;
+
+    radeon_bo_ref((struct radeon_bo *)bo);
+    return (struct radeon_bo *)bo;
+
+}
diff --git a/radeon/radeon_bo_gem.h b/radeon/radeon_bo_gem.h
index 0af8610..08965f3 100644
--- a/radeon/radeon_bo_gem.h
+++ b/radeon/radeon_bo_gem.h
@@ -41,4 +41,8 @@ uint32_t radeon_gem_name_bo(struct radeon_bo *bo);
 void *radeon_gem_get_reloc_in_cs(struct radeon_bo *bo);
 int radeon_gem_set_domain(struct radeon_bo *bo, uint32_t read_domains, uint32_t write_domain);
 int radeon_gem_get_kernel_name(struct radeon_bo *bo, uint32_t *name);
+int radeon_gem_prime_share_bo(struct radeon_bo *bo, int *handle);
+struct radeon_bo *radeon_gem_bo_open_prime(struct radeon_bo_manager *bom,
+					   int fd_handle,
+					   uint32_t size);
 #endif
diff --git a/radeon/radeon_cs_gem.c b/radeon/radeon_cs_gem.c
index 9834bcf..b963140 100644
--- a/radeon/radeon_cs_gem.c
+++ b/radeon/radeon_cs_gem.c
@@ -330,6 +330,7 @@ static int cs_gem_end(struct radeon_cs_int *cs,
     return 0;
 }
 
+#if CS_BOF_DUMP
 static void cs_gem_dump_bof(struct radeon_cs_int *cs)
 {
     struct cs_gem *csg = (struct cs_gem*)cs;
@@ -415,6 +416,7 @@ out_err:
     bof_decref(device_id);
     bof_decref(root);
 }
+#endif
 
 static int cs_gem_emit(struct radeon_cs_int *cs)
 {
diff --git a/radeon/radeon_surface.c b/radeon/radeon_surface.c
index 6303c47..eb587d2 100644
--- a/radeon/radeon_surface.c
+++ b/radeon/radeon_surface.c
@@ -69,6 +69,9 @@ enum radeon_family {
     CHIP_CAICOS,
     CHIP_CAYMAN,
     CHIP_ARUBA,
+    CHIP_TAHITI,
+    CHIP_PITCAIRN,
+    CHIP_VERDE,
     CHIP_LAST,
 };
 
@@ -141,31 +144,32 @@ static unsigned mip_minify(unsigned size, unsigned level)
 }
 
 static void surf_minify(struct radeon_surface *surf,
-                        unsigned level,
+                        struct radeon_surface_level *surflevel,
+                        unsigned bpe, unsigned level,
                         uint32_t xalign, uint32_t yalign, uint32_t zalign,
                         unsigned offset)
 {
-    surf->level[level].npix_x = mip_minify(surf->npix_x, level);
-    surf->level[level].npix_y = mip_minify(surf->npix_y, level);
-    surf->level[level].npix_z = mip_minify(surf->npix_z, level);
-    surf->level[level].nblk_x = (surf->level[level].npix_x + surf->blk_w - 1) / surf->blk_w;
-    surf->level[level].nblk_y = (surf->level[level].npix_y + surf->blk_h - 1) / surf->blk_h;
-    surf->level[level].nblk_z = (surf->level[level].npix_z + surf->blk_d - 1) / surf->blk_d;
-    if (surf->level[level].mode == RADEON_SURF_MODE_2D) {
-        if (surf->level[level].nblk_x < xalign || surf->level[level].nblk_y < yalign) {
-            surf->level[level].mode = RADEON_SURF_MODE_1D;
+    surflevel->npix_x = mip_minify(surf->npix_x, level);
+    surflevel->npix_y = mip_minify(surf->npix_y, level);
+    surflevel->npix_z = mip_minify(surf->npix_z, level);
+    surflevel->nblk_x = (surflevel->npix_x + surf->blk_w - 1) / surf->blk_w;
+    surflevel->nblk_y = (surflevel->npix_y + surf->blk_h - 1) / surf->blk_h;
+    surflevel->nblk_z = (surflevel->npix_z + surf->blk_d - 1) / surf->blk_d;
+    if (surf->nsamples == 1 && surflevel->mode == RADEON_SURF_MODE_2D) {
+        if (surflevel->nblk_x < xalign || surflevel->nblk_y < yalign) {
+            surflevel->mode = RADEON_SURF_MODE_1D;
             return;
         }
     }
-    surf->level[level].nblk_x  = ALIGN(surf->level[level].nblk_x, xalign);
-    surf->level[level].nblk_y  = ALIGN(surf->level[level].nblk_y, yalign);
-    surf->level[level].nblk_z  = ALIGN(surf->level[level].nblk_z, zalign);
+    surflevel->nblk_x  = ALIGN(surflevel->nblk_x, xalign);
+    surflevel->nblk_y  = ALIGN(surflevel->nblk_y, yalign);
+    surflevel->nblk_z  = ALIGN(surflevel->nblk_z, zalign);
 
-    surf->level[level].offset = offset;
-    surf->level[level].pitch_bytes = surf->level[level].nblk_x * surf->bpe;
-    surf->level[level].slice_size = surf->level[level].pitch_bytes * surf->level[level].nblk_y;
+    surflevel->offset = offset;
+    surflevel->pitch_bytes = surflevel->nblk_x * bpe * surf->nsamples;
+    surflevel->slice_size = surflevel->pitch_bytes * surflevel->nblk_y;
 
-    surf->bo_size = offset + surf->level[level].slice_size * surf->level[level].nblk_z * surf->array_size;
+    surf->bo_size = offset + surflevel->slice_size * surflevel->nblk_z * surf->array_size;
 }
 
 /* ===========================================================================
@@ -188,6 +192,7 @@ static int r6_init_hw_info(struct radeon_surface_manager *surf_man)
     if (version && version->version_minor >= 14) {
         surf_man->hw_info.allow_2d = 1;
     }
+    drmFreeVersion(version);
 
     switch ((tiling_config & 0xe) >> 1) {
     case 0:
@@ -203,7 +208,9 @@ static int r6_init_hw_info(struct radeon_surface_manager *surf_man)
         surf_man->hw_info.num_pipes = 8;
         break;
     default:
-        return -EINVAL;
+        surf_man->hw_info.num_pipes = 8;
+        surf_man->hw_info.allow_2d = 0;
+        break;
     }
 
     switch ((tiling_config & 0x30) >> 4) {
@@ -214,7 +221,9 @@ static int r6_init_hw_info(struct radeon_surface_manager *surf_man)
         surf_man->hw_info.num_banks = 8;
         break;
     default:
-        return -EINVAL;
+        surf_man->hw_info.num_banks = 8;
+        surf_man->hw_info.allow_2d = 0;
+        break;
     }
 
     switch ((tiling_config & 0xc0) >> 6) {
@@ -225,7 +234,9 @@ static int r6_init_hw_info(struct radeon_surface_manager *surf_man)
         surf_man->hw_info.group_bytes = 512;
         break;
     default:
-        return -EINVAL;
+        surf_man->hw_info.group_bytes = 256;
+        surf_man->hw_info.allow_2d = 0;
+        break;
     }
     return 0;
 }
@@ -254,7 +265,7 @@ static int r6_surface_init_linear(struct radeon_surface_manager *surf_man,
     /* build mipmap tree */
     for (i = start_level; i <= surf->last_level; i++) {
         surf->level[i].mode = RADEON_SURF_MODE_LINEAR;
-        surf_minify(surf, i, xalign, yalign, zalign, offset);
+        surf_minify(surf, surf->level+i, surf->bpe, i, xalign, yalign, zalign, offset);
         /* level0 and first mipmap need to have alignment */
         offset = surf->bo_size;
         if ((i == 0)) {
@@ -282,7 +293,7 @@ static int r6_surface_init_linear_aligned(struct radeon_surface_manager *surf_ma
     /* build mipmap tree */
     for (i = start_level; i <= surf->last_level; i++) {
         surf->level[i].mode = RADEON_SURF_MODE_LINEAR_ALIGNED;
-        surf_minify(surf, i, xalign, yalign, zalign, offset);
+        surf_minify(surf, surf->level+i, surf->bpe, i, xalign, yalign, zalign, offset);
         /* level0 and first mipmap need to have alignment */
         offset = surf->bo_size;
         if ((i == 0)) {
@@ -315,7 +326,7 @@ static int r6_surface_init_1d(struct radeon_surface_manager *surf_man,
     /* build mipmap tree */
     for (i = start_level; i <= surf->last_level; i++) {
         surf->level[i].mode = RADEON_SURF_MODE_1D;
-        surf_minify(surf, i, xalign, yalign, zalign, offset);
+        surf_minify(surf, surf->level+i, surf->bpe, i, xalign, yalign, zalign, offset);
         /* level0 and first mipmap need to have alignment */
         offset = surf->bo_size;
         if ((i == 0)) {
@@ -346,14 +357,14 @@ static int r6_surface_init_2d(struct radeon_surface_manager *surf_man,
         surf->bo_alignment =
             MAX2(surf_man->hw_info.num_pipes *
                  surf_man->hw_info.num_banks *
-                 surf->bpe * 64,
+                 surf->nsamples * surf->bpe * 64,
                  xalign * yalign * surf->nsamples * surf->bpe);
     }
 
     /* build mipmap tree */
     for (i = start_level; i <= surf->last_level; i++) {
         surf->level[i].mode = RADEON_SURF_MODE_2D;
-        surf_minify(surf, i, xalign, yalign, zalign, offset);
+        surf_minify(surf, surf->level+i, surf->bpe, i, xalign, yalign, zalign, offset);
         if (surf->level[i].mode == RADEON_SURF_MODE_1D) {
             return r6_surface_init_1d(surf_man, surf, offset, i);
         }
@@ -372,11 +383,35 @@ static int r6_surface_init(struct radeon_surface_manager *surf_man,
     unsigned mode;
     int r;
 
+    /* MSAA surfaces support the 2D mode only. */
+    if (surf->nsamples > 1) {
+        surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
+        surf->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_2D, MODE);
+    }
+
     /* tiling mode */
     mode = (surf->flags >> RADEON_SURF_MODE_SHIFT) & RADEON_SURF_MODE_MASK;
 
+    if (surf->flags & (RADEON_SURF_ZBUFFER | RADEON_SURF_SBUFFER)) {
+        /* zbuffer only support 1D or 2D tiled surface */
+        switch (mode) {
+        case RADEON_SURF_MODE_1D:
+        case RADEON_SURF_MODE_2D:
+            break;
+        default:
+            mode = RADEON_SURF_MODE_1D;
+            surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
+            surf->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_1D, MODE);
+            break;
+        }
+    }
+
     /* force 1d on kernel that can't do 2d */
     if (!surf_man->hw_info.allow_2d && mode > RADEON_SURF_MODE_1D) {
+        if (surf->nsamples > 1) {
+            fprintf(stderr, "radeon: Cannot use 2D tiling for an MSAA surface (%i).\n", __LINE__);
+            return -EFAULT;
+        }
         mode = RADEON_SURF_MODE_1D;
         surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
         surf->flags |= RADEON_SURF_SET(mode, MODE);
@@ -437,9 +472,10 @@ static int eg_init_hw_info(struct radeon_surface_manager *surf_man)
 
     surf_man->hw_info.allow_2d = 0;
     version = drmGetVersion(surf_man->fd);
-    if (version && version->version_minor >= 14) {
+    if (version && version->version_minor >= 16) {
         surf_man->hw_info.allow_2d = 1;
     }
+    drmFreeVersion(version);
 
     switch (tiling_config & 0xf) {
     case 0:
@@ -455,7 +491,9 @@ static int eg_init_hw_info(struct radeon_surface_manager *surf_man)
         surf_man->hw_info.num_pipes = 8;
         break;
     default:
-        return -EINVAL;
+        surf_man->hw_info.num_pipes = 8;
+        surf_man->hw_info.allow_2d = 0;
+        break;
     }
 
     switch ((tiling_config & 0xf0) >> 4) {
@@ -469,7 +507,9 @@ static int eg_init_hw_info(struct radeon_surface_manager *surf_man)
         surf_man->hw_info.num_banks = 16;
         break;
     default:
-        return -EINVAL;
+        surf_man->hw_info.num_banks = 8;
+        surf_man->hw_info.allow_2d = 0;
+        break;
     }
 
     switch ((tiling_config & 0xf00) >> 8) {
@@ -480,7 +520,9 @@ static int eg_init_hw_info(struct radeon_surface_manager *surf_man)
         surf_man->hw_info.group_bytes = 512;
         break;
     default:
-        return -EINVAL;
+        surf_man->hw_info.group_bytes = 256;
+        surf_man->hw_info.allow_2d = 0;
+        break;
     }
 
     switch ((tiling_config & 0xf000) >> 12) {
@@ -494,12 +536,16 @@ static int eg_init_hw_info(struct radeon_surface_manager *surf_man)
         surf_man->hw_info.row_size = 4096;
         break;
     default:
-        return -EINVAL;
+        surf_man->hw_info.row_size = 4096;
+        surf_man->hw_info.allow_2d = 0;
+        break;
     }
     return 0;
 }
 
 static void eg_surf_minify(struct radeon_surface *surf,
+                           struct radeon_surface_level *surflevel,
+                           unsigned bpe,
                            unsigned level,
                            unsigned slice_pt,
                            unsigned mtilew,
@@ -509,36 +555,38 @@ static void eg_surf_minify(struct radeon_surface *surf,
 {
     unsigned mtile_pr, mtile_ps;
 
-    surf->level[level].npix_x = mip_minify(surf->npix_x, level);
-    surf->level[level].npix_y = mip_minify(surf->npix_y, level);
-    surf->level[level].npix_z = mip_minify(surf->npix_z, level);
-    surf->level[level].nblk_x = (surf->level[level].npix_x + surf->blk_w - 1) / surf->blk_w;
-    surf->level[level].nblk_y = (surf->level[level].npix_y + surf->blk_h - 1) / surf->blk_h;
-    surf->level[level].nblk_z = (surf->level[level].npix_z + surf->blk_d - 1) / surf->blk_d;
-    if (surf->level[level].mode == RADEON_SURF_MODE_2D) {
-        if (surf->level[level].nblk_x < mtilew || surf->level[level].nblk_y < mtileh) {
-            surf->level[level].mode = RADEON_SURF_MODE_1D;
+    surflevel->npix_x = mip_minify(surf->npix_x, level);
+    surflevel->npix_y = mip_minify(surf->npix_y, level);
+    surflevel->npix_z = mip_minify(surf->npix_z, level);
+    surflevel->nblk_x = (surflevel->npix_x + surf->blk_w - 1) / surf->blk_w;
+    surflevel->nblk_y = (surflevel->npix_y + surf->blk_h - 1) / surf->blk_h;
+    surflevel->nblk_z = (surflevel->npix_z + surf->blk_d - 1) / surf->blk_d;
+    if (surf->nsamples == 1 && surflevel->mode == RADEON_SURF_MODE_2D) {
+        if (surflevel->nblk_x < mtilew || surflevel->nblk_y < mtileh) {
+            surflevel->mode = RADEON_SURF_MODE_1D;
             return;
         }
     }
-    surf->level[level].nblk_x  = ALIGN(surf->level[level].nblk_x, mtilew);
-    surf->level[level].nblk_y  = ALIGN(surf->level[level].nblk_y, mtileh);
-    surf->level[level].nblk_z  = ALIGN(surf->level[level].nblk_z, 1);
+    surflevel->nblk_x  = ALIGN(surflevel->nblk_x, mtilew);
+    surflevel->nblk_y  = ALIGN(surflevel->nblk_y, mtileh);
+    surflevel->nblk_z  = ALIGN(surflevel->nblk_z, 1);
 
     /* macro tile per row */
-    mtile_pr = surf->level[level].nblk_x / mtilew;
+    mtile_pr = surflevel->nblk_x / mtilew;
     /* macro tile per slice */
-    mtile_ps = (mtile_pr * surf->level[level].nblk_y) / mtileh;
+    mtile_ps = (mtile_pr * surflevel->nblk_y) / mtileh;
 
-    surf->level[level].offset = offset;
-    surf->level[level].pitch_bytes = surf->level[level].nblk_x * surf->bpe * slice_pt;
-    surf->level[level].slice_size = mtile_ps * mtileb * slice_pt;
+    surflevel->offset = offset;
+    surflevel->pitch_bytes = surflevel->nblk_x * bpe * slice_pt;
+    surflevel->slice_size = mtile_ps * mtileb * slice_pt;
 
-    surf->bo_size = offset + surf->level[level].slice_size * surf->level[level].nblk_z * surf->array_size;
+    surf->bo_size = offset + surflevel->slice_size * surflevel->nblk_z * surf->array_size;
 }
 
 static int eg_surface_init_1d(struct radeon_surface_manager *surf_man,
                               struct radeon_surface *surf,
+                              struct radeon_surface_level *level,
+                              unsigned bpe,
                               uint64_t offset, unsigned start_level)
 {
     uint32_t xalign, yalign, zalign, tilew;
@@ -546,43 +594,40 @@ static int eg_surface_init_1d(struct radeon_surface_manager *surf_man,
 
     /* compute alignment */
     tilew = 8;
-    xalign = surf_man->hw_info.group_bytes / (tilew * surf->bpe * surf->nsamples);
-    if (surf->flags & RADEON_SURF_SBUFFER) {
-        surf->stencil_offset = 0;
-        surf->stencil_tile_split = 0;
-        xalign = surf_man->hw_info.group_bytes / (tilew * surf->nsamples);
-    }
+    xalign = surf_man->hw_info.group_bytes / (tilew * bpe * surf->nsamples);
     xalign = MAX2(tilew, xalign);
     yalign = tilew;
     zalign = 1;
     if (surf->flags & RADEON_SURF_SCANOUT) {
-        xalign = MAX2((surf->bpe == 1) ? 64 : 32, xalign);
+        xalign = MAX2((bpe == 1) ? 64 : 32, xalign);
     }
+
     if (!start_level) {
-        surf->bo_alignment = MAX2(256, surf_man->hw_info.group_bytes);
+        unsigned alignment = MAX2(256, surf_man->hw_info.group_bytes);
+        surf->bo_alignment = MAX2(surf->bo_alignment, alignment);
+
+        if (offset) {
+            offset = ALIGN(offset, alignment);
+        }
     }
 
     /* build mipmap tree */
     for (i = start_level; i <= surf->last_level; i++) {
-        surf->level[i].mode = RADEON_SURF_MODE_1D;
-        surf_minify(surf, i, xalign, yalign, zalign, offset);
+        level[i].mode = RADEON_SURF_MODE_1D;
+        surf_minify(surf, level+i, bpe, i, xalign, yalign, zalign, offset);
         /* level0 and first mipmap need to have alignment */
         offset = surf->bo_size;
         if ((i == 0)) {
             offset = ALIGN(offset, surf->bo_alignment);
         }
     }
-
-    if (surf->flags & RADEON_SURF_SBUFFER) {
-        surf->stencil_offset = ALIGN(surf->bo_size, surf->bo_alignment);
-        surf->bo_size = surf->stencil_offset + surf->bo_size / 4;
-    }
-
     return 0;
 }
 
 static int eg_surface_init_2d(struct radeon_surface_manager *surf_man,
                               struct radeon_surface *surf,
+                              struct radeon_surface_level *level,
+                              unsigned bpe, unsigned tile_split,
                               uint64_t offset, unsigned start_level)
 {
     unsigned tilew, tileh, tileb;
@@ -590,15 +635,14 @@ static int eg_surface_init_2d(struct radeon_surface_manager *surf_man,
     unsigned slice_pt;
     unsigned i;
 
-    surf->stencil_offset = 0;
     /* compute tile values */
     tilew = 8;
     tileh = 8;
-    tileb = tilew * tileh * surf->bpe * surf->nsamples;
+    tileb = tilew * tileh * bpe * surf->nsamples;
     /* slices per tile */
     slice_pt = 1;
-    if (tileb > surf->tile_split) {
-        slice_pt = tileb / surf->tile_split;
+    if (tileb > tile_split) {
+        slice_pt = tileb / tile_split;
     }
     tileb = tileb / slice_pt;
 
@@ -609,15 +653,20 @@ static int eg_surface_init_2d(struct radeon_surface_manager *surf_man,
     mtileb = (mtilew / tilew) * (mtileh / tileh) * tileb;
 
     if (!start_level) {
-        surf->bo_alignment = MAX2(256, mtileb);
+        unsigned alignment = MAX2(256, mtileb);
+        surf->bo_alignment = MAX2(surf->bo_alignment, alignment);
+
+        if (offset) {
+            offset = ALIGN(offset, alignment);
+        }
     }
 
     /* build mipmap tree */
     for (i = start_level; i <= surf->last_level; i++) {
-        surf->level[i].mode = RADEON_SURF_MODE_2D;
-        eg_surf_minify(surf, i, slice_pt, mtilew, mtileh, mtileb, offset);
-        if (surf->level[i].mode == RADEON_SURF_MODE_1D) {
-            return eg_surface_init_1d(surf_man, surf, offset, i);
+        level[i].mode = RADEON_SURF_MODE_2D;
+        eg_surf_minify(surf, level+i, bpe, i, slice_pt, mtilew, mtileh, mtileb, offset);
+        if (level[i].mode == RADEON_SURF_MODE_1D) {
+            return eg_surface_init_1d(surf_man, surf, level, bpe, offset, i);
         }
         /* level0 and first mipmap need to have alignment */
         offset = surf->bo_size;
@@ -625,12 +674,6 @@ static int eg_surface_init_2d(struct radeon_surface_manager *surf_man,
             offset = ALIGN(offset, surf->bo_alignment);
         }
     }
-
-    if (surf->flags & RADEON_SURF_SBUFFER) {
-        surf->stencil_offset = ALIGN(surf->bo_size, surf->bo_alignment);
-        surf->bo_size = surf->stencil_offset + surf->bo_size / 4;
-    }
-
     return 0;
 }
 
@@ -652,6 +695,10 @@ static int eg_surface_sanity(struct radeon_surface_manager *surf_man,
 
     /* force 1d on kernel that can't do 2d */
     if (!surf_man->hw_info.allow_2d && mode > RADEON_SURF_MODE_1D) {
+        if (surf->nsamples > 1) {
+            fprintf(stderr, "radeon: Cannot use 2D tiling for an MSAA surface (%i).\n", __LINE__);
+            return -EFAULT;
+        }
         mode = RADEON_SURF_MODE_1D;
         surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
         surf->flags |= RADEON_SURF_SET(mode, MODE);
@@ -713,18 +760,78 @@ static int eg_surface_sanity(struct radeon_surface_manager *surf_man,
     return 0;
 }
 
+static int eg_surface_init_1d_miptrees(struct radeon_surface_manager *surf_man,
+                                       struct radeon_surface *surf)
+{
+    unsigned zs_flags = RADEON_SURF_ZBUFFER | RADEON_SURF_SBUFFER;
+    int r, is_depth_stencil = (surf->flags & zs_flags) == zs_flags;
+    /* Old libdrm headers didn't have stencil_level in it. This prevents crashes. */
+    struct radeon_surface_level tmp[RADEON_SURF_MAX_LEVEL];
+    struct radeon_surface_level *stencil_level =
+        (surf->flags & RADEON_SURF_HAS_SBUFFER_MIPTREE) ? surf->stencil_level : tmp;
+
+    r = eg_surface_init_1d(surf_man, surf, surf->level, surf->bpe, 0, 0);
+    if (r)
+        return r;
+
+    if (is_depth_stencil) {
+        r = eg_surface_init_1d(surf_man, surf, stencil_level, 1,
+                               surf->bo_size, 0);
+        surf->stencil_offset = stencil_level[0].offset;
+    }
+    return r;
+}
+
+static int eg_surface_init_2d_miptrees(struct radeon_surface_manager *surf_man,
+                                       struct radeon_surface *surf)
+{
+    unsigned zs_flags = RADEON_SURF_ZBUFFER | RADEON_SURF_SBUFFER;
+    int r, is_depth_stencil = (surf->flags & zs_flags) == zs_flags;
+    /* Old libdrm headers didn't have stencil_level in it. This prevents crashes. */
+    struct radeon_surface_level tmp[RADEON_SURF_MAX_LEVEL];
+    struct radeon_surface_level *stencil_level =
+        (surf->flags & RADEON_SURF_HAS_SBUFFER_MIPTREE) ? surf->stencil_level : tmp;
+
+    r = eg_surface_init_2d(surf_man, surf, surf->level, surf->bpe,
+                           surf->tile_split, 0, 0);
+    if (r)
+        return r;
+
+    if (is_depth_stencil) {
+        r = eg_surface_init_2d(surf_man, surf, stencil_level, 1,
+                               surf->stencil_tile_split, surf->bo_size, 0);
+        surf->stencil_offset = stencil_level[0].offset;
+    }
+    return r;
+}
+
 static int eg_surface_init(struct radeon_surface_manager *surf_man,
                            struct radeon_surface *surf)
 {
     unsigned mode;
     int r;
 
+    /* MSAA surfaces support the 2D mode only. */
+    if (surf->nsamples > 1) {
+        surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
+        surf->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_2D, MODE);
+    }
+
     /* tiling mode */
     mode = (surf->flags >> RADEON_SURF_MODE_SHIFT) & RADEON_SURF_MODE_MASK;
 
-    /* for some reason eg need to have room for stencil right after depth */
-    if (surf->flags & RADEON_SURF_ZBUFFER) {
-        surf->flags |= RADEON_SURF_SBUFFER;
+    if (surf->flags & (RADEON_SURF_ZBUFFER | RADEON_SURF_SBUFFER)) {
+        /* zbuffer only support 1D or 2D tiled surface */
+        switch (mode) {
+        case RADEON_SURF_MODE_1D:
+        case RADEON_SURF_MODE_2D:
+            break;
+        default:
+            mode = RADEON_SURF_MODE_1D;
+            surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
+            surf->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_1D, MODE);
+            break;
+        }
     }
 
     r = eg_surface_sanity(surf_man, surf, mode);
@@ -732,6 +839,9 @@ static int eg_surface_init(struct radeon_surface_manager *surf_man,
         return r;
     }
 
+    surf->stencil_offset = 0;
+    surf->bo_alignment = 0;
+
     /* check tiling mode */
     switch (mode) {
     case RADEON_SURF_MODE_LINEAR:
@@ -741,10 +851,10 @@ static int eg_surface_init(struct radeon_surface_manager *surf_man,
         r = r6_surface_init_linear_aligned(surf_man, surf, 0, 0);
         break;
     case RADEON_SURF_MODE_1D:
-        r = eg_surface_init_1d(surf_man, surf, 0, 0);
+        r = eg_surface_init_1d_miptrees(surf_man, surf);
         break;
     case RADEON_SURF_MODE_2D:
-        r = eg_surface_init_2d(surf_man, surf, 0, 0);
+        r = eg_surface_init_2d_miptrees(surf_man, surf);
         break;
     default:
         return -EINVAL;
@@ -779,11 +889,6 @@ static int eg_surface_best(struct radeon_surface_manager *surf_man,
     /* tiling mode */
     mode = (surf->flags >> RADEON_SURF_MODE_SHIFT) & RADEON_SURF_MODE_MASK;
 
-    /* for some reason eg need to have room for stencil right after depth */
-    if (surf->flags & RADEON_SURF_ZBUFFER) {
-        surf->flags |= RADEON_SURF_SBUFFER;
-    }
-
     /* set some default value to avoid sanity check choking on them */
     surf->tile_split = 1024;
     surf->bankw = 1;
@@ -809,12 +914,39 @@ static int eg_surface_best(struct radeon_surface_manager *surf_man,
         return 0;
     }
 
-    /* set tile split to row size, optimize latter for multi-sample surface
-     * tile split >= 256 for render buffer surface. Also depth surface want
-     * smaller value for optimal performances.
-     */
-    surf->tile_split = surf_man->hw_info.row_size;
-    surf->stencil_tile_split = surf_man->hw_info.row_size / 2;
+    /* Tweak TILE_SPLIT for performance here. */
+    if (surf->nsamples > 1) {
+        if (surf->flags & (RADEON_SURF_ZBUFFER | RADEON_SURF_SBUFFER)) {
+            switch (surf->nsamples) {
+            case 2:
+                surf->tile_split = 128;
+                break;
+            case 4:
+                surf->tile_split = 128;
+                break;
+            case 8:
+                surf->tile_split = 256;
+                break;
+            case 16: /* cayman only */
+                surf->tile_split = 512;
+                break;
+            default:
+                fprintf(stderr, "radeon: Wrong number of samples %i (%i)\n",
+                        surf->nsamples, __LINE__);
+                return -EINVAL;
+            }
+            surf->stencil_tile_split = 64;
+        } else {
+            /* tile split must be >= 256 for colorbuffer surfaces */
+            surf->tile_split = MAX2(surf->nsamples * surf->bpe * 64, 256);
+            if (surf->tile_split > 4096)
+                surf->tile_split = 4096;
+        }
+    } else {
+        /* set tile split to row size */
+        surf->tile_split = surf_man->hw_info.row_size;
+        surf->stencil_tile_split = surf_man->hw_info.row_size / 2;
+    }
 
     /* bankw or bankh greater than 1 increase alignment requirement, not
      * sure if it's worth using smaller bankw & bankh to stick with 2D
@@ -824,7 +956,7 @@ static int eg_surface_best(struct radeon_surface_manager *surf_man,
      * fmask buffer has different optimal value figure them out once we
      * use it.
      */
-    if (surf->flags & (RADEON_SURF_ZBUFFER | RADEON_SURF_SBUFFER)) {
+    if (surf->flags & RADEON_SURF_SBUFFER) {
         /* assume 1 bytes for stencil, we optimize for stencil as stencil
          * and depth shares surface values
          */
@@ -865,6 +997,136 @@ static int eg_surface_best(struct radeon_surface_manager *surf_man,
 
 
 /* ===========================================================================
+ * Southern Islands family
+ */
+
+static void si_surf_minify_linear_aligned(struct radeon_surface *surf,
+                                          unsigned level,
+                                          uint32_t xalign, uint32_t yalign, uint32_t zalign, uint32_t slice_align,
+                                          unsigned offset)
+{
+    surf->level[level].npix_x = mip_minify(surf->npix_x, level);
+    surf->level[level].npix_y = mip_minify(surf->npix_y, level);
+    surf->level[level].npix_z = mip_minify(surf->npix_z, level);
+
+    if (level == 0 && surf->last_level > 0) {
+        surf->level[level].nblk_x = (next_power_of_two(surf->level[level].npix_x) + surf->blk_w - 1) / surf->blk_w;
+        surf->level[level].nblk_y = (next_power_of_two(surf->level[level].npix_y) + surf->blk_h - 1) / surf->blk_h;
+        surf->level[level].nblk_z = (next_power_of_two(surf->level[level].npix_z) + surf->blk_d - 1) / surf->blk_d;
+    } else {
+        surf->level[level].nblk_x = (surf->level[level].npix_x + surf->blk_w - 1) / surf->blk_w;
+        surf->level[level].nblk_y = (surf->level[level].npix_y + surf->blk_h - 1) / surf->blk_h;
+        surf->level[level].nblk_z = (surf->level[level].npix_z + surf->blk_d - 1) / surf->blk_d;
+    }
+
+    /* XXX: Texture sampling uses unexpectedly large pitches in some cases,
+     * these are just guesses for the rules behind those
+     */
+    if (level == 0 && surf->last_level == 0)
+        /* Non-mipmap pitch padded to slice alignment */
+        xalign = MAX2(xalign, slice_align / surf->bpe);
+    else
+        /* Small rows evenly distributed across slice */
+        xalign = MAX2(xalign, slice_align / surf->bpe / surf->level[level].npix_y);
+
+    surf->level[level].nblk_x  = ALIGN(surf->level[level].nblk_x, xalign);
+    surf->level[level].nblk_y  = ALIGN(surf->level[level].nblk_y, yalign);
+    surf->level[level].nblk_z  = ALIGN(surf->level[level].nblk_z, zalign);
+
+    surf->level[level].offset = offset;
+    surf->level[level].pitch_bytes = surf->level[level].nblk_x * surf->bpe * surf->nsamples;
+    surf->level[level].slice_size = ALIGN(surf->level[level].pitch_bytes * surf->level[level].nblk_y, slice_align);
+
+    surf->bo_size = offset + surf->level[level].slice_size * surf->level[level].nblk_z * surf->array_size;
+}
+
+static int si_surface_init_linear_aligned(struct radeon_surface_manager *surf_man,
+                                          struct radeon_surface *surf,
+                                          uint64_t offset, unsigned start_level)
+{
+    uint32_t xalign, yalign, zalign, slice_align;
+    unsigned i;
+
+    /* compute alignment */
+    if (!start_level) {
+        surf->bo_alignment = MAX2(256, surf_man->hw_info.group_bytes);
+    }
+    xalign = MAX2(8, 64 / surf->bpe);
+    yalign = 1;
+    zalign = 1;
+    slice_align = MAX2(64 * surf->bpe, surf_man->hw_info.group_bytes);
+
+    /* build mipmap tree */
+    for (i = start_level; i <= surf->last_level; i++) {
+        surf->level[i].mode = RADEON_SURF_MODE_LINEAR_ALIGNED;
+        si_surf_minify_linear_aligned(surf, i, xalign, yalign, zalign, slice_align, offset);
+        /* level0 and first mipmap need to have alignment */
+        offset = surf->bo_size;
+        if ((i == 0)) {
+            offset = ALIGN(offset, surf->bo_alignment);
+        }
+    }
+    return 0;
+}
+
+static int si_surface_init(struct radeon_surface_manager *surf_man,
+                           struct radeon_surface *surf)
+{
+    unsigned mode;
+    int r;
+
+    /* MSAA surfaces support the 2D mode only. */
+    if (surf->nsamples > 1) {
+        surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
+        surf->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_2D, MODE);
+    }
+
+    /* tiling mode */
+    mode = (surf->flags >> RADEON_SURF_MODE_SHIFT) & RADEON_SURF_MODE_MASK;
+
+    if (surf->flags & (RADEON_SURF_ZBUFFER | RADEON_SURF_SBUFFER)) {
+        /* zbuffer only support 1D or 2D tiled surface */
+        switch (mode) {
+        case RADEON_SURF_MODE_1D:
+        case RADEON_SURF_MODE_2D:
+            break;
+        default:
+            mode = RADEON_SURF_MODE_1D;
+            surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
+            surf->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_1D, MODE);
+            break;
+        }
+    }
+
+    r = eg_surface_sanity(surf_man, surf, mode);
+    if (r) {
+        return r;
+    }
+
+    surf->stencil_offset = 0;
+    surf->bo_alignment = 0;
+
+    /* check tiling mode */
+    switch (mode) {
+    case RADEON_SURF_MODE_LINEAR:
+        r = r6_surface_init_linear(surf_man, surf, 0, 0);
+        break;
+    case RADEON_SURF_MODE_LINEAR_ALIGNED:
+        r = si_surface_init_linear_aligned(surf_man, surf, 0, 0);
+        break;
+    case RADEON_SURF_MODE_1D:
+        r = eg_surface_init_1d_miptrees(surf_man, surf);
+        break;
+    case RADEON_SURF_MODE_2D:
+        r = eg_surface_init_2d_miptrees(surf_man, surf);
+        break;
+    default:
+        return -EINVAL;
+    }
+    return r;
+}
+
+/* ===========================================================================
  * public API
  */
 struct radeon_surface_manager *radeon_surface_manager_new(int fd)
@@ -893,7 +1155,11 @@ struct radeon_surface_manager *radeon_surface_manager_new(int fd)
         if (eg_init_hw_info(surf_man)) {
             goto out_err;
         }
-        surf_man->surface_init = &eg_surface_init;
+        if (surf_man->family <= CHIP_ARUBA) {
+            surf_man->surface_init = &eg_surface_init;
+        } else {
+            surf_man->surface_init = &si_surface_init;
+        }
         surf_man->surface_best = &eg_surface_best;
     }
 
diff --git a/radeon/radeon_surface.h b/radeon/radeon_surface.h
index bfee8ab..ed4b994 100644
--- a/radeon/radeon_surface.h
+++ b/radeon/radeon_surface.h
@@ -54,6 +54,7 @@
 #define RADEON_SURF_SCANOUT                     (1 << 16)
 #define RADEON_SURF_ZBUFFER                     (1 << 17)
 #define RADEON_SURF_SBUFFER                     (1 << 18)
+#define RADEON_SURF_HAS_SBUFFER_MIPTREE         (1 << 19)
 
 #define RADEON_SURF_GET(v, field)   (((v) >> RADEON_SURF_ ## field ## _SHIFT) & RADEON_SURF_ ## field ## _MASK)
 #define RADEON_SURF_SET(v, field)   (((v) & RADEON_SURF_ ## field ## _MASK) << RADEON_SURF_ ## field ## _SHIFT)
@@ -102,6 +103,7 @@ struct radeon_surface {
     uint32_t                    stencil_tile_split;
     uint64_t                    stencil_offset;
     struct radeon_surface_level level[RADEON_SURF_MAX_LEVEL];
+    struct radeon_surface_level stencil_level[RADEON_SURF_MAX_LEVEL];
 };
 
 struct radeon_surface_manager *radeon_surface_manager_new(int fd);
diff --git a/tests/modetest/Makefile.am b/tests/modetest/Makefile.am
index 2191242..065ae13 100644
diff --git a/tests/modetest/buffers.c b/tests/modetest/buffers.c
new file mode 100644
index 0000000..5086381
diff --git a/tests/modetest/buffers.h b/tests/modetest/buffers.h
new file mode 100644
index 0000000..2b15ce5
diff --git a/tests/modetest/modetest.c b/tests/modetest/modetest.c
index 1e4ec91..c91bb9d 100644
diff --git a/tests/vbltest/vbltest.c b/tests/vbltest/vbltest.c
index 903ca0f..4fccd59 100644
diff --git a/xf86drm.c b/xf86drm.c
index 6ea068f..2a74c80 100644
--- a/xf86drm.c
+++ b/xf86drm.c
@@ -2542,3 +2542,34 @@ char *drmGetDeviceNameFromFd(int fd)
 
 	return strdup(name);
 }
+
+int drmPrimeHandleToFD(int fd, uint32_t handle, uint32_t flags, int *prime_fd)
+{
+	struct drm_prime_handle args;
+	int ret;
+
+	args.handle = handle;
+	args.flags = flags;
+	ret = drmIoctl(fd, DRM_IOCTL_PRIME_HANDLE_TO_FD, &args);
+	if (ret)
+		return ret;
+
+	*prime_fd = args.fd;
+	return 0;
+}
+
+int drmPrimeFDToHandle(int fd, int prime_fd, uint32_t *handle)
+{
+	struct drm_prime_handle args;
+	int ret;
+
+	args.fd = prime_fd;
+	args.flags = 0;
+	ret = drmIoctl(fd, DRM_IOCTL_PRIME_FD_TO_HANDLE, &args);
+	if (ret)
+		return ret;
+
+	*handle = args.handle;
+	return 0;
+}
+
diff --git a/xf86drm.h b/xf86drm.h
index 76eb94e..5ecb284 100644
--- a/xf86drm.h
+++ b/xf86drm.h
@@ -727,6 +727,9 @@ extern int drmHandleEvent(int fd, drmEventContextPtr evctx);
 
 extern char *drmGetDeviceNameFromFd(int fd);
 
+extern int drmPrimeHandleToFD(int fd, uint32_t handle, uint32_t flags, int *prime_fd);
+extern int drmPrimeFDToHandle(int fd, int prime_fd, uint32_t *handle);
+
 #if defined(__cplusplus) || defined(c_plusplus)
 }
 #endif
diff --git a/xf86drmMode.c b/xf86drmMode.c
index c809c44..f603ceb 100644
--- a/xf86drmMode.c
+++ b/xf86drmMode.c
@@ -351,8 +351,11 @@ drmModeCrtcPtr drmModeGetCrtc(int fd, uint32_t crtcId)
 	r->x               = crtc.x;
 	r->y               = crtc.y;
 	r->mode_valid      = crtc.mode_valid;
-	if (r->mode_valid)
+	if (r->mode_valid) {
 		memcpy(&r->mode, &crtc.mode, sizeof(struct drm_mode_modeinfo));
+		r->width = crtc.mode.hdisplay;
+		r->height = crtc.mode.vdisplay;
+	}
 	r->buffer_id       = crtc.fb_id;
 	r->gamma_size      = crtc.gamma_size;
 	return r;
@@ -575,7 +578,7 @@ drmModePropertyPtr drmModeGetProperty(int fd, uint32_t property_id)
 	if (prop.count_values)
 		prop.values_ptr = VOID2U64(drmMalloc(prop.count_values * sizeof(uint64_t)));
 
-	if (prop.count_enum_blobs && (prop.flags & DRM_MODE_PROP_ENUM))
+	if (prop.count_enum_blobs && (prop.flags & (DRM_MODE_PROP_ENUM | DRM_MODE_PROP_BITMASK)))
 		prop.enum_blob_ptr = VOID2U64(drmMalloc(prop.count_enum_blobs * sizeof(struct drm_mode_property_enum)));
 
 	if (prop.count_enum_blobs && (prop.flags & DRM_MODE_PROP_BLOB)) {
@@ -597,7 +600,7 @@ drmModePropertyPtr drmModeGetProperty(int fd, uint32_t property_id)
 	r->flags = prop.flags;
 	if (prop.count_values)
 		r->values = drmAllocCpy(U642VOID(prop.values_ptr), prop.count_values, sizeof(uint64_t));
-	if (prop.flags & DRM_MODE_PROP_ENUM) {
+	if (prop.flags & (DRM_MODE_PROP_ENUM | DRM_MODE_PROP_BITMASK)) {
 		r->count_enums = prop.count_enum_blobs;
 		r->enums = drmAllocCpy(U642VOID(prop.enum_blob_ptr), prop.count_enum_blobs, sizeof(struct drm_mode_property_enum));
 	} else if (prop.flags & DRM_MODE_PROP_BLOB) {
@@ -974,3 +977,86 @@ void drmModeFreePlaneResources(drmModePlaneResPtr ptr)
 	drmFree(ptr->planes);
 	drmFree(ptr);
 }
+
+drmModeObjectPropertiesPtr drmModeObjectGetProperties(int fd,
+						      uint32_t object_id,
+						      uint32_t object_type)
+{
+	struct drm_mode_obj_get_properties properties;
+	drmModeObjectPropertiesPtr ret = NULL;
+	uint32_t count;
+
+retry:
+	memset(&properties, 0, sizeof(struct drm_mode_obj_get_properties));
+	properties.obj_id = object_id;
+	properties.obj_type = object_type;
+
+	if (drmIoctl(fd, DRM_IOCTL_MODE_OBJ_GETPROPERTIES, &properties))
+		return 0;
+
+	count = properties.count_props;
+
+	if (count) {
+		properties.props_ptr = VOID2U64(drmMalloc(count *
+							  sizeof(uint32_t)));
+		if (!properties.props_ptr)
+			goto err_allocs;
+		properties.prop_values_ptr = VOID2U64(drmMalloc(count *
+						      sizeof(uint64_t)));
+		if (!properties.prop_values_ptr)
+			goto err_allocs;
+	}
+
+	if (drmIoctl(fd, DRM_IOCTL_MODE_OBJ_GETPROPERTIES, &properties))
+		goto err_allocs;
+
+	if (count < properties.count_props) {
+		drmFree(U642VOID(properties.props_ptr));
+		drmFree(U642VOID(properties.prop_values_ptr));
+		goto retry;
+	}
+	count = properties.count_props;
+
+	ret = drmMalloc(sizeof(*ret));
+	if (!ret)
+		goto err_allocs;
+
+	ret->count_props = count;
+	ret->props = drmAllocCpy(U642VOID(properties.props_ptr),
+				 count, sizeof(uint32_t));
+	ret->prop_values = drmAllocCpy(U642VOID(properties.prop_values_ptr),
+				       count, sizeof(uint64_t));
+	if (ret->count_props && (!ret->props || !ret->prop_values)) {
+		drmFree(ret->props);
+		drmFree(ret->prop_values);
+		drmFree(ret);
+		ret = NULL;
+	}
+
+err_allocs:
+	drmFree(U642VOID(properties.props_ptr));
+	drmFree(U642VOID(properties.prop_values_ptr));
+	return ret;
+}
+
+void drmModeFreeObjectProperties(drmModeObjectPropertiesPtr ptr)
+{
+	if (!ptr)
+		return;
+	drmFree(ptr->props);
+	drmFree(ptr->prop_values);
+	drmFree(ptr);
+}
+
+int drmModeObjectSetProperty(int fd, uint32_t object_id, uint32_t object_type,
+			     uint32_t property_id, uint64_t value)
+{
+	struct drm_mode_obj_set_property prop;
+
+	prop.value = value;
+	prop.prop_id = property_id;
+	prop.obj_id = object_id;
+	prop.obj_type = object_type;
+
+	return DRM_IOCTL(fd, DRM_IOCTL_MODE_OBJ_SETPROPERTY, &prop);
+}
diff --git a/xf86drmMode.h b/xf86drmMode.h
index 991e3f9..8e40034 100644
--- a/xf86drmMode.h
+++ b/xf86drmMode.h
@@ -281,6 +281,12 @@ typedef struct _drmModeConnector {
 	uint32_t *encoders; /**< List of encoder ids */
 } drmModeConnector, *drmModeConnectorPtr;
 
+typedef struct _drmModeObjectProperties {
+	uint32_t count_props;
+	uint32_t *props;
+	uint64_t *prop_values;
+} drmModeObjectProperties, *drmModeObjectPropertiesPtr;
+
 typedef struct _drmModePlane {
 	uint32_t count_formats;
 	uint32_t *formats;
@@ -428,6 +434,14 @@ extern int drmModeSetPlane(int fd, uint32_t plane_id, uint32_t crtc_id,
 			   uint32_t src_x, uint32_t src_y,
 			   uint32_t src_w, uint32_t src_h);
 
+extern drmModeObjectPropertiesPtr drmModeObjectGetProperties(int fd,
+							uint32_t object_id,
+							uint32_t object_type);
+extern void drmModeFreeObjectProperties(drmModeObjectPropertiesPtr ptr);
+extern int drmModeObjectSetProperty(int fd, uint32_t object_id,
+				    uint32_t object_type, uint32_t property_id,
+				    uint64_t value);
+
 #if defined(__cplusplus) || defined(c_plusplus)
 }
 #endif

Attachment: signature.asc
Description: Digital signature


Reply to: