hwc: added support for ext display back buffer allocation

When the ext display transform is different from the FB,
the mirroring/cloning is achived with the help of back-buffers,
which are allocated in TILER2D space to get the required
transformation. This patch adds support in HWC to detect
the ext display transform and allocate back buffers from
TILER2D space and program dsscomp accordingly.

Signed-off-by: Sunita Nadampalli <sunitan@ti.com>

hwc: make file fix for local include path

the local include path for ion is changed from base level
to local. this is required to allow compiling at hwc level.

Change-Id: Ie1e9e6688652fdc8aa496dfc367d385aca362a27
Signed-off-by: Sunita Nadampalli <sunitan@ti.com>
(cherry picked from commit 5d7b83b7ee03be090076d9aefd40dac294377aac)

Conflicts:

	hwc/hwc.c
diff --git a/hwc/Android.mk b/hwc/Android.mk
index b31fb61..81ad059 100644
--- a/hwc/Android.mk
+++ b/hwc/Android.mk
@@ -7,7 +7,8 @@
 LOCAL_PRELINK_MODULE := false
 LOCAL_ARM_MODE := arm
 LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/../vendor/lib/hw
-LOCAL_SHARED_LIBRARIES := liblog libEGL libcutils libutils libhardware libhardware_legacy libz
+LOCAL_SHARED_LIBRARIES := liblog libEGL libcutils libutils libhardware libhardware_legacy libz \
+                          libion_ti
 LOCAL_SRC_FILES := hwc.c rgz_2d.c
 LOCAL_STATIC_LIBRARIES := libpng
 
diff --git a/hwc/hwc.c b/hwc/hwc.c
index cdbc8e2..174c18b 100644
--- a/hwc/hwc.c
+++ b/hwc/hwc.c
@@ -60,9 +60,13 @@
 #include "hal_public.h"
 #include "rgz_2d.h"
 
+#include <linux/ion.h>
+#include <linux/omap_ion.h>
+#include <ion/ion.h>
+
 #define MAX_HW_OVERLAYS 4
 #define NUM_NONSCALING_OVERLAYS 1
-#define MAX_TILER_SLOT (32 << 20)
+#define NUM_EXT_DISPLAY_BACK_BUFFERS 2
 
 struct ext_transform_t {
     __u8 rotation : 3;          /* 90-degree clockwise rotations */
@@ -199,6 +203,8 @@
     struct omap_hwc_data comp_data; /* This is a kernel data structure */
     struct rgz_blt_entry blit_ops[RGZ_MAX_BLITS];
     struct counts stats;
+    int    ion_fd;
+    struct ion_handle *ion_handles[2];
 
     /* fake vsync event state */
     pthread_mutex_t vsync_lock;
@@ -1336,8 +1342,21 @@
     /* reserve overlays at end for other display */
     o->cfg.ix = MAX_HW_OVERLAYS - 1 - ext_ovl_ix;
     o->cfg.mgr_ix = 1;
-    o->addressing = OMAP_DSS_BUFADDR_OVL_IX;
-    o->ba = ix;
+    /*
+    * Here the assumption is that overlay0 is the one attached to FB.
+    * Hence this clone_layer call is for FB cloning (provided use_sgx is true).
+    */
+    /* For the external displays whose transform is the same as
+    * that of primary display, ion_handles would be NULL hence
+    * the below logic doesn't execute.
+    */
+    if (ix == 0 && hwc_dev->ion_handles[sync_id%2] && hwc_dev->use_sgx) {
+        o->addressing = OMAP_DSS_BUFADDR_ION;
+        o->ba = (int)hwc_dev->ion_handles[sync_id%2];
+    } else {
+        o->addressing = OMAP_DSS_BUFADDR_OVL_IX;
+        o->ba = ix;
+    }
 
     /* use distinct z values (to simplify z-order checking) */
     o->cfg.zorder += hwc_dev->post2_layers;
@@ -1567,6 +1586,47 @@
     }
 }
 
