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

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



Your message dated Tue, 08 Jan 2013 19:53:54 +0000
with message-id <1357674834.4189.16.camel@jacala.jungle.funky-badger.org>
and subject line Re: Bug#696665: unblock: libdrm/2.4.40-1~deb7u1 (pre-approval, hw support)
has caused the Debian Bug report #696665,
regarding unblock: libdrm/2.4.40-1~deb7u1 (pre-approval, hw support)
to be marked as done.

This means that you claim that the problem has been dealt with.
If this is not the case it is now your responsibility to reopen the
Bug report if necessary, and/or fix the problem forthwith.

(NB: If you are a system administrator and have no idea what this
message is talking about, this may indicate a serious mail system
misconfiguration somewhere. Please contact owner@bugs.debian.org
immediately.)


-- 
696665: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=696665
Debian Bug Tracking System
Contact owner@bugs.debian.org with problems
--- Begin Message ---
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


--- End Message ---
--- Begin Message ---
On Sun, 2013-01-06 at 17:53 +0100, Julien Cristau wrote:
> On Sun, Jan  6, 2013 at 12:29:20 +0100, Julien Cristau wrote:
> 
> > On Fri, Jan  4, 2013 at 23:07:27 +0000, Adam D. Barratt wrote:
> > 
> > > Please go ahead.
> > > 
> > Thanks.  Uploaded last night.  Unfortunately FTBFS on kbsd, I'll work on
> > a fix...
> > 
> Fix uploaded (and built).  Additional changes:

Pre-emptively unblocked, on the assumption that if any
non-RC-but-important-enough-to-delay-transition issues arise then you'll
let us know (although in that case they should probably be RC anyway);
thanks.

Regards,

Adam

--- End Message ---

Reply to: