Fixes to Vivante BO on the resource leak and locking issues

Fix stuck issue while the app quit with "ctrl+c".

Upstream-Status: Pending

Signed-off-by: Yong Gan <yong.gan@nxp.com>
Signed-off-by: Prabhu Sundararaj <prabhu.sundararaj@nxp.com>
diff --git a/include/drm/vivante_drm.h b/include/drm/vivante_drm.h
index 29c7f27..b457372 100644
--- a/include/drm/vivante_drm.h
+++ b/include/drm/vivante_drm.h
@@ -1,18 +1,30 @@
-/*
- * Copyright © 2017 VIVANTE Corporation
- *
- * 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.
- *
- * 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.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program.  If not, see <http://www.gnu.org/licenses/>.
- */
+/****************************************************************************
+*
+*    Copyright 2012 - 2017 Vivante Corporation, Santa Clara, California.
+*    All Rights Reserved.
+*
+*    Permission is hereby granted, free of charge, to any person obtaining
+*    a copy of this software and associated documentation files (the
+*    'Software'), to deal in the Software without restriction, including
+*    without limitation the rights to use, copy, modify, merge, publish,
+*    distribute, sub license, and/or sell copies of the Software, and to
+*    permit persons to whom the Software is furnished to do so, subject
+*    to the following conditions:
+*
+*    The above copyright notice and this permission notice (including the
+*    next paragraph) shall be included in all copies or substantial
+*    portions of the Software.
+*
+*    THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
+*    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+*    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+*    IN NO EVENT SHALL VIVANTE AND/OR ITS SUPPLIERS BE LIABLE FOR ANY
+*    CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+*    TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+*    SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************/
+
 
 #ifndef __VIVNATE_DRM_H__
 #define __VIVNATE_DRM_H__