+static int free_tiler2d_buffers(omap4_hwc_device_t *hwc_dev)
+{
+    int i;
+
+    for (i = 0 ; i < NUM_EXT_DISPLAY_BACK_BUFFERS; i++) {
+        ion_free(hwc_dev->ion_fd, hwc_dev->ion_handles[i]);
+        hwc_dev->ion_handles[i] = NULL;
+    }
+    return 0;
+}
+
+static int allocate_tiler2d_buffers(omap4_hwc_device_t *hwc_dev)
+{
+    int ret, i;
+    size_t stride;
+
+    if (hwc_dev->ion_fd < 0) {
+        ALOGE("No ion fd, hence can't allocate tiler2d buffers");
+        return -1;
+    }
+
+    for (i = 0; i < NUM_EXT_DISPLAY_BACK_BUFFERS; i++) {
+        if (hwc_dev->ion_handles[i])
+            return 0;
+    }
+
+    for (i = 0 ; i < NUM_EXT_DISPLAY_BACK_BUFFERS; i++) {
+        ret = ion_alloc_tiler(hwc_dev->ion_fd, hwc_dev->fb_dev->base.width, hwc_dev->fb_dev->base.height,
+                                            TILER_PIXEL_FMT_32BIT, 0, &hwc_dev->ion_handles[i], &stride);
+        if (ret)
+            goto handle_error;
+
+        ALOGI("ion handle[%d][%p]", i, hwc_dev->ion_handles[i]);
+    }
+    return 0;
+
+handle_error:
+    free_tiler2d_buffers(hwc_dev);
+    return -1;
+}
+
 static int omap4_hwc_prepare(struct hwc_composer_device_1 *dev, size_t numDisplays,
         hwc_display_contents_1_t** displays)
 {
@@ -2151,6 +2211,9 @@
             close(hwc_dev->hdmi_fb_fd);
         if (hwc_dev->fb_fd >= 0)
             close(hwc_dev->fb_fd);
+        if (hwc_dev->ion_fd >= 0)
+            ion_close(hwc_dev->ion_fd);
+
         /* pthread will get killed when parent process exits */
         pthread_mutex_destroy(&hwc_dev->lock);
         pthread_mutex_destroy(&hwc_dev->vsync_lock);
@@ -2291,8 +2354,19 @@
             } else
                 ext->mirror.enabled = 0;
         }
+        /* Allocate backup buffers for FB rotation
+        * This is required only if the FB tranform is different from that
+        * of the external display and the FB is not in TILER2D space
+        */
+        if (ext->mirror.rotation && (limits.fbmem_type != DSSCOMP_FBMEM_TILER2D))
+            allocate_tiler2d_buffers(hwc_dev);
+
     } else {
         ext->last_mode = 0;
+        if (ext->mirror.rotation && (limits.fbmem_type != DSSCOMP_FBMEM_TILER2D)) {
+            /* free tiler 2D buffer on detach */
+            free_tiler2d_buffers(hwc_dev);
+        }
     }
     ALOGI("external display changed (state=%d, mirror={%s tform=%ddeg%s}, dock={%s tform=%ddeg%s%s}, tv=%d", state,
          ext->mirror.enabled ? "enabled" : "disabled",
@@ -2676,6 +2750,16 @@
         goto done;
     }
 
+    hwc_dev->ion_fd = ion_open();
+    if (hwc_dev->ion_fd < 0) {
+        ALOGE("failed to open ion driver (%d)", errno);
+    }
+
+    int i;
+    for (i = 0; i < NUM_EXT_DISPLAY_BACK_BUFFERS; i++) {
+        hwc_dev->ion_handles[i] = NULL;
+    }
+
     /* use default value in case some of requested display parameters missing */
     hwc_dev->ext.lcd_xpy = 1.0;
     if (hwc_dev->fb_dis.timings.x_res && hwc_dev->fb_dis.height_in_mm) {