hikey: gralloc960 Update for new ION interface

4.12+ kernels have an updated ION interface; this adapts hikey's gralloc
to work seemlessly with both old and new kernels' interfaces.

Currently supports only system heaps.

Change-Id: Ice26d05f65bb4dfcc5ce2ae3bbcbbab4e9a3723a
Signed-off-by: Sumit Semwal <sumit.semwal@linaro.org>
[jstultz: Build fixes]
Signed-off-by: John Stultz <john.stultz@linaro.org>
diff --git a/gralloc960/alloc_ion.cpp b/gralloc960/alloc_ion.cpp
index 2af9d94..0a84aaa 100644
--- a/gralloc960/alloc_ion.cpp
+++ b/gralloc960/alloc_ion.cpp
@@ -16,6 +16,7 @@
  * limitations under the License.
  */
 
+#include <cstdlib>
 #include <string.h>
 #include <errno.h>
 #include <inttypes.h>
@@ -32,6 +33,7 @@
 #include "gralloc_priv.h"
 #include "gralloc_helper.h"
 #include "framebuffer_device.h"
+#include "ion_4.12.h"
 
 #include "mali_gralloc_formats.h"
 
@@ -148,6 +150,51 @@
 	return ion_hnd;
 }
 
+static int find_system_heap_id(int ion_client)
+{
+	int i, ret, cnt, system_heap_id = -1;
+	struct ion_heap_data *data;
+
+	ret = ion_query_heap_cnt(ion_client, &cnt);
+
+	if (ret)
+	{
+		AERR("ion count query failed with %s", strerror(errno));
+		return -1;
+	}
+
+	data = (struct ion_heap_data *)malloc(cnt * sizeof(*data));
+	if (!data)
+	{
+		AERR("Error allocating data %s\n", strerror(errno));
+		return -1;
+	}
+
+	ret = ion_query_get_heaps(ion_client, cnt, data);
+	if (ret)
+	{
+		AERR("Error querying heaps from ion %s", strerror(errno));
+	}
+	else
+	{
+		for (i = 0; i < cnt; i++) {
+			if (strcmp(data[i].name, "ion_system_heap") == 0) {
+				system_heap_id = data[i].heap_id;
+				break;
+			}
+		}
+
+		if (i == cnt)
+		{
+			AERR("No System Heap Found amongst %d heaps\n", cnt);
+			system_heap_id = -1;
+		}
+	}
+
+	free(data);
+	return system_heap_id;
+}
+
 unsigned int pick_ion_heap(int usage)
 {
 	unsigned int heap_mask;
@@ -215,7 +262,6 @@
 int alloc_backend_alloc(alloc_device_t* dev, size_t size, int usage, buffer_handle_t* pHandle, uint64_t fmt, int w, int h)
 {
 	private_module_t* m = reinterpret_cast<private_module_t*>(dev->common.module);
-	ion_user_handle_t ion_hnd;
 	unsigned char *cpu_ptr = NULL;
 	int shared_fd;
 	int ret;
@@ -225,36 +271,52 @@
 	int lock_state = 0;
 	int min_pgsz = 0;
 
-	heap_mask = pick_ion_heap(usage);
-	if(heap_mask == 0)
+	if (m->gralloc_legacy_ion)
 	{
-		AERR("Failed to find an appropriate ion heap");
-		return -1;
-	}
-	set_ion_flags(heap_mask, usage, &priv_heap_flag, &ion_flags);
+		ion_user_handle_t ion_hnd;
 
-	ion_hnd = alloc_from_ion_heap(m->ion_client, size, heap_mask, ion_flags, &min_pgsz);
-	if (ion_hnd < 0)
+		heap_mask = pick_ion_heap(usage);
+		if(heap_mask == 0)
+		{
+			AERR("Failed to find an appropriate ion heap");
+			return -1;
+		}
+		set_ion_flags(heap_mask, usage, &priv_heap_flag, &ion_flags);
+
+		ion_hnd = alloc_from_ion_heap(m->ion_client, size, heap_mask, ion_flags, &min_pgsz);
+		if (ion_hnd < 0)
+		{
+			AERR("Failed to ion_alloc from ion_client:%d", m->ion_client);
+			return -1;
+		}
+
+		ret = ion_share( m->ion_client, ion_hnd, &shared_fd );
+		if ( ret != 0 )
+		{
+			AERR( "ion_share( %d ) failed", m->ion_client );
+			if ( 0 != ion_free( m->ion_client, ion_hnd ) ) AERR( "ion_free( %d ) failed", m->ion_client );
+			return -1;
+		}
+
+		// we do not need ion_hnd once we have shared_fd
+		if (0 != ion_free(m->ion_client, ion_hnd))
+		{
+		    AWAR("ion_free( %d ) failed", m->ion_client);
+		}
+		ion_hnd = -1;
+	}
+	else
 	{
-		AERR("Failed to ion_alloc from ion_client:%d", m->ion_client);
-		return -1;
+		/* Support only System heap to begin with */
+		ret = ion_alloc_fd(m->ion_client, size, 0, 1 << m->system_heap_id, 0, &(shared_fd));
+		if (ret != 0)
+		{
+			AERR("Failed to ion_alloc_fd from ion_client:%d", m->ion_client);
+			return -1;
+		}
+		min_pgsz = SZ_4K;
 	}
 
-	ret = ion_share( m->ion_client, ion_hnd, &shared_fd );
-	if ( ret != 0 )
-	{
-		AERR( "ion_share( %d ) failed", m->ion_client );
-		if ( 0 != ion_free( m->ion_client, ion_hnd ) ) AERR( "ion_free( %d ) failed", m->ion_client );		
-		return -1;
-	}
-
-        // we do not need ion_hnd once we have shared_fd
-        if (0 != ion_free(m->ion_client, ion_hnd))
-        {
-            AWAR("ion_free( %d ) failed", m->ion_client);
-        }
-        ion_hnd = -1;
-
 	if (!(usage & GRALLOC_USAGE_PROTECTED))
 	{
 		cpu_ptr = (unsigned char*)mmap( NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, shared_fd, 0 );
@@ -352,6 +414,20 @@
 		return -1;
 	}
 
+	m->gralloc_legacy_ion = ion_is_legacy(m->ion_client);
+
+	if (!m->gralloc_legacy_ion)
+	{
+		m->system_heap_id = find_system_heap_id(m->ion_client);
+		if (m->system_heap_id < 0)
+		{
+			ion_close(m->ion_client);
+			m->ion_client = -1;
+			AERR( "ion_open failed: no system heap found" );
+			return -1;
+		}
+	}
+
 	return 0;
 }
 