@@ -23,23 +35,33 @@
 extern "C" {
 #endif
 
+/* creation flag bits. */
+#define DRM_VIV_GEM_CONTIGUOUS      0x01
+#define DRM_VIV_GEM_CACHED          0x02
+#define DRM_VIV_GEM_SECURE          0x04
+
 struct drm_viv_gem_create {
-    __u64 size;         /* in */
-    __u32 flags;        /* in */
-    __u32 handle;       /* out */
+    __u64 size;
+    __u32 flags;
+    __u32 handle;
 };
 
 struct drm_viv_gem_lock {
     __u32 handle;
     __u32 cacheable;
-    __u32 gpu_va;
-    __u64 cpu_va;
+    __u64 logical;
 };
 
 struct drm_viv_gem_unlock {
     __u32 handle;
 };
 
+
+#define DRM_VIV_GEM_CLEAN_CACHE         0x01
+#define DRM_VIV_GEM_INVALIDATE_CACHE    0x02
+#define DRM_VIV_GEM_FLUSH_CACHE         0x03
+#define DRM_VIV_GEM_MEMORY_BARRIER      0x04
+
 struct drm_viv_gem_cache {
     __u32 handle;
     __u32 op;
@@ -47,24 +69,98 @@
     __u64 bytes;
 };
 
-struct drm_viv_gem_getinfo {
+
+#define DRM_VIV_GEM_PARAM_POOL      0x00
+#define DRM_VIV_GEM_PARAM_SIZE      0x01
+
+struct drm_viv_gem_query {
     __u32 handle;
     __u32 param;
     __u64 value;
 };
 
+
+struct drm_viv_gem_timestamp {
+    __u32 handle;
+    /* inc count, 0 for query current. */
+    __u32 inc;
+    /* output inc'ed timestamp. */
+    __u64 timestamp;
+};
+
+
+/* basic tiling mode. */
+#define DRM_VIV_GEM_TILING_LINEAR       0x01
+#define DRM_VIV_GEM_TILING_TILED        0x02
+#define DRM_VIV_GEM_TILING_SUPERTILED   0x04
+#define DRM_VIV_GEM_TILING_MINORTILED   0x08
+
+/* tiling mode modifiers. */
+#define DRM_VIV_GEM_TILING_SPLIT    0x10
+#define DRM_VIV_GEM_TILING_X_MAJOR  0x20
+#define DRM_VIV_GEM_TILING_Y_MAJOR  0x40
+#define DRM_VIV_GEM_TILING_SWAP     0x80
+
+/* ts mode. */
+#define DRM_VIV_GEM_TS_NONE         0x00
+#define DRM_VIV_GEM_TS_DISABLED     0x01
+#define DRM_VIV_GEM_TS_NORMAL       0x02
+#define DRM_VIV_GEM_TS_COMPRESSED   0x03
+
+struct drm_viv_gem_set_tiling {
+    __u32 handle;
+    __u32 tiling_mode;
+
+    __u32 ts_mode;
+    __u64 clear_value;
+};
+
+struct drm_viv_gem_get_tiling {
+    __u32 handle;
+    __u32 tiling_mode;
+
+    __u32 ts_mode;
+    __u64 clear_value;
+};
+
+
+struct drm_viv_gem_attach_aux {
+    __u32 handle;
+    __u32 ts_handle;
+};
+
+
+struct drm_viv_gem_ref_node {
+    __u32 handle;
+
+    /* output. */
+    __u32 node;
+    __u32 ts_node;
+};
+
+
 #define DRM_VIV_GEM_CREATE          0x00
 #define DRM_VIV_GEM_LOCK            0x01
 #define DRM_VIV_GEM_UNLOCK          0x02
 #define DRM_VIV_GEM_CACHE           0x03
-#define DRM_VIV_GEM_GETINFO         0x04
-#define DRM_VIV_NUM_IOCTLS          0x05
+#define DRM_VIV_GEM_QUERY           0x04
+#define DRM_VIV_GEM_TIMESTAMP       0x05
+#define DRM_VIV_GEM_SET_TILING      0x06
+#define DRM_VIV_GEM_GET_TILING      0x07
+#define DRM_VIV_GEM_ATTACH_AUX      0x08
+#define DRM_VIV_GEM_REF_NODE        0x09
+#define DRM_VIV_NUM_IOCTLS          0x0A
 
-#define DRM_IOCTL_VIV_GEM_CREATE    DRM_IOWR(DRM_COMMAND_BASE + DRM_VIV_GEM_CREATE,     struct drm_viv_gem_create)
-#define DRM_IOCTL_VIV_GEM_LOCK      DRM_IOWR(DRM_COMMAND_BASE + DRM_VIV_GEM_LOCK,       struct drm_viv_gem_lock)
-#define DRM_IOCTL_VIV_GEM_UNLOCK    DRM_IOWR(DRM_COMMAND_BASE + DRM_VIV_GEM_UNLOCK,     struct drm_viv_gem_unlock)
-#define DRM_IOCTL_VIV_GEM_CACHE     DRM_IOWR(DRM_COMMAND_BASE + DRM_VIV_GEM_CACHE,      struct drm_viv_gem_cache)
-#define DRM_IOCTL_VIV_GEM_GETINFO   DRM_IOWR(DRM_COMMAND_BASE + DRM_VIV_GEM_GETINFO,    struct drm_viv_gem_getinfo)
+#define DRM_IOCTL_VIV_GEM_CREATE        DRM_IOWR(DRM_COMMAND_BASE + DRM_VIV_GEM_CREATE,     struct drm_viv_gem_create)
+#define DRM_IOCTL_VIV_GEM_LOCK          DRM_IOWR(DRM_COMMAND_BASE + DRM_VIV_GEM_LOCK,       struct drm_viv_gem_lock)
+#define DRM_IOCTL_VIV_GEM_UNLOCK        DRM_IOWR(DRM_COMMAND_BASE + DRM_VIV_GEM_UNLOCK,     struct drm_viv_gem_unlock)
+#define DRM_IOCTL_VIV_GEM_CACHE         DRM_IOWR(DRM_COMMAND_BASE + DRM_VIV_GEM_CACHE,      struct drm_viv_gem_cache)
+#define DRM_IOCTL_VIV_GEM_QUERY         DRM_IOWR(DRM_COMMAND_BASE + DRM_VIV_GEM_QUERY,      struct drm_viv_gem_query)
+#define DRM_IOCTL_VIV_GEM_TIMESTAMP     DRM_IOWR(DRM_COMMAND_BASE + DRM_VIV_GEM_TIMESTAMP,  struct drm_viv_gem_timestamp)
+#define DRM_IOCTL_VIV_GEM_SET_TILING    DRM_IOWR(DRM_COMMAND_BASE + DRM_VIV_GEM_SET_TILING, struct drm_viv_gem_set_tiling)
+#define DRM_IOCTL_VIV_GEM_GET_TILING    DRM_IOWR(DRM_COMMAND_BASE + DRM_VIV_GEM_GET_TILING, struct drm_viv_gem_get_tiling)
+#define DRM_IOCTL_VIV_GEM_ATTACH_AUX    DRM_IOWR(DRM_COMMAND_BASE + DRM_VIV_GEM_ATTACH_AUX, struct drm_viv_gem_attach_aux)
+#define DRM_IOCTL_VIV_GEM_REF_NODE      DRM_IOWR(DRM_COMMAND_BASE + DRM_VIV_GEM_REF_NODE,   struct drm_viv_gem_ref_node)
 
 #if defined(__cplusplus)
 }
diff --git a/tests/vivante/Makefile.am b/tests/vivante/Makefile.am
index 8a0dedb..693a922 100644
--- a/tests/vivante/Makefile.am
+++ b/tests/vivante/Makefile.am
@@ -1,3 +1,29 @@
+##############################################################################
+#
+#    Copyright 2012 - 2017 Vivante Corporation, Santa Clara, California.
+#    All Rights Reserved.
+#
+#    Permission is hereby granted, free of charge, to any person obtaining
+#    a copy of this software and associated documentation files (the
+#    'Software'), to deal in the Software without restriction, including
+#    without limitation the rights to use, copy, modify, merge, publish,
+#    distribute, sub license, and/or sell copies of the Software, and to
+#    permit persons to whom the Software is furnished to do so, subject
+#    to the following conditions:
+#
+#    The above copyright notice and this permission notice (including the
+#    next paragraph) shall be included in all copies or substantial
+#    portions of the Software.
+#
+#    THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
+#    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+#    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+#    IN NO EVENT SHALL VIVANTE AND/OR ITS SUPPLIERS BE LIABLE FOR ANY
+#    CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+#    TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+#    SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+##############################################################################
 AM_CFLAGS = \
 	-pthread \
 	$(WARN_CFLAGS) \
diff --git a/tests/vivante/viv_bo_test.c b/tests/vivante/viv_bo_test.c
index aa21af3..4e9b066 100644
--- a/tests/vivante/viv_bo_test.c
+++ b/tests/vivante/viv_bo_test.c
@@ -1,3 +1,31 @@
+/****************************************************************************
+*
+*    Copyright 2012 - 2017 Vivante Corporation, Santa Clara, California.
+*    All Rights Reserved.
+*
+*    Permission is hereby granted, free of charge, to any person obtaining
+*    a copy of this software and associated documentation files (the
+*    'Software'), to deal in the Software without restriction, including
+*    without limitation the rights to use, copy, modify, merge, publish,
+*    distribute, sub license, and/or sell copies of the Software, and to
+*    permit persons to whom the Software is furnished to do so, subject
+*    to the following conditions:
+*
+*    The above copyright notice and this permission notice (including the
+*    next paragraph) shall be included in all copies or substantial
+*    portions of the Software.
+*
+*    THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
+*    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+*    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+*    IN NO EVENT SHALL VIVANTE AND/OR ITS SUPPLIERS BE LIABLE FOR ANY
+*    CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+*    TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+*    SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************/
+
+
 /*
  * Copyright © 2015 Canonical Ltd. (Maarten Lankhorst)
  *
@@ -33,89 +61,97 @@
 #include <pthread.h>
 
 #include "xf86drm.h"
-#include "vivante.h"
+#include "vivante_bo.h"
 
-static int import_fd;
+static int import_fd = -1;
 
 static void *
 openclose(void *dev)
 {
-	int fd = (intptr_t)dev;
-	uint32_t bo_handle;
-	int i;
+    struct drm_vivante *drm = dev;
+    struct drm_vivante_bo *bo;
+    int i;
 
-	for (i = 0; i < 100000; ++i) {
-		if (!drmPrimeFDToHandle(fd, import_fd, &bo_handle))
-			drm_vivante_bo_destroy(fd, bo_handle);
-	}
-	return NULL;
+    for (i = 0; i < 100000; ++i) {
+        if (!drm_vivante_bo_import_from_fd(drm, import_fd, &bo))
+            drm_vivante_bo_destroy(bo);
+    }
+    return NULL;
 }
 
 int main(int argc, char *argv[])
 {
-	drmVersionPtr version;
-	const char *device = NULL;
-	int err, fd1, fd2;
-	uint32_t bo_handle;
-	pthread_t t1, t2;
+    drmVersionPtr version;
+    const char *device = NULL;
+    int err, fd1, fd2;
+    struct drm_vivante *drm1, *drm2;
+    struct drm_vivante_bo *bo;
+    pthread_t t1, t2;
 
-	if (argc < 2) {
-		fd1 = drmOpenWithType("vivante", NULL, DRM_NODE_RENDER);
-		if (fd1 >= 0)
-			fd2 = drmOpenWithType("vivante", NULL, DRM_NODE_RENDER);
-	} else {
-		device = argv[1];
+    if (argc < 2) {
+        fd1 = drmOpenWithType("vivante", NULL, DRM_NODE_RENDER);
+        if (fd1 >= 0)
+            fd2 = drmOpenWithType("vivante", NULL, DRM_NODE_RENDER);
+    } else {
+        device = argv[1];
 
-		fd1 = open(device, O_RDWR);
-		if (fd1 >= 0)
-			fd2 = open(device, O_RDWR);
-		else
-			fd2 = fd1 = -errno;
-	}
+        fd1 = open(device, O_RDWR);
+        if (fd1 >= 0)
+            fd2 = open(device, O_RDWR);
+        else
+            fd2 = fd1 = -errno;
+    }
 
-	if (fd1 < 0) {
-		fprintf(stderr, "Opening 1st vivante render node failed with %i\n", fd1);
-		return device ? -fd1 : 77;
-	}
+    if (fd1 < 0) {
+        fprintf(stderr, "Opening 1st vivante render node failed with %i\n", fd1);
+        return device ? -fd1 : 77;
+    }
 
-	if (fd2 < 0) {
-		fprintf(stderr, "Opening 2nd vivante render node failed with %i\n", -errno);
-		return errno;
-	}
+    if (fd2 < 0) {
+        fprintf(stderr, "Opening 2nd vivante render node failed with %i\n", -errno);
+        return errno;
+    }
 
-	version = drmGetVersion(fd1);
-	if (version) {
-		printf("Version: %d.%d.%d\n", version->version_major,
-		       version->version_minor, version->version_patchlevel);
-		printf("  Name: %s\n", version->name);
-		printf("  Date: %s\n", version->date);
-		printf("  Description: %s\n", version->desc);
+    version = drmGetVersion(fd1);
+    if (version) {
+        printf("Version: %d.%d.%d\n", version->version_major,
+               version->version_minor, version->version_patchlevel);
+        printf("  Name: %s\n", version->name);
+        printf("  Date: %s\n", version->date);
+        printf("  Description: %s\n", version->desc);
 
-		drmFreeVersion(version);
-	}
+        drmFreeVersion(version);
+    }
 
-	err = drm_vivante_bo_create(fd2, 0, 4096, &bo_handle);
-	if (!err)
-        err = drmPrimeHandleToFD(fd2, bo_handle, DRM_CLOEXEC, &import_fd);
+    err = drm_vivante_create(fd1, &drm1);
+    if (!err)
+        err = drm_vivante_create(fd2, &drm2);
+    if (err < 0)
+        return 1;
 
-	if (!err) {
-		pthread_create(&t1, NULL, openclose, (void*)(intptr_t)fd1);
-		pthread_create(&t2, NULL, openclose, (void*)(intptr_t)fd1);
-	}
+    err = drm_vivante_bo_create(drm2, 0, 1920*1080*4, &bo);
+    if (!err)
+        err = drm_vivante_bo_export_to_fd(bo, &import_fd);
 
-	pthread_join(t1, NULL);
-	pthread_join(t2, NULL);
+    if (!err) {
+        pthread_create(&t1, NULL, openclose, (void*)drm1);
+        pthread_create(&t2, NULL, openclose, (void*)drm1);
+    }
 
-	close(import_fd);
-	drm_vivante_bo_destroy(fd2, bo_handle);
+    pthread_join(t1, NULL);
+    pthread_join(t2, NULL);
 
-	if (device) {
-		close(fd2);
-		close(fd1);
-	} else {
-		drmClose(fd2);
-		drmClose(fd1);
-	}
+    drm_vivante_bo_destroy(bo);
 
-	return 0;
+    drm_vivante_close(drm2);
+    drm_vivante_close(drm1);
+    if (device) {
+        close(fd2);
+        close(fd1);
+    } else {
+        drmClose(fd2);
+        drmClose(fd1);
+    }
+
+    return 0;
 }
diff --git a/vivante/Android.mk b/vivante/Android.mk
index 234028a..ccb9a02 100644
--- a/vivante/Android.mk
+++ b/vivante/Android.mk
@@ -1,11 +1,39 @@
+##############################################################################
+#
+#    Copyright 2012 - 2017 Vivante Corporation, Santa Clara, California.
+#    All Rights Reserved.
+#
+#    Permission is hereby granted, free of charge, to any person obtaining
+#    a copy of this software and associated documentation files (the
+#    'Software'), to deal in the Software without restriction, including
+#    without limitation the rights to use, copy, modify, merge, publish,
+#    distribute, sub license, and/or sell copies of the Software, and to
+#    permit persons to whom the Software is furnished to do so, subject
+#    to the following conditions:
+#
+#    The above copyright notice and this permission notice (including the
+#    next paragraph) shall be included in all copies or substantial
+#    portions of the Software.
+#
+#    THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
+#    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+#    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+#    IN NO EVENT SHALL VIVANTE AND/OR ITS SUPPLIERS BE LIABLE FOR ANY
+#    CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+#    TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+#    SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+##############################################################################
+
+
 LOCAL_PATH := $(call my-dir)
 include $(CLEAR_VARS)
 
-LOCAL_MODULE := libdrm_vivante
+LOCAL_SRC_FILES := vivante_bo.c
+
+LOCAL_CFLAGS := -Wno-unused-parameter
 
 LOCAL_SHARED_LIBRARIES := libdrm
 
-LOCAL_SRC_FILES := vivante.c
-
-include $(LIBDRM_COMMON_MK)
+LOCAL_MODULE := libdrm_vivante
 include $(BUILD_SHARED_LIBRARY)
diff --git a/vivante/Makefile.am b/vivante/Makefile.am
index 8963bf0..cd4c73e 100644
--- a/vivante/Makefile.am
+++ b/vivante/Makefile.am
@@ -1,3 +1,31 @@
+##############################################################################
+#
+#    Copyright 2012 - 2017 Vivante Corporation, Santa Clara, California.
+#    All Rights Reserved.
+#
+#    Permission is hereby granted, free of charge, to any person obtaining
+#    a copy of this software and associated documentation files (the
+#    'Software'), to deal in the Software without restriction, including
+#    without limitation the rights to use, copy, modify, merge, publish,
+#    distribute, sub license, and/or sell copies of the Software, and to
+#    permit persons to whom the Software is furnished to do so, subject
+#    to the following conditions:
+#
+#    The above copyright notice and this permission notice (including the
+#    next paragraph) shall be included in all copies or substantial
+#    portions of the Software.
+#
+#    THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
+#    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+#    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+#    IN NO EVENT SHALL VIVANTE AND/OR ITS SUPPLIERS BE LIABLE FOR ANY
+#    CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+#    TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+#    SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+##############################################################################
+
+
 AM_CPPFLAGS = \
 	-I$(top_srcdir) \
 	-I$(top_srcdir)/include/drm
@@ -12,10 +40,10 @@
 libdrm_vivante_la_LIBADD = ../libdrm.la @PTHREADSTUBS_LIBS@
 
 libdrm_vivante_la_SOURCES = \
-	vivante.c
+	vivante_bo.c
 
 libdrm_vivanteincludedir = ${includedir}/libdrm
-libdrm_vivanteinclude_HEADERS = vivante.h
+libdrm_vivanteinclude_HEADERS = vivante_bo.h
 
 pkgconfigdir = @pkgconfigdir@
 pkgconfig_DATA = libdrm_vivante.pc
diff --git a/vivante/libdrm_vivante.pc b/vivante/libdrm_vivante.pc
new file mode 100644
index 0000000..474a33c
--- /dev/null
+++ b/vivante/libdrm_vivante.pc
@@ -0,0 +1,11 @@
+prefix=/usr
+exec_prefix=${prefix}
+libdir=${exec_prefix}/lib
+includedir=${prefix}/include
+
+Name: libdrm_vivante
+Description: Userspace interface to Vivante kernel DRM services
+Version: 2.4.84
+Libs: -L${libdir} -ldrm_vivante
+Cflags: -I${includedir} -I${includedir}/libdrm
+Requires.private: libdrm
diff --git a/vivante/vivante-symbol-check b/vivante/vivante-symbol-check
index 29c12a0..177bba9 100644
--- a/vivante/vivante-symbol-check
+++ b/vivante/vivante-symbol-check
@@ -1,6 +1,6 @@
 #!/bin/bash
 
-# The following symbols (past the first nine) are taken from vivante.h.
+# The following symbols (past the first nine) are taken from vivante_bo.h.
 
 FUNCS=$(nm -D --format=bsd --defined-only ${1-.libs/libdrm_vivante.so} | awk '{print $3}'| while read func; do
 ( grep -q "^$func$" || echo $func )  <<EOF
@@ -14,10 +14,18 @@
 _fini
 _init
 drm_vivante_bo_create
+drm_vivante_bo_create_with_ts
+drm_vivante_bo_export_to_fd
+drm_vivante_bo_import_from_fd
 drm_vivante_bo_destroy
-drm_vivante_bo_lock
-drm_vivante_bo_unlock
-drm_vivante_bo_cache
-drm_vivante_bo_getinfo
+drm_vivante_bo_get_handle
+drm_vivante_bo_mmap
+drm_vivante_bo_munmap
+drm_vivante_bo_query
+drm_vivante_bo_set_tiling
+drm_vivante_bo_get_tiling
+drm_vivante_bo_inc_timestamp
+drm_vivante_bo_get_timestamp
+drm_vivante_bo_ref_node
 EOF
 done)
diff --git a/vivante/vivante.c b/vivante/vivante.c
deleted file mode 100644
index b82138c..0000000
--- a/vivante/vivante.c
+++ /dev/null
@@ -1,145 +0,0 @@
-/*
- * Copyright © 2012, 2013 Thierry Reding
- * Copyright © 2013 Erik Faye-Lund
- * Copyright © 2014 NVIDIA Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#ifdef HAVE_CONFIG_H
-#  include "config.h"
-#endif
-
-#include <errno.h>
-#include <fcntl.h>
-#include <string.h>
-#include <unistd.h>
-
-#include <sys/mman.h>
-
-#include <xf86drm.h>
-
-#include <vivante_drm.h>
-
-#include "vivante.h"
-
-int drm_vivante_bo_create(int fd, uint32_t flags, uint32_t size, uint32_t *handle)
-{
-    struct drm_viv_gem_create args;
-    int err = 0;
-
-    if (size == 0 || !handle)
-        return -EINVAL;
-
-    memset(&args, 0, sizeof(args));
-    args.flags = flags;
-    args.size = size;
-
-    if (drmIoctl(fd, DRM_IOCTL_VIV_GEM_CREATE, &args))
-        return -errno;
-
-    *handle = args.handle;
-
-    return 0;
-}
-
-int drm_vivante_bo_destroy(int fd, uint32_t handle)
-{
-    struct drm_gem_close args;
-
-    if (!handle)
-        return -EINVAL;
-
-    args.handle = handle;
-    if (drmIoctl(fd, DRM_IOCTL_GEM_CLOSE, &args))
-        return -errno;
-
-    return 0;
-}
-
-void* drm_vivante_bo_lock(int fd, uint32_t handle, uint32_t *gpu_va)
-{
-    struct drm_viv_gem_lock args;
-
-    if (!handle)
-        return NULL;
-
-    args.handle = handle;
-    args.cacheable = 0;
-    if (drmIoctl(fd, DRM_IOCTL_VIV_GEM_LOCK, &args))
-        return NULL;
-
-    if (gpu_va)
-    {
-        *gpu_va = args.gpu_va;
-    }
-
-    return (void*)(intptr_t)args.cpu_va;
-}
-
-int drm_vivante_bo_unlock(int fd, uint32_t handle)
-{
-    struct drm_viv_gem_unlock args;
-
-    if (!handle)
-        return -EINVAL;
-
-    args.handle = handle;
-    if (drmIoctl(fd, DRM_IOCTL_VIV_GEM_UNLOCK, &args))
-        return -errno;
-
-    return 0;
-}
-
-int drm_vivante_bo_cache(int fd, uint32_t handle, uint32_t op, void* logical, uint32_t bytes)
-{
-    struct drm_viv_gem_cache args;
-
-    if (!handle)
-        return -EINVAL;
-
-    args.handle = handle;
-    args.op = handle;
-    args.logical = (uintptr_t)logical;
-    args.bytes = bytes;
-    if (drmIoctl(fd, DRM_IOCTL_VIV_GEM_CACHE, &args))
-        return -errno;
-
-    return 0;
-}
-
-int drm_vivante_bo_getinfo(int fd, uint32_t handle, uint32_t param, uint64_t *value)
-{
-    struct drm_viv_gem_getinfo args;
-
-    if (!handle)
-        return -EINVAL;
-
-    args.handle = handle;
-    args.param  = param;
-    if (drmIoctl(fd, DRM_IOCTL_VIV_GEM_GETINFO, &args))
-        return -errno;
-
-    *value = args.value;
-
-    return 0;
-}
-
-
-
diff --git a/vivante/vivante.h b/vivante/vivante.h
deleted file mode 100644
index 2492e5a..0000000
--- a/vivante/vivante.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright © 2017 VIVANTE Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#ifndef __DRM_VIVANTE_H__
-#define __DRM_VIVANTE_H__ 1
-
-#include <stdint.h>
-#include <stdlib.h>
-
-enum VIV_CACHE_OP {
-    VIV_CACHE_CLEAN      = 0x01,
-    VIV_CACHE_INVALIDATE = 0x02,
-    VIV_CACHE_FLUSH      = VIV_CACHE_CLEAN  | VIV_CACHE_INVALIDATE,
-    VIV_CACHE_BARRIER    = 0x04
-};
-
-enum VIV_GEM_PARAM {
-    VIV_GEM_PARAM_NODE = 0,
-    VIV_GEM_PARAM_POOL,
-    VIV_GEM_PARAM_SIZE,
-};
-
-int drm_vivante_bo_create(int fd, uint32_t flags, uint32_t size, uint32_t *handle);
-int drm_vivante_bo_destroy(int fd, uint32_t handle);
-void* drm_vivante_bo_lock(int fd, uint32_t handle, uint32_t *gpu_va);
-int drm_vivante_bo_unlock(int fd, uint32_t handle);
-int drm_vivante_bo_cache(int fd, uint32_t handle, uint32_t op, void* logical, uint32_t bytes);
-int drm_vivante_bo_getinfo(int fd, uint32_t handle, uint32_t param, uint64_t *value);
-
-#endif /* __DRM_VIVANTE_H__ */
diff --git a/vivante/vivante_bo.c b/vivante/vivante_bo.c
new file mode 100644
index 0000000..fe74384
--- /dev/null
+++ b/vivante/vivante_bo.c
@@ -0,0 +1,474 @@
+/****************************************************************************
+*
+*    Copyright 2012 - 2017 Vivante Corporation, Santa Clara, California.
+*    All Rights Reserved.
+*
+*    Permission is hereby granted, free of charge, to any person obtaining
+*    a copy of this software and associated documentation files (the
+*    'Software'), to deal in the Software without restriction, including
+*    without limitation the rights to use, copy, modify, merge, publish,
+*    distribute, sub license, and/or sell copies of the Software, and to
+*    permit persons to whom the Software is furnished to do so, subject
+*    to the following conditions:
+*
+*    The above copyright notice and this permission notice (including the
+*    next paragraph) shall be included in all copies or substantial
+*    portions of the Software.
+*
+*    THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
+*    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+*    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+*    IN NO EVENT SHALL VIVANTE AND/OR ITS SUPPLIERS BE LIABLE FOR ANY
+*    CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+*    TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+*    SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************/
+
+
+#ifdef HAVE_CONFIG_H
+#  include "config.h"
+#endif
+
+#include <errno.h>
+#include <fcntl.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <sys/mman.h>
+
+#include <xf86drm.h>
+
+#include <vivante_drm.h>
+
+#include "vivante_bo.h"
+
+struct drm_vivante
+{
+    /* driver fd. */
+    int fd;
+};
+
+struct drm_vivante_bo
+{
+    struct drm_vivante *drm;
+
+    uint32_t handle;
+
+    /* export prime fd if any */
+    int fd;
+
+    uint32_t flags;
+    uint32_t size;
+
+    void *vaddr;
+};
+
+int drm_vivante_create(int fd, struct drm_vivante **drmp)
+{
+    int supported = 0;
+    drmVersionPtr version;
+    struct drm_vivante *drm;
+
+    version = drmGetVersion(fd);
+    if (!version)
+        return -ENOMEM;
+
+    if (!strncmp(version->name, "vivante", version->name_len))
+        supported = 1;
+
+    drmFreeVersion(version);
+
+    if (!supported)
+        return -ENOTSUP;
+
+    drm = calloc(1, sizeof(struct drm_vivante));
+    if (!drm)
+        return -ENOMEM;
+
+    drm->fd = fd;
+    *drmp = drm;
+
+    return 0;
+}
+
+void drm_vivante_close(struct drm_vivante *drm)
+{
+    free(drm);
+}
+
+static int drm_vivante_bo_init(struct drm_vivante *drm,
+                struct drm_vivante_bo **bop)
+{
+    struct drm_vivante_bo *bo;
+
+    bo = calloc(1, sizeof(*bo));
+    if (!bo)
+        return -ENOMEM;
+
+    bo->drm = drm;
+    bo->fd = -1;
+    bo->vaddr = NULL;
+
+    *bop = bo;
+    return 0;
+}
+
+int drm_vivante_bo_create(struct drm_vivante *drm,
+            uint32_t flags, uint32_t size, struct drm_vivante_bo **bop)
+{
+    int err = 0;
+    struct drm_vivante_bo *bo;
+    struct drm_viv_gem_create args = {
+        .flags = flags,
+        .size  = size
+    };
+
+    if (size == 0)
+        return -EINVAL;
+
+    if (!drm || !bop)
+        return -EINVAL;
+
+    err = drm_vivante_bo_init(drm, &bo);
+    if (err) {
+        return err;
+    }
+
+    if (drmIoctl(drm->fd, DRM_IOCTL_VIV_GEM_CREATE, &args)) {
+        free(bo);
+        return -errno;
+    }
+    bo->handle = args.handle;
+    bo->flags = flags;
+    bo->size = size;
+
+    *bop = bo;
+    return 0;
+}
+
+int drm_vivante_bo_create_with_ts(struct drm_vivante *drm,
+            uint32_t flags, uint32_t size, struct drm_vivante_bo **bop)
+{
+    int err = 0;
+    uint32_t ts_handle = 0;
+    struct drm_vivante_bo *bo;
+    struct drm_viv_gem_create args = {
+        .flags = flags,
+        .size  = size
+    };
+    struct drm_gem_close close_args;
+    struct drm_viv_gem_attach_aux aux_args;
+    const uint32_t valid_ts_flags = DRM_VIV_GEM_CONTIGUOUS | DRM_VIV_GEM_SECURE;
+
+    if (size == 0)
+        return -EINVAL;
+
+    if (!drm || !bop)
+        return -EINVAL;
+
+    err = drm_vivante_bo_init(drm, &bo);
+    if (err)
+        return err;
+
+    if (drmIoctl(drm->fd, DRM_IOCTL_VIV_GEM_CREATE, &args)) {
+        err = -errno;
+        goto err_close;
+    }
+    bo->handle = args.handle;
+
+    /* alloc ts handle, size is master buffer size / 256, align up to 64B. */
+    args.flags = flags & valid_ts_flags;
+    args.size  = ((size >> 8) + 0x3f) & ~0x3f;
+    if (drmIoctl(drm->fd, DRM_IOCTL_VIV_GEM_CREATE, &args)) {
+        err = -errno;
+        goto err_close;
+    }
+    ts_handle = args.handle;
+
+    /* ref ts_handle in master handle. */
+    aux_args.handle = bo->handle;
+    aux_args.ts_handle = ts_handle;
+    if (drmIoctl(drm->fd, DRM_IOCTL_VIV_GEM_ATTACH_AUX, &aux_args)) {
+        err = -errno;
+        goto err_close;
+    }
+
+    /* Now ts was attached to master, destroy it now. */
+    close_args.handle = ts_handle;
+    if (drmIoctl(drm->fd, DRM_IOCTL_GEM_CLOSE, &close_args)) {
+        err = -errno;
+        goto err_close;
+    }
+    ts_handle = 0;
+
+    bo->flags = flags;
+    bo->size = size;
+
+    *bop = bo;
+    return 0;
+
+err_close:
+    if (bo->handle) {
+
+        if (ts_handle) {
+            close_args.handle = ts_handle;
+            drmIoctl(drm->fd, DRM_IOCTL_GEM_CLOSE, &close_args);
+        }
+
+        close_args.handle = bo->handle;
+        drmIoctl(drm->fd, DRM_IOCTL_GEM_CLOSE, &close_args);
+    }
+
+    free(bo);
+    return err;
+}
+
+int drm_vivante_bo_export_to_fd(struct drm_vivante_bo *bo, int *pfd)
+{
+    if (!bo || !pfd)
+        return -EINVAL;
+
+    if (bo->fd < 0) {
+        int fd;
+        if (drmPrimeHandleToFD(bo->drm->fd, bo->handle, O_RDWR, &fd))
+            return -errno;
+        bo->fd = fd;
+    }
+
+    *pfd = bo->fd;
+    return 0;
+}
+
+int drm_vivante_bo_import_from_fd(struct drm_vivante *drm, int fd,
+            struct drm_vivante_bo **bop)
+{
+    int err;
+    uint64_t size;
+    uint32_t handle = 0;
+    struct drm_vivante_bo *bo = NULL;
+
+    if (!drm || !bop || fd < 0)
+        return -EINVAL;
+
+    err = drm_vivante_bo_init(drm, &bo);
+    if (err)
+        return err;
+
+    if (drmPrimeFDToHandle(drm->fd, fd, &handle)) {
+        err = -errno;
+        goto err_close;
+    }
+    bo->handle = handle;
+
+    err = drm_vivante_bo_query(bo, DRM_VIV_GEM_PARAM_SIZE, &size);
+    if (err)
+        goto err_close;
+    bo->size = (uint32_t)size;
+
+    *bop = bo;
+    return 0;
+
+err_close:
+    if (handle > 0) {
+        struct drm_gem_close close_args = {
+            .handle = handle,
+        };
+        drmIoctl(drm->fd, DRM_IOCTL_GEM_CLOSE, &close_args);
+    }
+    free(bo);
+
+    return err;
+}
+
+void drm_vivante_bo_destroy(struct drm_vivante_bo *bo)
+{
+    struct drm_gem_close close_args;
+
+    if (!bo)
+        return;
+
+    if (bo->vaddr) {
+        drm_vivante_bo_munmap(bo);
+    }
+
+    close_args.handle = bo->handle;
+    drmIoctl(bo->drm->fd, DRM_IOCTL_GEM_CLOSE, &close_args);
+
+    free(bo);
+}
+
+int drm_vivante_bo_get_handle(struct drm_vivante_bo *bo, uint32_t *handle)
+{
+    if (!bo || !handle)
+        return -EINVAL;
+
+    *handle = bo->handle;
+    return 0;
+}
+
+static int clean_bo_cache(struct drm_vivante_bo *bo)
+{
+    struct drm_viv_gem_cache args = {
+        .op = DRM_VIV_GEM_CLEAN_CACHE,
+        .handle = bo->handle,
+        .logical = (uint64_t)(uintptr_t)bo->vaddr,
+        .bytes = bo->size
+    };
+
+    if (drmIoctl(bo->drm->fd, DRM_IOCTL_VIV_GEM_CACHE, &args))
+        return -errno;
+
+    return 0;
+}
+
+
+int drm_vivante_bo_mmap(struct drm_vivante_bo *bo, void **vaddr)
+{
+    struct drm_viv_gem_lock args;
+
+    if (!bo || !vaddr)
+        return -EINVAL;
+
+    /* already locked */
+    if (bo->vaddr)
+        return -EPERM;
+        
+    args.handle = bo->handle;
+    args.cacheable = (bo->flags & DRM_VIV_GEM_CACHED) ? 1 : 0;
+    if (drmIoctl(bo->drm->fd, DRM_IOCTL_VIV_GEM_LOCK, &args))
+        return -errno;
+
+    bo->vaddr = (void *)(uintptr_t)args.logical;
+
+    *vaddr = bo->vaddr;
+    return 0;
+}
+
+int drm_vivante_bo_munmap(struct drm_vivante_bo *bo)
+{
+    struct drm_viv_gem_unlock args;
+
+    if (!bo || !bo->vaddr)
+        return -EINVAL;
+
+    args.handle = bo->handle;
+    if (bo->flags & DRM_VIV_GEM_CACHED) {
+        int err = clean_bo_cache(bo);
+        if (err)
+            return err;
+    }
+
+    if (drmIoctl(bo->drm->fd, DRM_IOCTL_VIV_GEM_UNLOCK, &args))
+        return -errno;
+
+    bo->vaddr = NULL;
+    return 0;
+}
+
+int drm_vivante_bo_query(struct drm_vivante_bo *bo,
+            uint32_t param, uint64_t *value)
+{
+    struct drm_viv_gem_query args = {
+        .param = param,
+    };
+
+    if (!bo || !value)
+        return -EINVAL;
+
+    args.handle = bo->handle;
+    if (drmIoctl(bo->drm->fd, DRM_IOCTL_VIV_GEM_QUERY, &args))
+        return -errno;
+
+    *value = args.value;
+    return 0;
+}
+
+int drm_vivante_bo_set_tiling(struct drm_vivante_bo *bo,
+            const struct drm_vivante_bo_tiling *tiling)
+{
+    struct drm_viv_gem_set_tiling args;
+
+    if (!bo || !tiling)
+        return -EINVAL;
+
+    args = (struct drm_viv_gem_set_tiling) {
+        .handle = bo->handle,
+        .tiling_mode = tiling->tiling_mode,
+        .ts_mode = tiling->ts_mode,
+        .clear_value = tiling->clear_value,
+    };
+
+    if (drmIoctl(bo->drm->fd, DRM_IOCTL_VIV_GEM_SET_TILING, &args))
+        return -errno;
+
+    return 0;
+}
+
+int drm_vivante_bo_get_tiling(struct drm_vivante_bo *bo,
+            struct drm_vivante_bo_tiling *tiling)
+{
+    struct drm_viv_gem_get_tiling args;
+
+    if (!bo || !tiling)
+        return -EINVAL;
+
+    args.handle = bo->handle;
+    if (drmIoctl(bo->drm->fd, DRM_IOCTL_VIV_GEM_GET_TILING, &args))
+        return -errno;
+
+    tiling->tiling_mode = args.tiling_mode;
+    tiling->ts_mode = args.ts_mode;
+    tiling->clear_value = args.clear_value;
+
+    return 0;
+}
+
+static inline int inc_bo_timestamp(struct drm_vivante_bo *bo,
+                        uint32_t inc, uint64_t *timestamp)
+{
+    struct drm_viv_gem_timestamp args = {
+        .handle = bo->handle,
+        .inc = inc,
+    };
+    if (drmIoctl(bo->drm->fd, DRM_IOCTL_VIV_GEM_TIMESTAMP, &args))
+        return -errno;
+
+    if (timestamp)
+        *timestamp = args.timestamp;
+    return 0;
+}
+
+int drm_vivante_bo_inc_timestamp(struct drm_vivante_bo *bo,
+            uint64_t *timestamp)
+{
+    if (!bo)
+        return -EINVAL;
+    return inc_bo_timestamp(bo, 1, timestamp);
+}
+
+int drm_vivante_bo_get_timestamp(struct drm_vivante_bo *bo,
+            uint64_t *timestamp)
+{
+    if (!bo || !timestamp)
+        return -EINVAL;
+    return inc_bo_timestamp(bo, 0, timestamp);
+}
+
+int drm_vivante_bo_ref_node(struct drm_vivante_bo *bo,
+            uint32_t *node, uint32_t *ts_node)
+{
+    struct drm_viv_gem_ref_node args;
+
+    if (!bo || !node || !ts_node)
+        return -EINVAL;
+
+    args.handle = bo->handle;
+    if (drmIoctl(bo->drm->fd, DRM_IOCTL_VIV_GEM_REF_NODE, &args))
+        return -errno;
+
+    *node = args.node;
+    *ts_node = args.ts_node;
+    return 0;
+}
+
diff --git a/vivante/vivante_bo.h b/vivante/vivante_bo.h
new file mode 100644
index 0000000..a12f2a3
--- /dev/null
+++ b/vivante/vivante_bo.h
@@ -0,0 +1,87 @@
+/****************************************************************************
+*
+*    Copyright 2012 - 2017 Vivante Corporation, Santa Clara, California.
+*    All Rights Reserved.
+*
+*    Permission is hereby granted, free of charge, to any person obtaining
+*    a copy of this software and associated documentation files (the
+*    'Software'), to deal in the Software without restriction, including
+*    without limitation the rights to use, copy, modify, merge, publish,
+*    distribute, sub license, and/or sell copies of the Software, and to
+*    permit persons to whom the Software is furnished to do so, subject
+*    to the following conditions:
+*
+*    The above copyright notice and this permission notice (including the
+*    next paragraph) shall be included in all copies or substantial
+*    portions of the Software.
+*
+*    THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
+*    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+*    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+*    IN NO EVENT SHALL VIVANTE AND/OR ITS SUPPLIERS BE LIABLE FOR ANY
+*    CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+*    TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+*    SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************/
+
+
+#ifndef __DRM_VIVANTE_H__
+#define __DRM_VIVANTE_H__
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <vivante_drm.h>
+
+struct drm_vivante_bo;
+struct drm_vivante;
+
+struct drm_vivante_bo_tiling {
+    uint32_t tiling_mode;
+    uint32_t ts_mode;
+    uint64_t clear_value;
+};
+
+/* caller owns the driver fd. */
+int drm_vivante_create(int fd, struct drm_vivante **drmp);
+void drm_vivante_close(struct drm_vivante *drm);
+
+int drm_vivante_bo_create(struct drm_vivante *drm,
+            uint32_t flags, uint32_t size, struct drm_vivante_bo **bop);
+
+/* create bo with auxillary tile-status bo. */
+int drm_vivante_bo_create_with_ts(struct drm_vivante *drm,
+            uint32_t flags, uint32_t size, struct drm_vivante_bo **bop);
+
+/* caller owns the fd. */
+int drm_vivante_bo_export_to_fd(struct drm_vivante_bo *bo, int *pfd);
+/* caller still owns the fd upon return. */
+int drm_vivante_bo_import_from_fd(struct drm_vivante *drm, int fd,
+        struct drm_vivante_bo **bop);
+
+void drm_vivante_bo_destroy(struct drm_vivante_bo *bo);
+
+/* do not close the handle directly. */
+int drm_vivante_bo_get_handle(struct drm_vivante_bo *bo, uint32_t *handle);
+
+int drm_vivante_bo_mmap(struct drm_vivante_bo *bo, void **vaddr);
+int drm_vivante_bo_munmap(struct drm_vivante_bo *bo);
+
+int drm_vivante_bo_query(struct drm_vivante_bo *bo,
+            uint32_t param, uint64_t *value);
+
+int drm_vivante_bo_set_tiling(struct drm_vivante_bo *bo,
+            const struct drm_vivante_bo_tiling *tiling);
+int drm_vivante_bo_get_tiling(struct drm_vivante_bo *bo,
+            struct drm_vivante_bo_tiling *tiling);
+
+/* output inc'ed timestamp, optional. */
+int drm_vivante_bo_inc_timestamp(struct drm_vivante_bo *bo,
+            uint64_t *timestamp);
+int drm_vivante_bo_get_timestamp(struct drm_vivante_bo *bo,
+            uint64_t *timestamp);
+
+int drm_vivante_bo_ref_node(struct drm_vivante_bo *bo,
+            uint32_t *node, uint32_t *ts_node);
+
+#endif /* __DRM_VIVANTE_H__ */