diff --git a/gralloc960/gralloc_module_ion.cpp b/gralloc960/gralloc_module_ion.cpp
index d91902c..9d3c4c8 100644
--- a/gralloc960/gralloc_module_ion.cpp
+++ b/gralloc960/gralloc_module_ion.cpp
@@ -27,6 +27,7 @@
 #include "gralloc_priv.h"
 #include "alloc_device.h"
 #include "framebuffer_device.h"
+#include "ion_4.12.h"
 
 #include <linux/ion.h>
 #include <ion/ion.h>
@@ -110,13 +111,15 @@
 	{
 	case private_handle_t::PRIV_FLAGS_USES_ION:
 		hw_module_t * pmodule = NULL;
-		private_module_t *m=NULL;
 		if (hw_get_module(GRALLOC_HARDWARE_MODULE_ID, (const hw_module_t **)&pmodule) == 0)
 		{
-			if(!(hnd->flags & private_handle_t::PRIV_FLAGS_USES_ION_DMA_HEAP))
+			private_module_t *m = reinterpret_cast<private_module_t *>(pmodule);
+			if (m->gralloc_legacy_ion)
 			{
-				m = reinterpret_cast<private_module_t *>(pmodule);
-				ion_sync_fd(m->ion_client, hnd->share_fd);
+				if(!(hnd->flags & private_handle_t::PRIV_FLAGS_USES_ION_DMA_HEAP))
+				{
+					ion_sync_fd(m->ion_client, hnd->share_fd);
+				}
 			}
 		}
 		else
diff --git a/gralloc960/gralloc_priv.h b/gralloc960/gralloc_priv.h
index 55feb67..606b365 100644
--- a/gralloc960/gralloc_priv.h
+++ b/gralloc960/gralloc_priv.h
@@ -94,6 +94,8 @@
 	pthread_mutex_t lock;
 	buffer_handle_t currentBuffer;
 	int ion_client;
+	int system_heap_id;
+	bool gralloc_legacy_ion;
 	mali_dpy_type dpy_type;
 
 	struct fb_var_screeninfo info;