diff --git a/Android.mk b/Android.mk
new file mode 100644
index 0000000..0360739
--- /dev/null
+++ b/Android.mk
@@ -0,0 +1 @@
+# Empty Android.mk
diff --git a/libcopybit/Android.mk b/libcopybit/Android.mk
new file mode 100644
index 0000000..9e425e0
--- /dev/null
+++ b/libcopybit/Android.mk
@@ -0,0 +1,73 @@
+# Copyright (C) 2008 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+
+LOCAL_PATH:= $(call my-dir)
+# HAL module implemenation, not prelinked and stored in
+# hw/<COPYPIX_HARDWARE_MODULE_ID>.<ro.board.platform>.so
+
+ifeq ($(TARGET_USES_C2D_COMPOSITION),true)
+    include $(CLEAR_VARS)
+    LOCAL_PRELINK_MODULE := false
+    LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw
+    LOCAL_SHARED_LIBRARIES := liblog libdl
+    LOCAL_SRC_FILES := copybit_c2d.cpp
+    LOCAL_MODULE := copybit.$(TARGET_BOARD_PLATFORM)
+    LOCAL_C_INCLUDES += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr/include
+    LOCAL_ADDITIONAL_DEPENDENCIES += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr
+    LOCAL_C_INCLUDES += hardware/msm7k/libgralloc-qsd8k
+    LOCAL_CFLAGS += -DCOPYBIT_Z180=1 -DC2D_SUPPORT_DISPLAY=1
+    include $(BUILD_SHARED_LIBRARY)
+else
+    ifneq "$(findstring msm7630,$(TARGET_PRODUCT))" "msm7630"
+        ifeq ($(TARGET_BOARD_PLATFORM),msm7k)
+            include $(CLEAR_VARS)
+            ifeq ($(TARGET_GRALLOC_USES_ASHMEM),true)
+                LOCAL_CFLAGS += -DUSE_ASHMEM
+                ifeq "$(findstring msm7627,$(TARGET_PRODUCT))" "msm7627"
+                   LOCAL_CFLAGS += -DTARGET_7x27
+                endif
+            endif
+
+            LOCAL_PRELINK_MODULE := false
+            LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw
+            LOCAL_SHARED_LIBRARIES := liblog
+            LOCAL_SRC_FILES := copybit.cpp
+            LOCAL_MODULE := copybit.msm7k
+            LOCAL_C_INCLUDES += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr/include
+            LOCAL_ADDITIONAL_DEPENDENCIES += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr
+            LOCAL_C_INCLUDES += hardware/msm7k/libgralloc-qsd8k
+            LOCAL_CFLAGS += -DCOPYBIT_MSM7K=1
+            include $(BUILD_SHARED_LIBRARY)
+        endif
+
+        ifeq ($(TARGET_BOARD_PLATFORM),qsd8k)
+            include $(CLEAR_VARS)
+            ifeq ($(TARGET_GRALLOC_USES_ASHMEM),true)
+                LOCAL_CFLAGS += -DUSE_ASHMEM
+            endif
+
+            LOCAL_PRELINK_MODULE := false
+            LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw
+            LOCAL_SHARED_LIBRARIES := liblog
+            LOCAL_SRC_FILES := copybit.cpp
+            LOCAL_MODULE := copybit.qsd8k
+            LOCAL_C_INCLUDES += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr/include
+            LOCAL_ADDITIONAL_DEPENDENCIES += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr
+            LOCAL_C_INCLUDES += hardware/msm7k/libgralloc-qsd8k
+            LOCAL_CFLAGS += -DCOPYBIT_QSD8K=1
+            include $(BUILD_SHARED_LIBRARY)
+        endif
+    endif
+endif
diff --git a/libcopybit/MODULE_LICENSE_APACHE2 b/libcopybit/MODULE_LICENSE_APACHE2
new file mode 100644
index 0000000..e69de29
diff --git a/libcopybit/NOTICE b/libcopybit/NOTICE
new file mode 100644
index 0000000..7340b9e
--- /dev/null
+++ b/libcopybit/NOTICE
@@ -0,0 +1,190 @@
+
+   Copyright (c) 2008, The Android Open Source Project
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
diff --git a/libcopybit/c2d2.h b/libcopybit/c2d2.h
new file mode 100644
index 0000000..10c94be
--- /dev/null
+++ b/libcopybit/c2d2.h
@@ -0,0 +1,618 @@
+/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ *       copyright notice, this list of conditions and the following
+ *       disclaimer in the documentation and/or other materials provided
+ *       with the distribution.
+ *     * Neither the name of Code Aurora Forum, Inc. nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+#ifndef __c2d2_h_
+#define __c2d2_h_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <EGL/egl.h> /* for EGL surfaces */
+
+#ifndef C2D_API
+#define C2D_API /* define API export as needed */
+#endif
+#ifndef int32
+typedef int                     int32;
+#endif
+#ifndef uint32
+typedef unsigned int            uint32;
+#endif
+
+/*****************************************************************************/
+/*********************** Blit definitions *****************************/
+/*****************************************************************************/
+
+/* Status codes, returned by any blit function */
+typedef enum {
+    C2D_STATUS_OK              = 0,
+    C2D_STATUS_NOT_SUPPORTED   = 1,
+    C2D_STATUS_OUT_OF_MEMORY   = 2,
+    C2D_STATUS_INVALID_PARAM   = 3,
+    C2D_STATUS_SURFACE_IN_USE  = 4,
+} C2D_STATUS;
+
+
+/* Definitions of color format modes, used together with color formats */
+typedef enum {
+    C2D_FORMAT_PACK_INTO_32BIT   = (1 <<  8), /* pack into dword if set */
+    C2D_FORMAT_SWAP_ENDIANNESS   = (1 <<  9), /* swaps the order */
+    C2D_FORMAT_LINEAR_SPACE      = (1 << 10), /* linear color space */
+    C2D_FORMAT_PREMULTIPLIED     = (1 << 11), /* alpha premultiplied */
+    C2D_FORMAT_INVERT_ALPHA      = (1 << 12), /* inverts alpha */
+    C2D_FORMAT_DISABLE_ALPHA     = (1 << 13), /* disables alpha */
+    C2D_FORMAT_INTERLACED        = (1 << 14), /* YUV line-interlaced */
+    C2D_FORMAT_TRANSPARENT       = (1 << 15), /* YUV 1-bit alpha in Y */
+    C2D_FORMAT_MACROTILED        = (1 << 16), /* tiled in macro level */
+    C2D_FORMAT_TILED_4x4         = (1 << 17), /* 4x4 tiled format */
+    C2D_FORMAT_SWAP_RB           = (1 << 18), /* Swap R & B color components */
+} C2D_FORMAT_MODE;
+
+/* Definitions of supported RGB formats, used in C2D_RGB_SURFACE_DEF.
+ * The bits of each color channel are packed into a machine word
+ * representing a single pixel from left to right (MSB to LSB) in the
+ * order indicated by format name. For the sub-byte formats the pixels
+ * are packed into bytes from left to right (MSbit to LSBit).
+ * If the C2D_FORMAT_PACK_INTO_32BIT bit is set, the minimal
+ * machine word used for pixel storage is 32-bit and the whole word
+ * is reversed if endianness is swapped.
+ * If the C2D_FORMAT_SWAP_ENDIANNESS bit is set, the order within a
+ * minimal machine word representing a pixel
+ * is reversed for both sub-byte and multi-byte formats.
+ * If the C2D_FORMAT_LINEAR_SPACE bit is set, the color space of
+ * the formats below is considered linear, if applicable.
+ * If the C2D_FORMAT_PREMULTIPLIED bit is set, the color channels
+ * are premultiplied with the alpha, if applicable.
+ * If the C2D_FORMAT_INVERT_ALPHA bit is set, the alpha interpretation
+ * is inverted: 0 - opaque, 1 - transparent, if applicable.
+ * If the C2D_FORMAT_DISABLE_ALPHA bit is set, the alpha channel serves
+ * as a placeholder and is ignored during blit, if applicable.
+ * If the COMP_FORMAT_MACROTILED bit is set, the surface is in the
+ * tiled format : 64x32 for 8bpp, 32x32 for 16bpp formats  */
+typedef enum {
+    C2D_COLOR_FORMAT_1            = 0,   /* 1-bit alpha/color expansion */
+
+    C2D_COLOR_FORMAT_2_PALETTE    = 1,   /* 2-bit indices for palette */
+    C2D_COLOR_FORMAT_4_PALETTE    = 2,   /* 4-bit indices for palette */
+    C2D_COLOR_FORMAT_8_PALETTE    = 3,   /* 8-bit indices for palette */
+
+    C2D_COLOR_FORMAT_2_L          = 4,   /* 2-bit grayscale */
+    C2D_COLOR_FORMAT_4_L          = 5,   /* 4-bit grayscale */
+    C2D_COLOR_FORMAT_8_L          = 6,   /* 8-bit grayscale */
+
+    C2D_COLOR_FORMAT_2_A          = 7,   /* 2-bit alpha only */
+    C2D_COLOR_FORMAT_4_A          = 8,   /* 4-bit alpha only */
+    C2D_COLOR_FORMAT_8_A          = 9,   /* 8-bit alpha only */
+
+    C2D_COLOR_FORMAT_444_RGB      = 10,  /* 12-bit colors */
+    C2D_COLOR_FORMAT_565_RGB      = 11,  /* 16-bit colors */
+    C2D_COLOR_FORMAT_888_RGB      = 12,  /* 24-bit colors */
+
+    C2D_COLOR_FORMAT_1555_ARGB    = 13,  /* 16-bit colors (1-bit alpha) */
+    C2D_COLOR_FORMAT_4444_ARGB    = 14,  /* 16-bit colors (4-bit alpha) */
+    C2D_COLOR_FORMAT_8565_ARGB    = 15,  /* 24-bit colors (8-bit alpha) */
+    C2D_COLOR_FORMAT_8888_ARGB    = 16,  /* 32-bit colors (8-bit alpha) */
+
+    C2D_COLOR_FORMAT_5551_RGBA    = 17,  /* 16-bit colors (1-bit alpha) */
+    C2D_COLOR_FORMAT_4444_RGBA    = 18,  /* 16-bit colors (4-bit alpha) */
+    C2D_COLOR_FORMAT_5658_RGBA    = 19,  /* 24-bit colors (8-bit alpha) */
+    C2D_COLOR_FORMAT_8888_RGBA    = 20,  /* 32-bit colors (8-bit alpha) */
+
+    /* derived RGB color formats (base format + mode bits) */
+
+} C2D_RGB_FORMAT;
+
+/* Definitions of supported YUV formats, used in C2D_YUV_SURFACE_DEF.
+ * Each of Y,U,V channels usually takes 1 byte and therefore is
+ * individually addressable. The definitions below show how Y,U,V
+ * channels are packed into macropixels for each particular format.
+ * The order is from left (smaller byte addresses) to right (larger
+ * byte addresses). The first three digits (4xx) denote the chroma
+ * subsampling in standard YUV notation. The digits in the macropixel
+ * denote that the whole block (from the previous digit or from the
+ * beginning) has to be repeated the number of times. Underscores
+ * between Y,U,V channels are used to describe separate planes for
+ * planar YUV formats. Formats are mapped to numbers so that future
+ * versions with various YUV permutations are easy to add.
+ * If the C2D_FORMAT_INTERLACED bit is set, the line order is
+ * interlaced: 0,2,4,...1,3,5... if applicable.
+ * If the C2D_FORMAT_TRANSPARENT bit is set, the least significant
+ * bit of Y channel serves as alpha: 0 - transparent, 1 - opaque. */
+typedef enum {
+    C2D_COLOR_FORMAT_411_YYUYYV   = 110, /* packed, 12-bit         */
+    C2D_COLOR_FORMAT_411_YUYYVY   = 111, /* packed, 12-bit         */
+    C2D_COLOR_FORMAT_411_UYYVYY   = 112, /* packed, 12-bit, "Y411" */
+    C2D_COLOR_FORMAT_411_YUYV2Y4  = 116, /* packed, 12-bit         */
+    C2D_COLOR_FORMAT_411_UYVY2Y4  = 117, /* packed, 12-bit, "Y41P" */
+
+    C2D_COLOR_FORMAT_422_YUYV     = 120, /* packed, 16-bit, "YUY2" */
+    C2D_COLOR_FORMAT_422_UYVY     = 121, /* packed, 16-bit, "UYVY" */
+    C2D_COLOR_FORMAT_422_YVYU     = 122, /* packed, 16-bit, "YVYU" */
+    C2D_COLOR_FORMAT_422_VYUY     = 123, /* packed, 16-bit         */
+
+    C2D_COLOR_FORMAT_444_YUV      = 130, /* packed, 24-bit         */
+    C2D_COLOR_FORMAT_444_UYV      = 131, /* packed, 24-bit, "IYU2" */
+    C2D_COLOR_FORMAT_444_AYUV     = 136, /* packed, 24-bit, "AYUV" */
+
+    C2D_COLOR_FORMAT_410_Y_UV     = 150, /* planar, Y + interleaved UV */
+    C2D_COLOR_FORMAT_411_Y_UV     = 151, /* planar, Y + interleaved UV */
+    C2D_COLOR_FORMAT_420_Y_UV     = 152, /* planar, Y + interleaved UV */
+    C2D_COLOR_FORMAT_422_Y_UV     = 153, /* planar, Y + interleaved UV */
+    C2D_COLOR_FORMAT_444_Y_UV     = 154, /* planar, Y + interleaved UV */
+
+    C2D_COLOR_FORMAT_410_Y_VU     = 160, /* planar, Y + interleaved VU */
+    C2D_COLOR_FORMAT_411_Y_VU     = 161, /* planar, Y + interleaved VU */
+    C2D_COLOR_FORMAT_420_Y_VU     = 162, /* planar, Y + interleaved VU */
+    C2D_COLOR_FORMAT_422_Y_VU     = 163, /* planar, Y + interleaved VU */
+    C2D_COLOR_FORMAT_444_Y_VU     = 164, /* planar, Y + interleaved VU */
+
+    C2D_COLOR_FORMAT_410_Y_U_V    = 170, /* planar, Y + U + V separate */
+    C2D_COLOR_FORMAT_411_Y_U_V    = 171, /* planar, Y + U + V separate */
+    C2D_COLOR_FORMAT_420_Y_V_U    = 172, /* planar, Y + V + U separate */
+    C2D_COLOR_FORMAT_420_Y_U_V    = 173, /* planar, Y + U + V separate */
+    C2D_COLOR_FORMAT_422_Y_U_V    = 174, /* planar, Y + U + V separate */
+    C2D_COLOR_FORMAT_444_Y_U_V    = 175, /* planar, Y + U + V separate */
+
+    C2D_COLOR_FORMAT_800_Y        = 190, /* planar, Y only, grayscale */
+
+    /* derived YUV color formats (base format + mode bits), FOURCC */
+
+    C2D_COLOR_FORMAT_411_Y411     = 112,
+    C2D_COLOR_FORMAT_411_Y41P     = 117,
+    C2D_COLOR_FORMAT_411_IY41     = 117 | (1 << 14),
+    C2D_COLOR_FORMAT_411_Y41T     = 117 | (1 << 15),
+
+    C2D_COLOR_FORMAT_422_YUY2     = 120,
+    C2D_COLOR_FORMAT_422_IUYV     = 121 | (1 << 14),
+    C2D_COLOR_FORMAT_422_Y42T     = 121 | (1 << 15),
+    C2D_COLOR_FORMAT_444_IYU2     = 131,
+
+    C2D_COLOR_FORMAT_420_NV12     = 152,
+    C2D_COLOR_FORMAT_420_NV21     = 162,
+
+    C2D_COLOR_FORMAT_410_YUV9     = 170,
+    C2D_COLOR_FORMAT_410_YVU9     = 170,
+    C2D_COLOR_FORMAT_411_Y41B     = 171,
+    C2D_COLOR_FORMAT_420_YV12     = 172,
+    C2D_COLOR_FORMAT_420_IYUV     = 173,
+    C2D_COLOR_FORMAT_420_I420     = 173,
+    C2D_COLOR_FORMAT_422_YV16     = 174,
+    C2D_COLOR_FORMAT_422_Y42B     = 174,
+
+    C2D_COLOR_FORMAT_800_Y800     = 190,
+
+} C2D_YUV_FORMAT;
+
+
+/* Configuration bits, used in the config_mask field of C2D_OBJECT struct */
+typedef enum {
+    C2D_SOURCE_RECT_BIT      = (1 <<  0), /* enables source_rect field */
+    C2D_MIRROR_H_BIT         = (1 <<  1), /* enables horizontal flipping */
+    C2D_MIRROR_V_BIT         = (1 <<  2), /* enables vertical flipping */
+    C2D_SOURCE_TILE_BIT      = (1 <<  3), /* enables source surface tiling */
+    C2D_TARGET_RECT_BIT      = (1 <<  4), /* enables target_rect field */
+    C2D_ROTATE_BIT           = (1 <<  5), /* enables all rotation fields */
+    C2D_SCISSOR_RECT_BIT     = (1 <<  6), /* enables scissor_rect field */
+    C2D_MASK_SURFACE_BIT     = (1 <<  7), /* enables mask_surface_id field */
+    C2D_MASK_ALIGN_BIT       = (1 <<  8), /* aligns mask to source_rect */
+    C2D_MASK_SCALE_BIT       = (1 <<  9), /* enables mask surface scaling */
+    C2D_MASK_TILE_BIT        = (1 << 10), /* enables mask surface tiling */
+    C2D_GLOBAL_ALPHA_BIT     = (1 << 11), /* enables global_alpha field */
+    C2D_COLOR_KEY_BIT        = (1 << 12), /* enables color_key field */
+    C2D_NO_PIXEL_ALPHA_BIT   = (1 << 13), /* disables source alpha channel */
+    C2D_NO_BILINEAR_BIT      = (1 << 14), /* disables bilinear on scaling */
+    C2D_NO_ANTIALIASING_BIT  = (1 << 15), /* disables antialiasing on edges */
+    C2D_DRAW_LINE_BIT        = (1 << 16), /* enables line drawing with source rectangle */
+    C2D_DRAW_LINE_NOLAST     = (1 << 17), /* disable last pixel draw for line */
+} C2D_SOURCE_CONFIG;
+
+/* Target configuration bits, defines rotation + mirroring.
+ * Mirror is applied prior to rotation if enabled. */
+typedef enum {
+    C2D_TARGET_MIRROR_H        = (1 << 0), /* horizontal flip */
+    C2D_TARGET_MIRROR_V        = (1 << 1), /* vertical flip */
+    C2D_TARGET_ROTATE_0        = (0 << 2), /* no rotation */
+    C2D_TARGET_ROTATE_90       = (1 << 2), /* 90 degree rotation */
+    C2D_TARGET_ROTATE_180      = (2 << 2), /* 180 degree rotation */
+    C2D_TARGET_ROTATE_270      = (3 << 2), /* 270 degree rotation, 90 + 180 */
+    C2D_TARGET_MASK_ALIGN      = (1 << 4), /* aligns mask to target scissor */
+    C2D_TARGET_MASK_SCALE      = (1 << 5), /* enables mask scaling */
+    C2D_TARGET_MASK_TILE       = (1 << 6), /* enables mask tiling */
+    C2D_TARGET_COLOR_KEY       = (1 << 7), /* enables target_color_key */
+    C2D_TARGET_NO_PIXEL_ALPHA  = (1 << 8), /* disables target alpha channel */
+} C2D_TARGET_CONFIG;
+
+#define C2D_TARGET_ROTATION_MASK  (C2D_TARGET_ROTATE_90*3)
+
+/* Additional blend modes, can be used with both source and target configs.
+   If none of the below is set, the default "SRC over DST" is applied. */
+typedef enum {
+    C2D_ALPHA_BLEND_SRC_OVER   = (0  << 20), /* Default, Porter-Duff "SRC over DST" */
+    C2D_ALPHA_BLEND_SRC        = (1  << 20), /* Porter-Duff "SRC" */
+    C2D_ALPHA_BLEND_SRC_IN     = (2  << 20), /* Porter-Duff "SRC in DST" */
+    C2D_ALPHA_BLEND_DST_IN     = (3  << 20), /* Porter-Duff "DST in SRC" */
+    C2D_ALPHA_BLEND_SRC_OUT    = (4  << 20), /* Porter-Duff "SRC out DST" */
+    C2D_ALPHA_BLEND_DST_OUT    = (5  << 20), /* Porter-Duff "DST out SRC" */
+    C2D_ALPHA_BLEND_DST_OVER   = (6  << 20), /* Porter-Duff "DST over SRC" */
+    C2D_ALPHA_BLEND_SRC_ATOP   = (7  << 20), /* Porter-Duff "SRC ATOP" */
+    C2D_ALPHA_BLEND_DST_ATOP   = (8  << 20), /* Porter-Duff "DST ATOP" */
+    C2D_ALPHA_BLEND_XOR        = (9  << 20), /* Xor */
+    C2D_ALPHA_BLEND_MULTIPLY   = (10 << 20), /* OpenVG "MULTIPLY" */
+    C2D_ALPHA_BLEND_SCREEN     = (11 << 20), /* OpenVG "SCREEN" */
+    C2D_ALPHA_BLEND_DARKEN     = (12 << 20), /* OpenVG "DARKEN" */
+    C2D_ALPHA_BLEND_LIGHTEN    = (13 << 20), /* OpenVG "LIGHTEN" */
+    C2D_ALPHA_BLEND_ADDITIVE   = (14 << 20), /* OpenVG "ADDITIVE" */
+    C2D_ALPHA_BLEND_DIRECT     = (15 << 20), /* Direct alpha blitting */
+    C2D_ALPHA_BLEND_INVERTC    = (16 << 20), /* Invert color */
+    C2D_ALPHA_BLEND_NONE       = (1  << 25), /* disables alpha blending */
+} C2D_ALPHA_BLEND_MODE;
+
+
+/* Surface caps enumeration */
+typedef enum {
+    C2D_SOURCE          = (1 << 0), /* allows to use as a source */
+    C2D_TARGET          = (1 << 1), /* allows to use as a target */
+    C2D_MASK            = (1 << 2), /* allows to use as a mask */
+    C2D_PALETTE         = (1 << 3), /* allows to use as a palette */
+} C2D_SURFACE_BITS;
+
+/* Surface type enumeration */
+typedef enum {
+    C2D_SURFACE_EGL          = 0, /* Arbitrary EGL surface */
+    C2D_SURFACE_RGB_HOST     = 1, /* Host memory RGB surface */
+    C2D_SURFACE_RGB_EXT      = 2, /* External memory RGB surface */
+    C2D_SURFACE_YUV_HOST     = 3, /* Host memory YUV surface */
+    C2D_SURFACE_YUV_EXT      = 4, /* External memory YUV surface */
+    C2D_SURFACE_WITH_PHYS    = (1<<3), /* physical address allready mapped */
+                                        /* this bit is valid with HOST types */
+} C2D_SURFACE_TYPE;
+
+/* Structure for registering an EGL surface as a blit surface */
+typedef struct {
+    EGLDisplay display; /* EGL display */
+    EGLContext context; /* EGL context, reserved - pass EGL_NO_CONTEXT */
+    EGLSurface surface; /* EGL surface */
+} C2D_EGL_SURFACE_DEF;
+
+/* Structure for registering a RGB buffer as a blit surface */
+typedef struct {
+    uint32 format;   /* RGB color format plus additional mode bits */
+    uint32 width;    /* defines width in pixels */
+    uint32 height;   /* defines height in pixels */
+    void  *buffer;   /* pointer to the RGB buffer */
+    void  *phys;     /* physical address */
+    int32  stride;   /* defines stride in bytes, negative stride is allowed */
+} C2D_RGB_SURFACE_DEF;
+
+/* Structure for registering a YUV plane(s) as a blit surface */
+typedef struct {
+    uint32 format;   /* YUV color format plus additional mode bits */
+    uint32 width;    /* defines width in pixels */
+    uint32 height;   /* defines height in pixels */
+    void  *plane0;  /* holds the whole buffer if YUV format is not planar */
+    void  *phys0;   /* physical address */
+    int32  stride0; /* stride in bytes if YUV format is not planar */
+    void  *plane1;  /* holds UV or VU plane for planar interleaved */
+    void  *phys1;   /* physical address */
+    int32  stride1; /* stride for UV or VU plane for planar interleaved */
+    void  *plane2;  /* holds the 3. plane, ignored if YUV format is not planar */
+    void  *phys2;    /* physical address */
+    int32  stride2; /* stride for the 3. plane, ignored if YUV format is not planar */
+} C2D_YUV_SURFACE_DEF;
+
+
+/* Rectangle definition */
+typedef struct {
+    int32 x;        /* upper-left x */
+    int32 y;        /* upper-left y */
+    int32 width;    /* width */
+    int32 height;   /* height */
+} C2D_RECT;
+
+/* C2D_OBJECT encapsulates the blit parameters for a source surface.
+ * The fg_color defines color in target format for bits equal to 1
+ * in the source C2D_COLOR_FORMAT_1 format. It also defines rendering
+ * color for all alpha-only source formats. If the surface_id is 0
+ * the fg_color defines a constant fill color used instead of the surface.
+ * The bg_color defines color in target format for bits equal to 0
+ * in the source C2D_COLOR_FORMAT_1 format, otherwise both are ignored.
+ * The palette_id is used for all palette source formats, otherwise ignored.
+
+ * The source_rect first defines the content of the source surface,
+ * it is then horizontally/vertically flipped if C2D_MIRROR_*_BIT is set,
+ * then scaled with bilinear interpolation to exactly fit target_rect
+ * or repeated across target_rect if C2D_SOURCE_TILE_BIT is set,
+ * target_rect is then rotated clockwise by an arbitrary angle in degrees
+ * around the rot_orig_x/y, defined relative to target_rect's top left point,
+ * and then clipped to scissor_rect defined in target coordinate system.
+
+ * Finally alpha blending is applied before pixels get written into the target.
+ * Surface's pixel alpha is combined with mask alpha and with global alpha.
+ * Mask surface follows all transformations applied to the source surface.
+ * Source color key defines transparent color, applied together with alpha. */
+typedef struct C2D_OBJECT_STR {
+    uint32 surface_id;      /* source surface */
+
+    uint32 fg_color;        /* foreground color */
+    uint32 bg_color;        /* background color */
+    uint32 palette_id;      /* one-dimensional horizontal palette surface */
+
+    uint32 config_mask;     /* defines which fields below are enabled */
+
+    C2D_RECT source_rect;  /* region of the source surface,   16.16 fp */
+    C2D_RECT target_rect;  /* position and scaling in target, 16.16 fp */
+
+    int32 rot_orig_x;       /* rotation origin relative to target_rect's... */
+    int32 rot_orig_y;       /* ...top left point,     both are 16.16 fp */
+    int32 rotation;         /* clock-wise rotation in degrees, 16.16 fp */
+
+    C2D_RECT scissor_rect; /* defines the clip rectangle in target surface */
+
+    uint32 mask_surface_id; /* source alpha-mask surface */
+    uint32 global_alpha;    /* 0 = fully transparent, 255 = fully opaque */
+    uint32 color_key;       /* transparent color for the source surface */
+
+    struct C2D_OBJECT_STR *next; /* pointer to the next object or NULL */
+} C2D_OBJECT;
+
+
+/*****************************************************************************/
+/**************************** C2D API 2.0 ********************************/
+/*****************************************************************************/
+
+/******************************************************************************
+ * Functions to create/destroy surfaces */
+
+/* Creates a generic blit surface according to its type.
+ * Pass a combination of desired surface bits according to planned usage.
+ * Accepted values for surface_bits may include bits from C2D_SURFACE_BITS,
+ * and also from C2D_DISPLAY for compatibility with HW display controller.
+ * For host memory types the memory is preallocated outside the API
+ * and should remain valid until surface is destroyed.
+ * For external memory types the memory is allocated within API.
+ * On success, the non-zero surface identifier is returned.
+ * All numbers greater that 0 are valid surface identifiers, 0 is invalid.
+
+ * arbitrary EGL surface (including  proprietary Command List Surface):
+ * surface_type       = C2D_SURFACE_EGL
+ * surface_definition = C2D_EGL_SURFACE_DEF
+ * all fields in definition structure should be set
+ * context field is reserved and can be ignored
+
+ * Host memory RGB surface:
+ * surface_type       = C2D_SURFACE_RGB_HOST
+ * surface_definition = C2D_RGB_SURFACE_DEF
+ * all fields in definition structure should be set
+
+ * External memory RGB surface:
+ * surface_type       = C2D_SURFACE_RGB_EXT
+ * surface_definition = C2D_RGB_SURFACE_DEF
+ * buffer field in definition structure is ignored
+
+ * Host memory YUV surface:
+ * surface_type       = C2D_SURFACE_YUV_HOST
+ * surface_definition = C2D_YUV_SURFACE_DEF
+ * one or all plane and stride fields in definition structure
+ * should be set depending on whether the format is planar or not
+
+ * External memory YUV surface:
+ * surface_type       = C2D_SURFACE_YUV_EXT
+ * surface_definition = C2D_YUV_SURFACE_DEF
+ * all plane and stride fields in definition structure are ignored */
+C2D_API C2D_STATUS c2dCreateSurface( uint32 *surface_id,
+                         uint32 surface_bits,
+                         C2D_SURFACE_TYPE surface_type,
+                         void *surface_definition );
+
+/* Requests properties of the specified surface. */
+C2D_API C2D_STATUS c2dQuerySurface( uint32 surface_id,
+                         uint32 *surface_bits,
+                         C2D_SURFACE_TYPE *surface_type,
+                         uint32 *width, uint32 *height,
+                         uint32 *format );
+
+/* Destroys a generic blit surface.
+ * For external memory surfaces also deallocates the memory.
+ * It is safe to free any external resources associated with a given
+ * surface on c2dCreateSurface call after this function returns. */
+C2D_API C2D_STATUS c2dDestroySurface( uint32 surface_id );
+
+
+/******************************************************************************
+ * Functions to modify/exchange surface data */
+
+/* The format of fill_color is the same as color format being used
+ * for specified surface. If fill_rect is NULL the whole surface is filled.
+ * Alpha-blending is not performed while filling.
+ * The operation is complete when function returns. */
+C2D_API C2D_STATUS c2dFillSurface( uint32 surface_id,
+                         uint32 fill_color,
+                         C2D_RECT *fill_rect );
+
+/* Writes data located in host memory into the specified surface.
+ * The chunk of host memory is identified with surface_type and
+ * surface_definition, no surface registration needed in this case.
+ * Only C2D_SURFACE_RGB_HOST, C2D_SURFACE_YUV_HOST are accepted.
+ * If only part of the host memory buffer should be loaded, it should
+ * be configured in surface_definition using width, height and stride.
+ * The x and y are defined in target surface coordinate space.
+ * Color conversion has to be done, if color formats differ.
+ * Alpha-blending is not performed while writing.
+ * The operation is complete when function returns. */
+C2D_API C2D_STATUS c2dWriteSurface( uint32 surface_id,
+                         C2D_SURFACE_TYPE surface_type,
+                         void *surface_definition,
+                         int32 x, int32 y );
+
+/* Reads data from the specified surface into the host memory.
+ * The chunk of host memory is identified with surface_type and
+ * surface_definition, no surface registration needed in this case.
+ * Only C2D_SURFACE_RGB_HOST, C2D_SURFACE_YUV_HOST are accepted.
+ * If only part of the surface should be read, it should
+ * be configured in surface_definition using width, height and stride.
+ * The x and y are defined in source surface coordinate space.
+ * Color conversion has to be done, if color formats differ.
+ * Alpha-blending is not performed while reading.
+ * The operation is complete when function returns. */
+C2D_API C2D_STATUS c2dReadSurface( uint32 surface_id,
+                         C2D_SURFACE_TYPE surface_type,
+                         void *surface_definition,
+                         int32 x, int32 y );
+
+/* Notifies c2d imlementation that surface has been updated from outside the API,
+ * if updated_rect is NULL then the whole surface has been updated. */
+C2D_API C2D_STATUS c2dSurfaceUpdated( uint32 surface_id,
+                         C2D_RECT *updated_rect );
+
+/* Updates surface information.
+ * Could be called only for host surfaces set with parameter "C2D_SURFACE_WITH_PHYS".
+ * Count for surface planes have to be same than for already allocated surface */
+C2D_API C2D_STATUS c2dUpdateSurface( uint32 surface_id,
+                         uint32 surface_bits,
+                         C2D_SURFACE_TYPE surface_type,
+                         void *surface_definition );
+
+/******************************************************************************
+ * Functions to do actual blit */
+
+/* Draw a list of blit objects into the given target.
+ * The target_config is a bitwise OR of values from C2D_TARGET_CONFIG.
+ * The target transformation creates the effect that target surface
+ * is transformed before the blit and then transformed back
+ * after blit, however no physical target transform is performed.
+ * The objects_list is a linked list of blit objects, no more
+ * than num_objects is drawn from the given list.
+ * If num_objects is 0, the whole list is drawn.
+ * The blit is not guaranteed to complete after function returns. */
+C2D_API C2D_STATUS c2dDraw( uint32 target_id,
+                         uint32 target_config, C2D_RECT *target_scissor,
+                         uint32 target_mask_id, uint32 target_color_key,
+                         C2D_OBJECT *objects_list, uint32 num_objects );
+
+
+/* timstamp set in the blit commands flush */
+typedef void*                   c2d_ts_handle;
+
+/* Forces any pending blit to complete for a given target.
+ * Non-blocking. All input surfaces for this target except those
+ * which are shared with other targets are expected to be immediately
+ * writable after client has been waiting returned timestamp with
+ * c2dWaitTimestamp funtion or c2dFinish has been called for same target */
+C2D_API C2D_STATUS c2dFlush( uint32 target_id, c2d_ts_handle *timestamp);
+
+
+/* Waits the pending timestamp */
+C2D_API C2D_STATUS c2dWaitTimestamp( c2d_ts_handle timestamp );
+
+
+/* Forces any pending blit to complete for a given target.
+ * Blocking version, returns when blit is done.
+ * All input surfaces for this target except those which are shared with
+ * other targets are expected to be immediately
+ * writable after this function returns. */
+C2D_API C2D_STATUS c2dFinish( uint32 target_id );
+
+
+/*****************************************************************************/
+/****************************** Display API **********************************/
+/*****************************************************************************/
+
+
+/* Display input enumeration */
+typedef enum {
+    C2D_DISPLAY_INPUT_0      = 0,       /*!< default input */
+    C2D_DISPLAY_INPUT_1      = (1<<16), /*!< Overlay 1     */
+    C2D_DISPLAY_INPUT_2      = (1<<17), /*!< Overlay 2...    */
+} C2D_DISPLAY_INPUT;
+
+
+/******************************************************************************
+ * Functions for display output. */
+
+/* Functionality described in this section is optional and is
+ * provided only for the cases when blit HW
+ * is tightly bound to the display controller. */
+
+/* Display enumeration, may also be used in surface caps */
+typedef enum {
+    C2D_DISPLAY_MAIN         = (1 << 10), /* main display */
+    C2D_DISPLAY_SECONDARY    = (1 << 11), /* secondary display */
+    C2D_DISPLAY_TV_OUT       = (1 << 12), /* tv-out */
+} C2D_DISPLAY;
+
+/* Display window enumeration */
+typedef enum {
+    C2D_DISPLAY_OVERLAY      = C2D_DISPLAY_INPUT_1, /*!< Overlay window bit. This defines display input.
+                                                When defined the surface is set on the overlay window
+                                                otherwise the surface is set on the background window. */
+} C2D_DISPLAY_WINDOW;                    /*!< Window bit set with display parameter */
+
+
+/* Display update modes */
+typedef enum {
+    C2D_DISPLAY_MODE_TEAR_SYNC   = (1 << 0), /* enables tearing sync */
+    C2D_DISPLAY_MODE_SURF_REMOVE = (1 << 1), /* Remove surface from given display + input */
+} C2D_DISPLAY_MODE;
+
+
+/* Sets the given surface as a current display front buffer.
+ * Several displays can be specified as an output if supported.
+ * Still only one input can be specified at a time fro display/displays.
+ * The surface remains shown until it gets replaced with another one. */
+C2D_API C2D_STATUS c2dDisplaySetSurface( uint32 display,
+                         uint32 surface_id, uint32 mode );
+
+/* Returns the current surface for a particular display.
+ * Only one display can be specified at a time.
+ * The latest surface set with compDisplaySetSurface or
+ * the default pre-allocated surface is returned. */
+C2D_API C2D_STATUS c2dDisplayGetSurface( uint32 display,
+                         uint32 *surface_id );
+
+/* Returns the properties for a particular display.
+ * Only one display can be specified at a time. */
+C2D_API C2D_STATUS c2dDisplayGetProperties( uint32 display,
+                         uint32 *width, uint32 *height,
+                         uint32 *format );
+
+/* Sets the properties for a particular display input.
+ * Only one display + input can be specified at a time.
+ * C2D_OBJECT used to set input rect(target rect),
+ * blending operations, rotation...etc for display source */
+C2D_API C2D_STATUS c2dDisplaySetObject( uint32 display,
+                         uint32 target_config, uint32 target_color_key,
+                         C2D_OBJECT * c2dObject, uint32 mode);
+
+/*****************************************************************************/
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __c2d2_h_ */
diff --git a/libcopybit/copybit.cpp b/libcopybit/copybit.cpp
new file mode 100644
index 0000000..6f6fca5
--- /dev/null
+++ b/libcopybit/copybit.cpp
@@ -0,0 +1,498 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+#define LOG_TAG "copybit"
+
+#include <cutils/log.h>
+
+#include <linux/msm_mdp.h>
+#include <linux/fb.h>
+
+#include <stdint.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <fcntl.h>
+
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/mman.h>
+
+#include <hardware/copybit.h>
+
+#include "gralloc_priv.h"
+
+#define DEBUG_MDP_ERRORS 1
+
+/******************************************************************************/
+
+#if defined(COPYBIT_MSM7K)
+#define MAX_SCALE_FACTOR    (4)
+#define MAX_DIMENSION       (4096)
+#elif defined(COPYBIT_QSD8K)
+#define MAX_SCALE_FACTOR    (8)
+#define MAX_DIMENSION       (2048)
+#else
+#error "Unsupported MDP version"
+#endif
+
+/******************************************************************************/
+
+/** State information for each device instance */
+struct copybit_context_t {
+    struct copybit_device_t device;
+    int     mFD;
+    uint8_t mAlpha;
+    uint8_t mFlags;
+};
+
+/**
+ * Common hardware methods
+ */
+
+static int open_copybit(const struct hw_module_t* module, const char* name,
+        struct hw_device_t** device);
+
+static struct hw_module_methods_t copybit_module_methods = {
+    open:  open_copybit
+};
+
+/*
+ * The COPYBIT Module
+ */
+struct copybit_module_t HAL_MODULE_INFO_SYM = {
+    common: {
+        tag: HARDWARE_MODULE_TAG,
+        version_major: 1,
+        version_minor: 0,
+        id: COPYBIT_HARDWARE_MODULE_ID,
+        name: "QCT MSM7K COPYBIT Module",
+        author: "Google, Inc.",
+        methods: &copybit_module_methods
+    }
+};
+
+/******************************************************************************/
+
+/** min of int a, b */
+static inline int min(int a, int b) {
+    return (a<b) ? a : b;
+}
+
+/** max of int a, b */
+static inline int max(int a, int b) {
+    return (a>b) ? a : b;
+}
+
+/** scale each parameter by mul/div. Assume div isn't 0 */
+static inline void MULDIV(uint32_t *a, uint32_t *b, int mul, int div) {
+    if (mul != div) {
+        *a = (mul * *a) / div;
+        *b = (mul * *b) / div;
+    }
+}
+
+/** Determine the intersection of lhs & rhs store in out */
+static void intersect(struct copybit_rect_t *out,
+                      const struct copybit_rect_t *lhs,
+                      const struct copybit_rect_t *rhs) {
+    out->l = max(lhs->l, rhs->l);
+    out->t = max(lhs->t, rhs->t);
+    out->r = min(lhs->r, rhs->r);
+    out->b = min(lhs->b, rhs->b);
+}
+
+/** convert COPYBIT_FORMAT to MDP format */
+static int get_format(int format) {
+    switch (format) {
+    case HAL_PIXEL_FORMAT_RGB_565:       return MDP_RGB_565;
+    case HAL_PIXEL_FORMAT_RGBX_8888:     return MDP_RGBX_8888;
+    case HAL_PIXEL_FORMAT_RGB_888:       return MDP_RGB_888;
+    case HAL_PIXEL_FORMAT_RGBA_8888:     return MDP_RGBA_8888;
+    case HAL_PIXEL_FORMAT_BGRA_8888:     return MDP_BGRA_8888;
+    case HAL_PIXEL_FORMAT_YCrCb_422_SP:  return MDP_Y_CBCR_H2V1;
+    case HAL_PIXEL_FORMAT_YCrCb_420_SP:  return MDP_Y_CBCR_H2V2;
+    case HAL_PIXEL_FORMAT_YCbCr_422_SP:  return MDP_Y_CRCB_H2V1;
+    case HAL_PIXEL_FORMAT_YCbCr_420_SP:  return MDP_Y_CRCB_H2V2;
+    }
+    return -1;
+}
+
+/** convert from copybit image to mdp image structure */
+static void set_image(struct mdp_img *img, const struct copybit_image_t *rhs) 
+{
+    private_handle_t* hnd = (private_handle_t*)rhs->handle;
+    img->width      = rhs->w;
+    img->height     = rhs->h;
+    img->format     = get_format(rhs->format);
+    img->offset     = hnd->offset;
+    #if defined(COPYBIT_MSM7K)
+        #if defined(USE_ASHMEM) && (TARGET_7x27)
+             img->memory_id = hnd->fd;
+        #else //USE_ASHMEM not defined
+             img->memory_id = hnd->fd;
+        #endif //end USE_ASHMEM
+    #else
+        img->memory_id  = hnd->fd;
+    #endif
+}
+/** setup rectangles */
+static void set_rects(struct copybit_context_t *dev,
+                      struct mdp_blit_req *e,
+                      const struct copybit_rect_t *dst,
+                      const struct copybit_rect_t *src,
+                      const struct copybit_rect_t *scissor,
+                      uint32_t horiz_padding,
+                      uint32_t vert_padding) {
+    struct copybit_rect_t clip;
+    intersect(&clip, scissor, dst);
+
+    e->dst_rect.x  = clip.l;
+    e->dst_rect.y  = clip.t;
+    e->dst_rect.w  = clip.r - clip.l;
+    e->dst_rect.h  = clip.b - clip.t;
+
+    uint32_t W, H;
+    if (dev->mFlags & COPYBIT_TRANSFORM_ROT_90) {
+        e->src_rect.x = (clip.t - dst->t) + src->t;
+        e->src_rect.y = (dst->r - clip.r) + src->l;
+        e->src_rect.w = (clip.b - clip.t);
+        e->src_rect.h = (clip.r - clip.l);
+        W = dst->b - dst->t;
+        H = dst->r - dst->l;
+    } else {
+        e->src_rect.x  = (clip.l - dst->l) + src->l;
+        e->src_rect.y  = (clip.t - dst->t) + src->t;
+        e->src_rect.w  = (clip.r - clip.l);
+        e->src_rect.h  = (clip.b - clip.t);
+        W = dst->r - dst->l;
+        H = dst->b - dst->t;
+    }
+    MULDIV(&e->src_rect.x, &e->src_rect.w, src->r - src->l, W);
+    MULDIV(&e->src_rect.y, &e->src_rect.h, src->b - src->t, H);
+
+    if (dev->mFlags & COPYBIT_TRANSFORM_FLIP_V) {
+        if (dev->mFlags & COPYBIT_TRANSFORM_ROT_90) {
+            e->src_rect.x = e->src.width - (e->src_rect.x + e->src_rect.w) - horiz_padding;
+        }else{
+            e->src_rect.y = e->src.height - (e->src_rect.y + e->src_rect.h) - vert_padding;
+        }
+    }
+
+    if (dev->mFlags & COPYBIT_TRANSFORM_FLIP_H) {
+        if (dev->mFlags & COPYBIT_TRANSFORM_ROT_90) {
+            e->src_rect.y = e->src.height - (e->src_rect.y + e->src_rect.h) - vert_padding;
+        }else{
+            e->src_rect.x = e->src.width - (e->src_rect.x + e->src_rect.w) - horiz_padding;
+        }
+    }
+}
+
+/** setup mdp request */
+static void set_infos(struct copybit_context_t *dev, struct mdp_blit_req *req, int flags) {
+    req->alpha = dev->mAlpha;
+    req->transp_mask = MDP_TRANSP_NOP;
+    req->flags = dev->mFlags | flags;
+#if defined(COPYBIT_QSD8K)
+    req->flags |= MDP_BLEND_FG_PREMULT;
+#endif
+}
+
+/** copy the bits */
+static int msm_copybit(struct copybit_context_t *dev, void const *list) 
+{
+    int err = ioctl(dev->mFD, MSMFB_BLIT,
+                    (struct mdp_blit_req_list const*)list);
+    LOGE_IF(err<0, "copyBits failed (%s)", strerror(errno));
+    if (err == 0) {
+        return 0;
+    } else {
+#if DEBUG_MDP_ERRORS
+        struct mdp_blit_req_list const* l = (struct mdp_blit_req_list const*)list;
+        for (int i=0 ; i<l->count ; i++) {
+            LOGD("%d: src={w=%d, h=%d, f=%d, rect={%d,%d,%d,%d}}\n"
+                 "    dst={w=%d, h=%d, f=%d, rect={%d,%d,%d,%d}}\n"
+                 "    flags=%08lx"
+                    ,
+                    i,
+                    l->req[i].src.width,
+                    l->req[i].src.height,
+                    l->req[i].src.format,
+                    l->req[i].src_rect.x,
+                    l->req[i].src_rect.y,
+                    l->req[i].src_rect.w,
+                    l->req[i].src_rect.h,
+                    l->req[i].dst.width,
+                    l->req[i].dst.height,
+                    l->req[i].dst.format,
+                    l->req[i].dst_rect.x,
+                    l->req[i].dst_rect.y,
+                    l->req[i].dst_rect.w,
+                    l->req[i].dst_rect.h,
+                    l->req[i].flags
+            );
+        }
+#endif
+        return -errno;
+    }
+}
+
+/*****************************************************************************/
+
+/** Set a parameter to value */
+static int set_parameter_copybit(
+        struct copybit_device_t *dev,
+        int name,
+        int value) 
+{
+    struct copybit_context_t* ctx = (struct copybit_context_t*)dev;
+    int status = 0;
+    if (ctx) {
+        switch(name) {
+        case COPYBIT_ROTATION_DEG:
+            switch (value) {
+            case 0:
+                ctx->mFlags &= ~0x7;
+                break;
+            case 90:
+                ctx->mFlags &= ~0x7;
+                ctx->mFlags |= MDP_ROT_90;
+                break;
+            case 180:
+                ctx->mFlags &= ~0x7;
+                ctx->mFlags |= MDP_ROT_180;
+                break;
+            case 270:
+                ctx->mFlags &= ~0x7;
+                ctx->mFlags |= MDP_ROT_270;
+                break;
+            default:
+                LOGE("Invalid value for COPYBIT_ROTATION_DEG");
+                status = -EINVAL;
+                break;
+            }
+            break;
+        case COPYBIT_PLANE_ALPHA:
+            if (value < 0)      value = 0;
+            if (value >= 256)   value = 255;
+            ctx->mAlpha = value;
+            break;
+        case COPYBIT_DITHER:
+            if (value == COPYBIT_ENABLE) {
+                ctx->mFlags |= MDP_DITHER;
+            } else if (value == COPYBIT_DISABLE) {
+                ctx->mFlags &= ~MDP_DITHER;
+            }
+            break;
+        case COPYBIT_BLUR:
+            if (value == COPYBIT_ENABLE) {
+                ctx->mFlags |= MDP_BLUR;
+            } else if (value == COPYBIT_DISABLE) {
+                ctx->mFlags &= ~MDP_BLUR;
+            }
+            break;
+        case COPYBIT_TRANSFORM:
+            ctx->mFlags &= ~0x7;
+            ctx->mFlags |= value & 0x7;
+            break;
+        default:
+            status = -EINVAL;
+            break;
+        }
+    } else {
+        status = -EINVAL;
+    }
+    return status;
+}
+
+/** Get a static info value */
+static int get(struct copybit_device_t *dev, int name) 
+{
+    struct copybit_context_t* ctx = (struct copybit_context_t*)dev;
+    int value;
+    if (ctx) {
+        switch(name) {
+        case COPYBIT_MINIFICATION_LIMIT:
+            value = MAX_SCALE_FACTOR;
+            break;
+        case COPYBIT_MAGNIFICATION_LIMIT:
+            value = MAX_SCALE_FACTOR;
+            break;
+        case COPYBIT_SCALING_FRAC_BITS:
+            value = 32;
+            break;
+        case COPYBIT_ROTATION_STEP_DEG:
+            value = 90;
+            break;
+        default:
+            value = -EINVAL;
+        }
+    } else {
+        value = -EINVAL;
+    }
+    return value;
+}
+
+/** do a stretch blit type operation */
+static int stretch_copybit(
+        struct copybit_device_t *dev,
+        struct copybit_image_t const *dst,
+        struct copybit_image_t const *src,
+        struct copybit_rect_t const *dst_rect,
+        struct copybit_rect_t const *src_rect,
+        struct copybit_region_t const *region) 
+{
+    struct copybit_context_t* ctx = (struct copybit_context_t*)dev;
+    int status = 0;
+    if (ctx) {
+        struct {
+            uint32_t count;
+            struct mdp_blit_req req[12];
+        } list;
+
+        if (ctx->mAlpha < 255) {
+            switch (src->format) {
+                // we don't support plane alpha with RGBA formats
+                case HAL_PIXEL_FORMAT_RGBA_8888:
+                case HAL_PIXEL_FORMAT_BGRA_8888:
+                case HAL_PIXEL_FORMAT_RGBA_5551:
+                case HAL_PIXEL_FORMAT_RGBA_4444:
+                    return -EINVAL;
+            }
+        }
+
+        if (src_rect->l < 0 || src_rect->r > src->w ||
+            src_rect->t < 0 || src_rect->b > src->h) {
+            // this is always invalid
+            return -EINVAL;
+        }
+
+        if (src->w > MAX_DIMENSION || src->h > MAX_DIMENSION)
+            return -EINVAL;
+
+        if (dst->w > MAX_DIMENSION || dst->h > MAX_DIMENSION)
+            return -EINVAL;
+
+        const uint32_t maxCount = sizeof(list.req)/sizeof(list.req[0]);
+        const struct copybit_rect_t bounds = { 0, 0, dst->w, dst->h };
+        struct copybit_rect_t clip;
+        list.count = 0;
+        status = 0;
+        while ((status == 0) && region->next(region, &clip)) {
+            intersect(&clip, &bounds, &clip);
+            mdp_blit_req* req = &list.req[list.count];
+            int flags = 0;
+
+            set_infos(ctx, req, flags);
+            set_image(&req->dst, dst);
+            set_image(&req->src, src);
+            set_rects(ctx, req, dst_rect, src_rect, &clip, src->horiz_padding, src->vert_padding);
+
+            if (req->src_rect.w<=0 || req->src_rect.h<=0)
+                continue;
+
+            if (req->dst_rect.w<=0 || req->dst_rect.h<=0)
+                continue;
+
+            if (++list.count == maxCount) {
+                status = msm_copybit(ctx, &list);
+                list.count = 0;
+            }
+        }
+        if ((status == 0) && list.count) {
+            status = msm_copybit(ctx, &list);
+        }
+    } else {
+        status = -EINVAL;
+    }
+    return status;
+}
+
+/** Perform a blit type operation */
+static int blit_copybit(
+        struct copybit_device_t *dev,
+        struct copybit_image_t const *dst,
+        struct copybit_image_t const *src,
+        struct copybit_region_t const *region) 
+{
+    struct copybit_rect_t dr = { 0, 0, dst->w, dst->h };
+    struct copybit_rect_t sr = { 0, 0, src->w, src->h };
+    return stretch_copybit(dev, dst, src, &dr, &sr, region);
+}
+
+/*****************************************************************************/
+
+/** Close the copybit device */
+static int close_copybit(struct hw_device_t *dev) 
+{
+    struct copybit_context_t* ctx = (struct copybit_context_t*)dev;
+    if (ctx) {
+        close(ctx->mFD);
+        free(ctx);
+    }
+    return 0;
+}
+
+/** Open a new instance of a copybit device using name */
+static int open_copybit(const struct hw_module_t* module, const char* name,
+        struct hw_device_t** device)
+{
+    int status = -EINVAL;
+    copybit_context_t *ctx;
+    ctx = (copybit_context_t *)malloc(sizeof(copybit_context_t));
+    memset(ctx, 0, sizeof(*ctx));
+
+    ctx->device.common.tag = HARDWARE_DEVICE_TAG;
+    ctx->device.common.version = 1;
+    ctx->device.common.module = const_cast<hw_module_t*>(module);
+    ctx->device.common.close = close_copybit;
+    ctx->device.set_parameter = set_parameter_copybit;
+    ctx->device.get = get;
+    ctx->device.blit = blit_copybit;
+    ctx->device.stretch = stretch_copybit;
+    ctx->mAlpha = MDP_ALPHA_NOP;
+    ctx->mFlags = 0;
+    ctx->mFD = open("/dev/graphics/fb0", O_RDWR, 0);
+    
+    if (ctx->mFD < 0) {
+        status = errno;
+        LOGE("Error opening frame buffer errno=%d (%s)",
+             status, strerror(status));
+        status = -status;
+    } else {
+        struct fb_fix_screeninfo finfo;
+        if (ioctl(ctx->mFD, FBIOGET_FSCREENINFO, &finfo) == 0) {
+            if (strncmp(finfo.id, "msmfb", 5) == 0) {
+                /* Success */
+                status = 0;
+            } else {
+                LOGE("Error not msm frame buffer");
+                status = -EINVAL;
+            }
+        } else {
+            LOGE("Error executing ioctl for screen info");
+            status = -errno;
+        }
+    }
+
+    if (status == 0) {
+        *device = &ctx->device.common;
+    } else {
+        close_copybit(&ctx->device.common);
+    }
+    return status;
+}
diff --git a/libcopybit/copybit_c2d.cpp b/libcopybit/copybit_c2d.cpp
new file mode 100644
index 0000000..0995345
--- /dev/null
+++ b/libcopybit/copybit_c2d.cpp
@@ -0,0 +1,1036 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "copybit_c2d"
+
+#include <cutils/log.h>
+
+#include <stdint.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <fcntl.h>
+
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/mman.h>
+
+#include <linux/msm_kgsl.h>
+#include <linux/ioctl.h>
+
+#include <ui/egl/android_natives.h>
+#include <ui/egl/android_natives.h>
+#include <private/ui/android_natives_priv.h>
+#include <cutils/native_handle.h>
+#include <gralloc_priv.h>
+
+#include <hardware/copybit.h>
+
+#include "c2d2.h"
+
+#include <dlfcn.h>
+C2D_STATUS (*LINK_c2dCreateSurface)( uint32 *surface_id,
+                                     uint32 surface_bits,
+                                     C2D_SURFACE_TYPE surface_type,
+                                     void *surface_definition );
+
+C2D_STATUS (*LINK_c2dUpdateSurface)( uint32 surface_id,
+                                     uint32 surface_bits,
+                                     C2D_SURFACE_TYPE surface_type,
+                                     void *surface_definition );
+
+C2D_STATUS (*LINK_c2dReadSurface)( uint32 surface_id,
+                                   C2D_SURFACE_TYPE surface_type,
+                                   void *surface_definition,
+                                   int32 x, int32 y );
+
+C2D_STATUS (*LINK_c2dDraw)( uint32 target_id,
+                            uint32 target_config, C2D_RECT *target_scissor,
+                            uint32 target_mask_id, uint32 target_color_key,
+                            C2D_OBJECT *objects_list, uint32 num_objects );
+
+C2D_STATUS (*LINK_c2dFinish)( uint32 target_id);
+
+C2D_STATUS (*LINK_c2dFlush)( uint32 target_id, c2d_ts_handle *timestamp);
+
+C2D_STATUS (*LINK_c2dWaitTimestamp)( c2d_ts_handle timestamp );
+
+C2D_STATUS (*LINK_c2dDestroySurface)( uint32 surface_id );
+
+
+/******************************************************************************/
+
+#if defined(COPYBIT_Z180)
+#define MAX_SCALE_FACTOR    (4096)
+#define MAX_DIMENSION       (4096)
+#else
+#error "Unsupported HW version"
+#endif
+
+#define G12_DEVICE_NAME "/dev/kgsl-2d0"
+
+#define COPYBIT_SUCCESS 0
+#define COPYBIT_FAILURE -1
+
+#define RGB_SURFACE 0
+#define YUV_SURFACE 1
+#define NUM_SRC_SURFACES 2
+#define ALIGN(x, align) (((x) + ((align)-1)) & ~((align)-1))
+/******************************************************************************/
+
+/** State information for each device instance */
+struct copybit_context_t {
+    struct copybit_device_t device;
+    unsigned int src[NUM_SRC_SURFACES];
+    unsigned int dst;                /* dst surface */
+    unsigned int trg_transform;      /* target transform */
+    C2D_OBJECT blitState;
+    void *libc2d2;
+    int g12_device_fd;
+    int fb_width;
+    int fb_height;
+    bool isPremultipliedAlpha;
+};
+
+struct blitlist{
+    uint32_t count;
+    C2D_OBJECT blitObjects[12];
+};
+
+/**
+ * Common hardware methods
+ */
+
+static int open_copybit(const struct hw_module_t* module, const char* name,
+        struct hw_device_t** device);
+
+static struct hw_module_methods_t copybit_module_methods = {
+    open:  open_copybit
+};
+
+/*
+ * The COPYBIT Module
+ */
+struct copybit_module_t HAL_MODULE_INFO_SYM = {
+    common: {
+        tag: HARDWARE_MODULE_TAG,
+        version_major: 1,
+        version_minor: 0,
+        id: COPYBIT_HARDWARE_MODULE_ID,
+        name: "QCT COPYBIT C2D 2.0 Module",
+        author: "Qualcomm",
+        methods: &copybit_module_methods
+    }
+};
+
+
+/* convert COPYBIT_FORMAT to C2D format */
+static int get_format(int format) {
+    switch (format) {
+    case HAL_PIXEL_FORMAT_RGB_565:        return C2D_COLOR_FORMAT_565_RGB;
+    case HAL_PIXEL_FORMAT_RGBX_8888:      return C2D_COLOR_FORMAT_8888_ARGB | C2D_FORMAT_SWAP_RB | C2D_FORMAT_DISABLE_ALPHA;
+    case HAL_PIXEL_FORMAT_RGBA_8888:      return C2D_COLOR_FORMAT_8888_ARGB | C2D_FORMAT_SWAP_RB;
+    case HAL_PIXEL_FORMAT_BGRA_8888:      return C2D_COLOR_FORMAT_8888_ARGB;
+    case HAL_PIXEL_FORMAT_RGBA_5551:      return C2D_COLOR_FORMAT_5551_RGBA;
+    case HAL_PIXEL_FORMAT_RGBA_4444:      return C2D_COLOR_FORMAT_4444_RGBA;
+    case HAL_PIXEL_FORMAT_YCbCr_420_SP:   return C2D_COLOR_FORMAT_420_NV12;
+    case HAL_PIXEL_FORMAT_YCrCb_420_SP:   return C2D_COLOR_FORMAT_420_NV21;
+    case HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED: return C2D_COLOR_FORMAT_420_NV12 | C2D_FORMAT_MACROTILED;
+    default:                            return -EINVAL;
+    }
+    return -EINVAL;
+}
+
+/* ------------------------------------------------------------------- *//*!
+ * \internal
+ * \brief Get the bpp for a particular color format
+ * \param color format
+ * \return bits per pixel
+*//* ------------------------------------------------------------------- */
+int c2diGetBpp(int32 colorformat)
+{
+
+    int c2dBpp = 0;
+
+    switch(colorformat&0xFF)
+    {
+    case C2D_COLOR_FORMAT_4444_RGBA:
+    case C2D_COLOR_FORMAT_4444_ARGB:
+    case C2D_COLOR_FORMAT_1555_ARGB:
+    case C2D_COLOR_FORMAT_565_RGB:
+    case C2D_COLOR_FORMAT_5551_RGBA:
+        c2dBpp = 16;
+        break;
+    case C2D_COLOR_FORMAT_8888_RGBA:
+    case C2D_COLOR_FORMAT_8888_ARGB:
+        c2dBpp = 32;
+        break;
+    case C2D_COLOR_FORMAT_8_L:
+    case C2D_COLOR_FORMAT_8_A:
+        c2dBpp = 8;
+        break;
+    case C2D_COLOR_FORMAT_4_A:
+        c2dBpp = 4;
+        break;
+    case C2D_COLOR_FORMAT_1:
+        c2dBpp = 1;
+        break;
+    default:
+        LOGE("%s ERROR", __func__);
+        break;
+    }
+    return c2dBpp;
+}
+
+static uint32 c2d_get_gpuaddr(int device_fd, struct private_handle_t *handle)
+{
+    if(!handle)
+        return 0;
+
+    struct kgsl_map_user_mem param;
+    memset(&param, 0, sizeof(param));
+    param.fd = handle->fd;
+    param.len = handle->size;
+    param.offset = handle->offset;
+    param.hostptr = handle->base;
+
+    if (handle->flags & (private_handle_t::PRIV_FLAGS_USES_PMEM |
+                private_handle_t::PRIV_FLAGS_USES_PMEM_ADSP))
+        param.memtype = KGSL_USER_MEM_TYPE_PMEM;
+    else if (handle->flags & private_handle_t::PRIV_FLAGS_USES_ASHMEM)
+        param.memtype = KGSL_USER_MEM_TYPE_ASHMEM;
+    else if (handle->flags & private_handle_t::PRIV_FLAGS_USES_ION)
+        param.memtype = KGSL_USER_MEM_TYPE_ION;
+    else {
+        LOGE("Invalid handle flags: 0x%x", handle->flags);
+        return 0;
+    }
+
+    if (!ioctl(device_fd, IOCTL_KGSL_MAP_USER_MEM, (void *)&param, sizeof(param))) {
+        return param.gpuaddr;
+    }
+
+    return 0;
+}
+
+static uint32 c2d_unmap_gpuaddr(int device_fd, unsigned int gpuaddr)
+{
+    struct kgsl_sharedmem_free param;
+
+    memset(&param, 0, sizeof(param));
+    param.gpuaddr = gpuaddr;
+
+    ioctl(device_fd, IOCTL_KGSL_SHAREDMEM_FREE, (void *)&param,  sizeof(param));
+    return COPYBIT_SUCCESS;
+}
+
+static int is_supported_rgb_format(int format)
+{
+    switch(format) {
+        case HAL_PIXEL_FORMAT_RGBA_8888:
+        case HAL_PIXEL_FORMAT_RGBX_8888:
+        case HAL_PIXEL_FORMAT_RGB_565:
+        case HAL_PIXEL_FORMAT_BGRA_8888:
+        case HAL_PIXEL_FORMAT_RGBA_5551:
+        case HAL_PIXEL_FORMAT_RGBA_4444: {
+            return COPYBIT_SUCCESS;
+        }
+        default:
+            return COPYBIT_FAILURE;
+    }
+}
+
+static int is_supported_yuv_format(int format)
+{
+    switch(format) {
+        case HAL_PIXEL_FORMAT_YCbCr_420_SP:
+        case HAL_PIXEL_FORMAT_YCrCb_420_SP:
+        case HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED: {
+            return COPYBIT_SUCCESS;
+        }
+        default:
+            return COPYBIT_FAILURE;
+    }
+}
+
+static int calculate_yuv_offset_and_stride(int format, int width, int height, int *offset, int *yStride, int *uvStride)
+{
+    int aligned_height = 0;
+    int aligned_width = 0, size = 0;
+
+    switch (format) {
+        case HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED: {
+            /* NV12 Tile buffers have their luma height aligned to 32bytes and width
+             * aligned to 128 bytes. The chroma offset starts at an 8K boundary
+             */
+            aligned_height = ALIGN(height, 32);
+            aligned_width  = ALIGN(width, 128);
+            size = aligned_width * aligned_height;
+            *offset = ALIGN(size,8192);
+            *yStride = aligned_width;
+            *uvStride = aligned_width;
+            break;
+        }
+        case HAL_PIXEL_FORMAT_YCbCr_420_SP:
+        case HAL_PIXEL_FORMAT_YCrCb_420_SP: {
+            aligned_width = ALIGN(width, 32);
+            *offset = aligned_width * height;
+            *yStride = aligned_width;
+            *uvStride = aligned_width;
+            break;
+        }
+        default: {
+            return COPYBIT_FAILURE;
+        }
+    }
+    return COPYBIT_SUCCESS;
+}
+
+/** create C2D surface from copybit image */
+static int set_image(int device_fd, uint32 surfaceId, const struct copybit_image_t *rhs, int *cformat, uint32_t *mapped,
+                     const bool isPremultipliedAlpha)
+{
+    struct private_handle_t* handle = (struct private_handle_t*)rhs->handle;
+    C2D_SURFACE_TYPE surfaceType;
+    int status = COPYBIT_SUCCESS;
+
+    *cformat  = get_format(rhs->format);
+    if(*cformat == -EINVAL) {
+        LOGE("%s: invalid format", __func__);
+        return -EINVAL;
+    }
+
+    if(handle == NULL) {
+        LOGE("%s: invalid handle", __func__);
+        return -EINVAL;
+    }
+
+    if (handle->gpuaddr == 0) {
+       handle->gpuaddr = c2d_get_gpuaddr(device_fd, handle);
+       if(!handle->gpuaddr) {
+           return COPYBIT_FAILURE;
+       }
+       *mapped = 1;
+    }
+
+    /* create C2D surface */
+    if(is_supported_rgb_format(rhs->format) == COPYBIT_SUCCESS) {
+        /* RGB */
+        C2D_RGB_SURFACE_DEF surfaceDef;
+
+        surfaceType = (C2D_SURFACE_TYPE) (C2D_SURFACE_RGB_HOST | C2D_SURFACE_WITH_PHYS);
+
+        surfaceDef.phys = (void*) handle->gpuaddr;
+        surfaceDef.buffer = (void*) (handle->base);
+
+        surfaceDef.format = *cformat | (isPremultipliedAlpha ? C2D_FORMAT_PREMULTIPLIED : 0);
+        surfaceDef.width = rhs->w;
+        surfaceDef.height = rhs->h;
+        surfaceDef.stride = ALIGN(((surfaceDef.width * c2diGetBpp(surfaceDef.format))>>3), 32);
+
+        if(LINK_c2dUpdateSurface( surfaceId,C2D_TARGET | C2D_SOURCE, surfaceType, &surfaceDef)) {
+            LOGE("%s: RGB Surface c2dUpdateSurface ERROR", __func__);
+            goto error;
+            status = COPYBIT_FAILURE;
+        }
+    } else if (is_supported_yuv_format(rhs->format) == COPYBIT_SUCCESS) {
+        C2D_YUV_SURFACE_DEF surfaceDef;
+        int offset = 0;
+        int yStride = 0;
+        int uvStride = 0;
+        memset(&surfaceDef, 0, sizeof(surfaceDef));
+        surfaceType = (C2D_SURFACE_TYPE)(C2D_SURFACE_YUV_HOST | C2D_SURFACE_WITH_PHYS);
+        surfaceDef.format = *cformat;
+
+        status = calculate_yuv_offset_and_stride(rhs->format, rhs->w, rhs->h, &offset, &yStride, &uvStride);
+        if(status != COPYBIT_SUCCESS) {
+            LOGE("calculate_yuv_offset_and_stride error");
+            goto error;
+        }
+
+        surfaceDef.width = rhs->w;
+        surfaceDef.height = rhs->h;
+        surfaceDef.plane0 = (void*) (handle->base);
+        surfaceDef.phys0 = (void*) (handle->gpuaddr);
+        surfaceDef.stride0 = yStride;
+
+        surfaceDef.plane1 = (void*) (handle->base + offset);
+        surfaceDef.phys1 = (void*) (handle->gpuaddr + offset);
+        surfaceDef.stride1 = uvStride;
+
+        if(LINK_c2dUpdateSurface( surfaceId,C2D_TARGET | C2D_SOURCE, surfaceType, &surfaceDef)) {
+            LOGE("%s: YUV Surface c2dUpdateSurface ERROR", __func__);
+            goto error;
+            status = COPYBIT_FAILURE;
+        }
+    } else {
+        LOGE("%s: invalid format %x", __func__, rhs->format);
+        goto error;
+        status = COPYBIT_FAILURE;
+    }
+
+    return status;
+
+error:
+    if(*mapped == 1) {
+        c2d_unmap_gpuaddr(device_fd, handle->gpuaddr);
+        handle->gpuaddr = 0;
+        *mapped = 0;
+    }
+    return status;
+}
+
+static int set_src_image(int device_fd, uint32 *surfaceId, const struct copybit_image_t *rhs, int *cformat, uint32 *mapped)
+{
+    struct private_handle_t* handle = (struct private_handle_t*)rhs->handle;
+    *cformat  = get_format(rhs->format);
+    C2D_SURFACE_TYPE surfaceType;
+    uint32 gpuaddr = (uint32)handle->gpuaddr;
+    int status = COPYBIT_SUCCESS;
+
+    if (handle->gpuaddr == 0)
+    {
+       handle->gpuaddr = c2d_get_gpuaddr(device_fd, handle);
+       if(!handle->gpuaddr)
+           return COPYBIT_FAILURE;
+
+       *mapped = 1;
+    }
+
+    /* create C2D surface */
+    if(is_supported_rgb_format(rhs->format) == COPYBIT_SUCCESS) {
+        /* RGB */
+        C2D_RGB_SURFACE_DEF surfaceDef;
+        surfaceType = (C2D_SURFACE_TYPE) (C2D_SURFACE_RGB_HOST | C2D_SURFACE_WITH_PHYS);
+
+        surfaceDef.phys = (void*) handle->gpuaddr;
+        surfaceDef.buffer = (void*) (handle->base);
+        surfaceDef.buffer = (void*) (handle->base + handle->offset);
+
+        surfaceDef.format = get_format(rhs->format);
+        surfaceDef.width = rhs->w;
+        surfaceDef.height = rhs->h;
+        surfaceDef.stride = ALIGN(((surfaceDef.width * c2diGetBpp(surfaceDef.format))>>3), 32);
+
+        if(LINK_c2dCreateSurface( surfaceId, C2D_TARGET, surfaceType,(void*)&surfaceDef)) {
+            LOGE("%s: LINK_c2dCreateSurface error", __func__);
+            status = COPYBIT_FAILURE;
+            goto error;
+        }
+    } else if(is_supported_yuv_format(rhs->format) == COPYBIT_SUCCESS) {
+        /* YUV */
+        C2D_YUV_SURFACE_DEF surfaceDef;
+        int offset = 0;
+        int yStride = 0;
+        int uvStride = 0;
+        memset(&surfaceDef, 0, sizeof(surfaceDef));
+
+        surfaceType = (C2D_SURFACE_TYPE)(C2D_SURFACE_YUV_HOST | C2D_SURFACE_WITH_PHYS);
+        surfaceDef.format = get_format(rhs->format);
+        status = calculate_yuv_offset_and_stride(rhs->format, rhs->w, rhs->h, &offset, &yStride, &uvStride);
+        if(status != COPYBIT_SUCCESS) {
+            LOGE("calculate_yuv_offset_and_stride error");
+            goto error;
+        }
+
+        surfaceDef.width = rhs->w;
+        surfaceDef.height = rhs->h;
+        surfaceDef.plane0 = (void*) (handle->base);
+        surfaceDef.phys0 = (void*) handle->gpuaddr;
+        surfaceDef.stride0 = yStride;
+
+        surfaceDef.plane1 = (void*) (handle->base + offset);
+        surfaceDef.phys1 = (void*) (handle->gpuaddr + offset);
+        surfaceDef.stride1 = uvStride;
+
+        if(LINK_c2dCreateSurface( surfaceId, C2D_TARGET | C2D_SOURCE, surfaceType, (void*)&surfaceDef)) {
+            LOGE("%s: YUV surface LINK_c2dCreateSurface error", __func__);
+            status = COPYBIT_FAILURE;
+            goto error;
+        }
+    } else {
+        LOGE("%s: Invalid format %x", __func__, rhs->format);
+        status = COPYBIT_FAILURE;
+    }
+
+    return COPYBIT_SUCCESS;
+
+error:
+    if(*mapped == 1) {
+        c2d_unmap_gpuaddr(device_fd, handle->gpuaddr);
+        handle->gpuaddr = 0;
+        *mapped = 0;
+    }
+    return status;
+}
+
+void unset_image(int device_fd, uint32 surfaceId, const struct copybit_image_t *rhs, uint32 mmapped)
+{
+    struct private_handle_t* handle = (struct private_handle_t*)rhs->handle;
+
+    if (mmapped && handle->gpuaddr) {
+        // Unmap this gpuaddr
+        c2d_unmap_gpuaddr(device_fd, handle->gpuaddr);
+        handle->gpuaddr = 0;
+    }
+}
+
+static int blit_to_target(int device_fd, uint32 surfaceId, const struct copybit_image_t *rhs)
+{
+    struct private_handle_t* handle = (struct private_handle_t*)rhs->handle;
+    uint32 cformat  = get_format(rhs->format);
+    C2D_SURFACE_TYPE surfaceType;
+    uint32 memoryMapped = 0;
+    int status = COPYBIT_SUCCESS;
+
+    if (!handle->gpuaddr) {
+        handle->gpuaddr = c2d_get_gpuaddr(device_fd,handle);
+        if(!handle->gpuaddr)
+            return COPYBIT_FAILURE;
+
+        memoryMapped = 1;
+    }
+
+    /* create C2D surface */
+
+    if(cformat) {
+        /* RGB */
+        C2D_RGB_SURFACE_DEF surfaceDef;
+        memset(&surfaceDef, 0, sizeof(surfaceDef));
+
+        surfaceDef.buffer = (void*) handle->base;
+        surfaceDef.phys = (void*) handle->gpuaddr;
+
+        surfaceType = C2D_SURFACE_RGB_HOST;
+        surfaceDef.format = get_format(rhs->format);
+        surfaceDef.width = rhs->w;
+        surfaceDef.height = rhs->h;
+        surfaceDef.stride = ALIGN(((surfaceDef.width * c2diGetBpp(surfaceDef.format))>>3), 32);
+
+        if(LINK_c2dReadSurface(surfaceId, surfaceType, (void*)&surfaceDef, 0, 0)) {
+            LOGE("%s: LINK_c2dReadSurface ERROR", __func__);
+            status = COPYBIT_FAILURE;
+            goto done;
+        }
+    }
+    else {
+        /* YUV */
+        /* TODO */
+    }
+
+done:
+    if (memoryMapped) {
+        c2d_unmap_gpuaddr(device_fd, handle->gpuaddr);
+        handle->gpuaddr = 0;
+    }
+    return status;
+}
+
+/** setup rectangles */
+static void set_rects(struct copybit_context_t *ctx,
+                      C2D_OBJECT *c2dObject,
+                      const struct copybit_rect_t *dst,
+                      const struct copybit_rect_t *src,
+                      const struct copybit_rect_t *scissor)
+{
+
+    if((ctx->trg_transform & C2D_TARGET_ROTATE_90) &&
+       (ctx->trg_transform & C2D_TARGET_ROTATE_180)) {
+        /* target rotation is 270 */
+        c2dObject->target_rect.x        = (dst->t)<<16;
+        c2dObject->target_rect.y        = (ALIGN(ctx->fb_width,32) - (dst->r))<<16;
+        c2dObject->target_rect.height   = ((dst->r) - (dst->l))<<16;
+        c2dObject->target_rect.width    = ((dst->b) - (dst->t))<<16;
+    } else if(ctx->trg_transform & C2D_TARGET_ROTATE_90) {
+        c2dObject->target_rect.x        = (ctx->fb_height - dst->b)<<16;
+        c2dObject->target_rect.y        = (dst->l)<<16;
+        c2dObject->target_rect.height   = ((dst->r) - (dst->l))<<16;
+        c2dObject->target_rect.width    = ((dst->b) - (dst->t))<<16;
+    } else if(ctx->trg_transform & C2D_TARGET_ROTATE_180) {
+        c2dObject->target_rect.y        = (ctx->fb_height - dst->b)<<16;
+        c2dObject->target_rect.x        = (ALIGN(ctx->fb_width,32) - dst->r)<<16;
+        c2dObject->target_rect.height   = ((dst->b) - (dst->t))<<16;
+        c2dObject->target_rect.width    = ((dst->r) - (dst->l))<<16;
+    } else {
+        c2dObject->target_rect.x        = (dst->l)<<16;
+        c2dObject->target_rect.y        = (dst->t)<<16;
+        c2dObject->target_rect.height   = ((dst->b) - (dst->t))<<16;
+        c2dObject->target_rect.width    = ((dst->r) - (dst->l))<<16;
+    }
+    c2dObject->config_mask |= C2D_TARGET_RECT_BIT;
+
+    c2dObject->source_rect.x        = (src->l)<<16;
+    c2dObject->source_rect.y        = (src->t)<<16;
+    c2dObject->source_rect.height   = ((src->b) - (src->t))<<16;
+    c2dObject->source_rect.width    = ((src->r) - (src->l))<<16;
+    c2dObject->config_mask |= C2D_SOURCE_RECT_BIT;
+
+    c2dObject->scissor_rect.x       = scissor->l;
+    c2dObject->scissor_rect.y       = scissor->t;
+    c2dObject->scissor_rect.height  = (scissor->b) - (scissor->t);
+    c2dObject->scissor_rect.width   = (scissor->r) - (scissor->l);
+
+    c2dObject->config_mask |= C2D_SCISSOR_RECT_BIT;
+}
+
+/** copy the bits */
+static int msm_copybit(struct copybit_context_t *dev, blitlist *list, uint32 target)
+{
+    int objects;
+
+    for(objects = 0; objects < list->count; objects++) {
+       list->blitObjects[objects].next = &(list->blitObjects[objects+1]);
+    }
+
+    if(LINK_c2dDraw(target,dev->trg_transform, 0x0, 0, 0, list->blitObjects,
+                    list->count)) {
+       LOGE("%s: LINK_c2dDraw ERROR");
+       return COPYBIT_FAILURE;
+    }
+
+    return COPYBIT_SUCCESS;
+}
+
+/*****************************************************************************/
+
+/** Set a parameter to value */
+static int set_parameter_copybit(
+        struct copybit_device_t *dev,
+        int name,
+        int value)
+{
+    struct copybit_context_t* ctx = (struct copybit_context_t*)dev;
+    if (!ctx) {
+        LOGE("%s: null context", __func__);
+        return -EINVAL;
+    }
+
+    switch(name) {
+    case COPYBIT_ROTATION_DEG:
+        ctx->blitState.rotation = value<<16;
+        /* SRC rotation */
+        if(!value)
+            ctx->blitState.config_mask &=~C2D_ROTATE_BIT;;
+        break;
+    case COPYBIT_PLANE_ALPHA:
+        if (value < 0)      value = 0;
+        if (value >= 256)   value = 255;
+
+        ctx->blitState.global_alpha = value;
+
+        if(ctx->blitState.global_alpha<255)
+            ctx->blitState.config_mask |= C2D_GLOBAL_ALPHA_BIT;
+        else
+            ctx->blitState.config_mask &=~C2D_GLOBAL_ALPHA_BIT;
+        break;
+    case COPYBIT_DITHER:
+        /* TODO */
+        break;
+    case COPYBIT_BLUR:
+        /* TODO */
+        break;
+    case COPYBIT_TRANSFORM:
+        ctx->blitState.config_mask &=~C2D_ROTATE_BIT;
+        ctx->blitState.config_mask &=~C2D_MIRROR_H_BIT;
+        ctx->blitState.config_mask &=~C2D_MIRROR_V_BIT;
+        ctx->trg_transform = C2D_TARGET_ROTATE_0;
+
+        if((value&0x7) == COPYBIT_TRANSFORM_ROT_180)
+            ctx->trg_transform = C2D_TARGET_ROTATE_180;
+        else if((value&0x7) == COPYBIT_TRANSFORM_ROT_270)
+            ctx->trg_transform = C2D_TARGET_ROTATE_90;
+        else {
+            if(value&COPYBIT_TRANSFORM_FLIP_H)
+                ctx->blitState.config_mask |= C2D_MIRROR_H_BIT;
+            if(value&COPYBIT_TRANSFORM_FLIP_V)
+                ctx->blitState.config_mask |= C2D_MIRROR_V_BIT;
+            if(value&COPYBIT_TRANSFORM_ROT_90)
+                ctx->trg_transform = C2D_TARGET_ROTATE_270;
+        }
+        break;
+    case COPYBIT_PREMULTIPLIED_ALPHA:
+        (value == COPYBIT_ENABLE) ? ctx->isPremultipliedAlpha = true :
+                                    ctx->isPremultipliedAlpha = false;
+        break;
+    default:
+        LOGE("%s: default case", __func__);
+        return -EINVAL;
+        break;
+    }
+
+    return COPYBIT_SUCCESS;
+}
+
+/** Get a static info value */
+static int get(struct copybit_device_t *dev, int name)
+{
+    struct copybit_context_t* ctx = (struct copybit_context_t*)dev;
+    int value;
+
+    if (!ctx) {
+        LOGE("%s: null context error", __func__);
+        return -EINVAL;
+    }
+
+    switch(name) {
+    case COPYBIT_MINIFICATION_LIMIT:
+        value = MAX_SCALE_FACTOR;
+        break;
+    case COPYBIT_MAGNIFICATION_LIMIT:
+        value = MAX_SCALE_FACTOR;
+        break;
+    case COPYBIT_SCALING_FRAC_BITS:
+        value = 32;
+        break;
+    case COPYBIT_ROTATION_STEP_DEG:
+        value = 1;
+        break;
+    default:
+        LOGE("%s: default case", __func__);
+        value = -EINVAL;
+    }
+    return value;
+}
+
+static int is_alpha(int cformat)
+{
+    int alpha = 0;
+    switch (cformat & 0xFF) {
+    case C2D_COLOR_FORMAT_8888_ARGB:
+    case C2D_COLOR_FORMAT_8888_RGBA:
+    case C2D_COLOR_FORMAT_5551_RGBA:
+    case C2D_COLOR_FORMAT_4444_ARGB:
+        alpha = 1;
+        break;
+    default:
+        alpha = 0;
+        break;
+    }
+
+    if(alpha && (cformat&C2D_FORMAT_DISABLE_ALPHA))
+        alpha = 0;
+
+    return alpha;
+}
+
+/** do a stretch blit type operation */
+static int stretch_copybit_internal(
+        struct copybit_device_t *dev,
+        struct copybit_image_t const *dst,
+        struct copybit_image_t const *src,
+        struct copybit_rect_t const *dst_rect,
+        struct copybit_rect_t const *src_rect,
+        struct copybit_region_t const *region,
+        bool enableBlend)
+{
+    struct copybit_context_t* ctx = (struct copybit_context_t*)dev;
+    int status = COPYBIT_SUCCESS;
+    uint32 maxCount;
+    uint32 src_mapped = 0, trg_mapped = 0;
+    blitlist list;
+    C2D_OBJECT *req;
+    memset(&list, 0, sizeof(list));
+    int cformat;
+    c2d_ts_handle timestamp;
+    uint32 surface_index = 0;
+
+    if (!ctx) {
+        LOGE("%s: null context error", __func__);
+        return -EINVAL;
+    }
+
+    if (src->w > MAX_DIMENSION || src->h > MAX_DIMENSION) {
+        LOGE("%s: src dimension error", __func__);
+        return -EINVAL;
+    }
+
+    if (dst->w > MAX_DIMENSION || dst->h > MAX_DIMENSION) {
+        LOGE("%s : dst dimension error dst w %d h %d",  __func__, dst->w, dst->h);
+        return -EINVAL;
+    }
+
+    maxCount = sizeof(list.blitObjects)/sizeof(C2D_OBJECT);
+
+    struct copybit_rect_t clip;
+    list.count = 0;
+
+    status = set_image(ctx->g12_device_fd, ctx->dst, dst, &cformat, &trg_mapped, ctx->isPremultipliedAlpha);
+    if(status) {
+        LOGE("%s: set_image error", __func__);
+        return COPYBIT_FAILURE;
+    }
+
+    if(is_supported_rgb_format(src->format) == COPYBIT_SUCCESS) {
+        surface_index = RGB_SURFACE;
+    } else if (is_supported_yuv_format(src->format) == COPYBIT_SUCCESS) {
+        surface_index = YUV_SURFACE;
+    } else {
+        LOGE("%s: Invalid source surface format %x", __func__, src->format);
+        return -EINVAL;
+    }
+
+    status = set_image(ctx->g12_device_fd, ctx->src[surface_index], src, &cformat, &src_mapped, ctx->isPremultipliedAlpha);
+    if(status) {
+        LOGE("%s: set_src_image error", __func__);
+        return COPYBIT_FAILURE;
+    }
+
+    if (enableBlend) {
+        if(ctx->blitState.config_mask & C2D_GLOBAL_ALPHA_BIT) {
+            ctx->blitState.config_mask &= ~C2D_ALPHA_BLEND_NONE;
+            if(!(ctx->blitState.global_alpha)) {
+                // src alpha is zero
+                unset_image(ctx->g12_device_fd, ctx->src[surface_index], src, src_mapped);
+                unset_image(ctx->g12_device_fd, ctx->dst, dst, trg_mapped);
+                return status;
+            }
+        } else {
+            if(is_alpha(cformat))
+                ctx->blitState.config_mask &= ~C2D_ALPHA_BLEND_NONE;
+            else
+                ctx->blitState.config_mask |= C2D_ALPHA_BLEND_NONE;
+        }
+    } else {
+        ctx->blitState.config_mask |= C2D_ALPHA_BLEND_NONE;
+    }
+
+    ctx->blitState.surface_id = ctx->src[surface_index];
+
+    while ((status == 0) && region->next(region, &clip)) {
+        req = &(list.blitObjects[list.count]);
+        memcpy(req,&ctx->blitState,sizeof(C2D_OBJECT));
+
+        set_rects(ctx, req, dst_rect, src_rect, &clip);
+
+        if (++list.count == maxCount) {
+            status = msm_copybit(ctx, &list, ctx->dst);
+            list.count = 0;
+        }
+    }
+    if ((status == 0) && list.count) {
+        status = msm_copybit(ctx, &list, ctx->dst);
+    }
+
+    if(LINK_c2dFinish(ctx->dst)) {
+        LOGE("%s: LINK_c2dFinish ERROR", __func__);
+    }
+
+
+    unset_image(ctx->g12_device_fd, ctx->src[surface_index], src, src_mapped);
+    unset_image(ctx->g12_device_fd, ctx->dst, dst, trg_mapped);
+    ctx->isPremultipliedAlpha = false;
+    return status;
+}
+
+static int stretch_copybit(
+        struct copybit_device_t *dev,
+        struct copybit_image_t const *dst,
+        struct copybit_image_t const *src,
+        struct copybit_rect_t const *dst_rect,
+        struct copybit_rect_t const *src_rect,
+        struct copybit_region_t const *region)
+{
+    return stretch_copybit_internal(dev, dst, src, dst_rect, src_rect, region, true);
+}
+
+/** Perform a blit type operation */
+static int blit_copybit(
+        struct copybit_device_t *dev,
+        struct copybit_image_t const *dst,
+        struct copybit_image_t const *src,
+        struct copybit_region_t const *region)
+{
+    struct copybit_rect_t dr = { 0, 0, dst->w, dst->h };
+    struct copybit_rect_t sr = { 0, 0, src->w, src->h };
+    return stretch_copybit_internal(dev, dst, src, &dr, &sr, region, false);
+}
+
+/*****************************************************************************/
+
+/** Close the copybit device */
+static int close_copybit(struct hw_device_t *dev)
+{
+    struct copybit_context_t* ctx = (struct copybit_context_t*)dev;
+    if (ctx) {
+        LINK_c2dDestroySurface(ctx->dst);
+        for(int i = 0; i <NUM_SRC_SURFACES; i++) {
+            LINK_c2dDestroySurface(ctx->src[i]);
+        }
+
+        if (ctx->libc2d2) {
+           ::dlclose(ctx->libc2d2);
+           LOGV("dlclose(libc2d2)");
+        }
+
+        if(ctx->g12_device_fd)
+          close(ctx->g12_device_fd);
+        free(ctx);
+    }
+
+    return 0;
+}
+
+/** Open a new instance of a copybit device using name */
+static int open_copybit(const struct hw_module_t* module, const char* name,
+        struct hw_device_t** device)
+{
+    int status = COPYBIT_SUCCESS;
+    C2D_RGB_SURFACE_DEF surfDefinition = {0};
+    C2D_YUV_SURFACE_DEF yuvSurfaceDef = {0} ;
+    struct copybit_context_t *ctx;
+    char const * const device_template[] = {
+            "/dev/graphics/fb%u",
+            "/dev/fb%u",
+            0 };
+
+    int fd = -1;
+    int i=0;
+    char fbName[64];
+
+    ctx = (struct copybit_context_t *)malloc(sizeof(struct copybit_context_t));
+    if(!ctx) {
+        LOGE("%s: malloc failed", __func__);
+        return COPYBIT_FAILURE;
+    }
+
+    /* initialize drawstate */
+    memset(ctx, 0, sizeof(*ctx));
+
+    ctx->libc2d2 = ::dlopen("libC2D2.so", RTLD_NOW);
+    if (!ctx->libc2d2) {
+        LOGE("FATAL ERROR: could not dlopen libc2d2.so: %s", dlerror());
+        goto error;
+    }
+    *(void **)&LINK_c2dCreateSurface = ::dlsym(ctx->libc2d2,
+                                               "c2dCreateSurface");
+    *(void **)&LINK_c2dUpdateSurface = ::dlsym(ctx->libc2d2,
+                                               "c2dUpdateSurface");
+    *(void **)&LINK_c2dReadSurface = ::dlsym(ctx->libc2d2,
+                                               "c2dReadSurface");
+    *(void **)&LINK_c2dDraw = ::dlsym(ctx->libc2d2, "c2dDraw");
+    *(void **)&LINK_c2dFlush = ::dlsym(ctx->libc2d2, "c2dFlush");
+    *(void **)&LINK_c2dFinish = ::dlsym(ctx->libc2d2, "c2dFinish");
+    *(void **)&LINK_c2dWaitTimestamp = ::dlsym(ctx->libc2d2,
+                                               "c2dWaitTimestamp");
+    *(void **)&LINK_c2dDestroySurface = ::dlsym(ctx->libc2d2,
+                                                "c2dDestroySurface");
+
+    if(!LINK_c2dCreateSurface || !LINK_c2dUpdateSurface || !LINK_c2dReadSurface
+       || !LINK_c2dDraw || !LINK_c2dFlush || !LINK_c2dWaitTimestamp || !LINK_c2dFinish
+       || !LINK_c2dDestroySurface) {
+        LOGE("%s: dlsym ERROR", __func__);
+        goto error1;
+    }
+
+    ctx->device.common.tag = HARDWARE_DEVICE_TAG;
+    ctx->device.common.version = 1;
+    ctx->device.common.module = (hw_module_t*)(module);
+    ctx->device.common.close = close_copybit;
+    ctx->device.set_parameter = set_parameter_copybit;
+    ctx->device.get = get;
+    ctx->device.blit = blit_copybit;
+    ctx->device.stretch = stretch_copybit;
+    ctx->blitState.config_mask = C2D_NO_BILINEAR_BIT | C2D_NO_ANTIALIASING_BIT;
+    ctx->trg_transform = C2D_TARGET_ROTATE_0;
+    ctx->g12_device_fd = open(G12_DEVICE_NAME, O_RDWR | O_SYNC);
+    if(ctx->g12_device_fd < 0) {
+      LOGE("%s: g12_device_fd open failed", __func__);
+        goto error1;
+    }
+
+    /* Create RGB Surface */
+    surfDefinition.buffer = (void*)0xdddddddd;
+    surfDefinition.phys = (void*)0xdddddddd;
+    surfDefinition.stride = 1 * 4;
+    surfDefinition.width = 1;
+    surfDefinition.height = 1;
+    surfDefinition.format = C2D_COLOR_FORMAT_8888_ARGB;
+
+    if(LINK_c2dCreateSurface(&ctx->dst,C2D_TARGET | C2D_SOURCE,
+                             (C2D_SURFACE_TYPE)(C2D_SURFACE_RGB_HOST |
+                             C2D_SURFACE_WITH_PHYS), &surfDefinition)) {
+        LOGE("%s: create ctx->dst failed", __func__);
+        goto error2;
+    }
+
+    if(LINK_c2dCreateSurface(&(ctx->src[RGB_SURFACE]), C2D_TARGET | C2D_SOURCE,
+                             (C2D_SURFACE_TYPE)(C2D_SURFACE_RGB_HOST |
+                             C2D_SURFACE_WITH_PHYS), &surfDefinition)) {
+        LOGE("%s: create ctx->src[RGB_SURFACE] failed", __func__);
+        goto error3;
+    }
+
+    /* Create YUV source surface */
+    yuvSurfaceDef.format = C2D_COLOR_FORMAT_420_NV12;
+
+    yuvSurfaceDef.width = 4;
+    yuvSurfaceDef.height = 4;
+    yuvSurfaceDef.plane0 = (void*)0xaaaaaaaa;
+    yuvSurfaceDef.phys0 = (void*) 0xaaaaaaaa;
+    yuvSurfaceDef.stride0 = 4;
+
+    yuvSurfaceDef.plane1 = (void*)0xaaaaaaaa;
+    yuvSurfaceDef.phys1 = (void*) 0xaaaaaaaa;
+    yuvSurfaceDef.stride1 = 4;
+
+    if(LINK_c2dCreateSurface(&(ctx->src[YUV_SURFACE]),C2D_TARGET | C2D_SOURCE,
+                             (C2D_SURFACE_TYPE)(C2D_SURFACE_YUV_HOST | C2D_SURFACE_WITH_PHYS),
+                             &yuvSurfaceDef)) {
+        LOGE("%s: create ctx->src[YUV_SURFACE] failed", __func__);
+        goto error4;
+    }
+
+    *device = &ctx->device.common;
+
+    while ((fd==-1) && device_template[i]) {
+        snprintf(fbName, 64, device_template[i], 0);
+        fd = open(fbName, O_RDWR, 0);
+        i++;
+    }
+    if (fd < 0)
+        goto error5;
+
+    struct fb_var_screeninfo info;
+    if (ioctl(fd, FBIOGET_VSCREENINFO, &info) == -1)
+        goto error6;
+
+    ctx->fb_width = info.xres;
+    ctx->fb_height = info.yres;
+    close(fd);
+    ctx->isPremultipliedAlpha = false;
+    return status;
+
+error6:
+    close(fd);
+    fd = -1;
+error5:
+    LINK_c2dDestroySurface(ctx->src[YUV_SURFACE]);
+error4:
+    LINK_c2dDestroySurface(ctx->src[RGB_SURFACE]);
+error3:
+    LINK_c2dDestroySurface(ctx->dst);
+error2:
+    close(ctx->g12_device_fd);
+error1:
+    ::dlclose(ctx->libc2d2);
+error:
+    free(ctx);
+    status = COPYBIT_FAILURE;
+    *device = NULL;
+
+    return status;
+}
diff --git a/libgralloc-qsd8k/Android.mk b/libgralloc-qsd8k/Android.mk
new file mode 100644
index 0000000..1157e9f
--- /dev/null
+++ b/libgralloc-qsd8k/Android.mk
@@ -0,0 +1,66 @@
+# Copyright (C) 2008 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+ifneq ($(TARGET_USES_ION),true)
+LOCAL_PATH := $(call my-dir)
+
+# HAL module implemenation, not prelinked and stored in
+# hw/<OVERLAY_HARDWARE_MODULE_ID>.<ro.product.board>.so
+include $(CLEAR_VARS)
+LOCAL_PRELINK_MODULE := false
+LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw
+LOCAL_SHARED_LIBRARIES := liblog libcutils libGLESv1_CM libutils
+
+LOCAL_C_INCLUDES += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr/include \
+                    hardware/qcom/display/libgralloc
+LOCAL_ADDITIONAL_DEPENDENCIES += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr
+LOCAL_SRC_FILES := 	\
+	allocator.cpp 	\
+	framebuffer.cpp \
+	gpu.cpp			\
+	gralloc.cpp		\
+	mapper.cpp		\
+	pmemalloc.cpp
+	
+LOCAL_MODULE := gralloc.$(TARGET_BOARD_PLATFORM)
+LOCAL_CFLAGS:= -DLOG_TAG=\"$(TARGET_BOARD_PLATFORM).gralloc\" -DHOST -DDEBUG_CALC_FPS
+
+ifneq (, $(filter msm7625_ffa msm7625_surf msm7627_ffa msm7627_surf msm7627_7x_ffa msm7627_7x_surf, $(QCOM_TARGET_PRODUCT)))
+LOCAL_CFLAGS += -DTARGET_MSM7x27
+endif
+
+ifeq ($(TARGET_HAVE_HDMI_OUT),true)
+LOCAL_CFLAGS += -DHDMI_DUAL_DISPLAY
+LOCAL_C_INCLUDES += $(LOCAL_PATH)/../liboverlay
+LOCAL_SHARED_LIBRARIES += liboverlay
+endif
+
+ifeq ($(TARGET_GRALLOC_USES_ASHMEM),true)
+LOCAL_CFLAGS += -DUSE_ASHMEM
+endif
+include $(BUILD_SHARED_LIBRARY)
+
+
+# Build a host library for testing
+ifeq ($(HOST_OS),linux)
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES :=		\
+    gpu.cpp				\
+	pmemalloc.cpp
+
+LOCAL_MODULE_TAGS := tests
+LOCAL_MODULE := libgralloc_qsd8k_host
+LOCAL_CFLAGS:= -DLOG_TAG=\"gralloc-qsd8k\"
+include $(BUILD_HOST_STATIC_LIBRARY)
+endif
+endif
diff --git a/libgralloc-qsd8k/MODULE_LICENSE_APACHE2 b/libgralloc-qsd8k/MODULE_LICENSE_APACHE2
new file mode 100644
index 0000000..e69de29
diff --git a/libgralloc-qsd8k/NOTICE b/libgralloc-qsd8k/NOTICE
new file mode 100644
index 0000000..3237da6
--- /dev/null
+++ b/libgralloc-qsd8k/NOTICE
@@ -0,0 +1,190 @@
+
+   Copyright (c) 2008-2009, The Android Open Source Project
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
diff --git a/libgralloc-qsd8k/allocator.cpp b/libgralloc-qsd8k/allocator.cpp
new file mode 100644
index 0000000..e7645b1
--- /dev/null
+++ b/libgralloc-qsd8k/allocator.cpp
@@ -0,0 +1,165 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <cutils/log.h>
+
+#include "allocator.h"
+
+
+// align all the memory blocks on a cache-line boundary
+const int SimpleBestFitAllocator::kMemoryAlign = 32;
+
+SimpleBestFitAllocator::SimpleBestFitAllocator()
+    : mHeapSize(0)
+{
+}
+
+SimpleBestFitAllocator::SimpleBestFitAllocator(size_t size)
+    : mHeapSize(0)
+{
+    setSize(size);
+}
+
+SimpleBestFitAllocator::~SimpleBestFitAllocator()
+{
+    while(!mList.isEmpty()) {
+        delete mList.remove(mList.head());
+    }
+}
+
+ssize_t SimpleBestFitAllocator::setSize(size_t size)
+{
+    Locker::Autolock _l(mLock);
+    if (mHeapSize != 0) return -EINVAL;
+    size_t pagesize = getpagesize();
+    mHeapSize = ((size + pagesize-1) & ~(pagesize-1));
+    chunk_t* node = new chunk_t(0, mHeapSize / kMemoryAlign);
+    mList.insertHead(node);
+    return size;
+}
+    
+    
+size_t SimpleBestFitAllocator::size() const
+{
+    return mHeapSize;
+}
+
+ssize_t SimpleBestFitAllocator::allocate(size_t size, uint32_t flags)
+{
+    Locker::Autolock _l(mLock);
+    if (mHeapSize == 0) return -EINVAL;
+    ssize_t offset = alloc(size, flags);
+    return offset;
+}
+
+ssize_t SimpleBestFitAllocator::deallocate(size_t offset)
+{
+    Locker::Autolock _l(mLock);
+    if (mHeapSize == 0) return -EINVAL;
+    chunk_t const * const freed = dealloc(offset);
+    if (freed) {
+        return 0;
+    }
+    return -ENOENT;
+}
+
+ssize_t SimpleBestFitAllocator::alloc(size_t size, uint32_t flags)
+{
+    if (size == 0) {
+        return 0;
+    }
+    size = (size + kMemoryAlign-1) / kMemoryAlign;
+    chunk_t* free_chunk = 0;
+    chunk_t* cur = mList.head();
+
+    size_t pagesize = getpagesize();
+    while (cur) {
+        int extra = ( -cur->start & ((pagesize/kMemoryAlign)-1) ) ;
+
+        // best fit
+        if (cur->free && (cur->size >= (size+extra))) {
+            if ((!free_chunk) || (cur->size < free_chunk->size)) {
+                free_chunk = cur;
+            }
+            if (cur->size == size) {
+                break;
+            }
+        }
+        cur = cur->next;
+    }
+
+    if (free_chunk) {
+        const size_t free_size = free_chunk->size;
+        free_chunk->free = 0;
+        free_chunk->size = size;
+        if (free_size > size) {
+            int extra = ( -free_chunk->start & ((pagesize/kMemoryAlign)-1) ) ;
+            if (extra) {
+                chunk_t* split = new chunk_t(free_chunk->start, extra);
+                free_chunk->start += extra;
+                mList.insertBefore(free_chunk, split);
+            }
+
+            LOGE_IF(((free_chunk->start*kMemoryAlign)&(pagesize-1)),
+                    "page is not aligned!!!");
+
+            const ssize_t tail_free = free_size - (size+extra);
+            if (tail_free > 0) {
+                chunk_t* split = new chunk_t(
+                        free_chunk->start + free_chunk->size, tail_free);
+                mList.insertAfter(free_chunk, split);
+            }
+        }
+        return (free_chunk->start)*kMemoryAlign;
+    }
+    return -ENOMEM;
+}
+
+SimpleBestFitAllocator::chunk_t* SimpleBestFitAllocator::dealloc(size_t start)
+{
+    start = start / kMemoryAlign;
+    chunk_t* cur = mList.head();
+    while (cur) {
+        if (cur->start == start) {
+            LOG_FATAL_IF(cur->free,
+                "block at offset 0x%08lX of size 0x%08lX already freed",
+                cur->start*kMemoryAlign, cur->size*kMemoryAlign);
+
+            // merge freed blocks together
+            chunk_t* freed = cur;
+            cur->free = 1;
+            do {
+                chunk_t* const p = cur->prev;
+                chunk_t* const n = cur->next;
+                if (p && (p->free || !cur->size)) {
+                    freed = p;
+                    p->size += cur->size;
+                    mList.remove(cur);
+                    delete cur;
+                }
+                cur = n;
+            } while (cur && cur->free);
+
+            LOG_FATAL_IF(!freed->free,
+                "freed block at offset 0x%08lX of size 0x%08lX is not free!",
+                freed->start * kMemoryAlign, freed->size * kMemoryAlign);
+
+            return freed;
+        }
+        cur = cur->next;
+    }
+    return 0;
+}
diff --git a/libgralloc-qsd8k/allocator.h b/libgralloc-qsd8k/allocator.h
new file mode 100644
index 0000000..dc81f51
--- /dev/null
+++ b/libgralloc-qsd8k/allocator.h
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+#ifndef GRALLOC_ALLOCATOR_H_
+#define GRALLOC_ALLOCATOR_H_
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include "gr.h"
+#include "pmemalloc.h"
+
+// ----------------------------------------------------------------------------
+
+/*
+ * A simple templatized doubly linked-list implementation
+ */
+
+template <typename NODE>
+class LinkedList
+{
+    NODE*  mFirst;
+    NODE*  mLast;
+
+public:
+                LinkedList() : mFirst(0), mLast(0) { }
+    bool        isEmpty() const { return mFirst == 0; }
+    NODE const* head() const { return mFirst; }
+    NODE*       head() { return mFirst; }
+    NODE const* tail() const { return mLast; }
+    NODE*       tail() { return mLast; }
+
+    void insertAfter(NODE* node, NODE* newNode) {
+        newNode->prev = node;
+        newNode->next = node->next;
+        if (node->next == 0) mLast = newNode;
+        else                 node->next->prev = newNode;
+        node->next = newNode;
+    }
+
+    void insertBefore(NODE* node, NODE* newNode) {
+         newNode->prev = node->prev;
+         newNode->next = node;
+         if (node->prev == 0)   mFirst = newNode;
+         else                   node->prev->next = newNode;
+         node->prev = newNode;
+    }
+
+    void insertHead(NODE* newNode) {
+        if (mFirst == 0) {
+            mFirst = mLast = newNode;
+            newNode->prev = newNode->next = 0;
+        } else {
+            newNode->prev = 0;
+            newNode->next = mFirst;
+            mFirst->prev = newNode;
+            mFirst = newNode;
+        }
+    }
+    
+    void insertTail(NODE* newNode) {
+        if (mLast == 0) {
+            insertHead(newNode);
+        } else {
+            newNode->prev = mLast;
+            newNode->next = 0;
+            mLast->next = newNode;
+            mLast = newNode;
+        }
+    }
+
+    NODE* remove(NODE* node) {
+        if (node->prev == 0)    mFirst = node->next;
+        else                    node->prev->next = node->next;
+        if (node->next == 0)    mLast = node->prev;
+        else                    node->next->prev = node->prev;
+        return node;
+    }
+};
+
+class SimpleBestFitAllocator : public PmemUserspaceAllocator::Deps::Allocator
+{
+public:
+
+    SimpleBestFitAllocator();
+    SimpleBestFitAllocator(size_t size);
+    virtual ~SimpleBestFitAllocator();
+
+    virtual ssize_t setSize(size_t size);
+
+    virtual ssize_t allocate(size_t size, uint32_t flags = 0);
+    virtual ssize_t deallocate(size_t offset);
+    virtual size_t  size() const;
+
+private:
+    struct chunk_t {
+        chunk_t(size_t start, size_t size) 
+            : start(start), size(size), free(1), prev(0), next(0) {
+        }
+        size_t              start;
+        size_t              size : 28;
+        int                 free : 4;
+        mutable chunk_t*    prev;
+        mutable chunk_t*    next;
+    };
+
+    ssize_t  alloc(size_t size, uint32_t flags);
+    chunk_t* dealloc(size_t start);
+
+    static const int    kMemoryAlign;
+    mutable Locker      mLock;
+    LinkedList<chunk_t> mList;
+    size_t              mHeapSize;
+};
+
+#endif /* GRALLOC_ALLOCATOR_H_ */
diff --git a/libgralloc-qsd8k/framebuffer.cpp b/libgralloc-qsd8k/framebuffer.cpp
new file mode 100644
index 0000000..dc51e08
--- /dev/null
+++ b/libgralloc-qsd8k/framebuffer.cpp
@@ -0,0 +1,1130 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * Copyright (c) 2010-2011 Code Aurora Forum. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <sys/mman.h>
+
+#include <dlfcn.h>
+
+#include <cutils/ashmem.h>
+#include <cutils/log.h>
+#include <cutils/properties.h>
+#include <utils/Timers.h>
+
+#include <hardware/hardware.h>
+#include <hardware/gralloc.h>
+
+#include <fcntl.h>
+#include <errno.h>
+#include <sys/ioctl.h>
+#include <string.h>
+#include <stdlib.h>
+#include <pthread.h>
+#include <utils/Timers.h>
+
+#include <cutils/log.h>
+#include <cutils/atomic.h>
+
+#include <linux/fb.h>
+#include <linux/msm_mdp.h>
+
+#include <GLES/gl.h>
+
+#include "gralloc_priv.h"
+#include "gr.h"
+#ifdef NO_SURFACEFLINGER_SWAPINTERVAL
+#include <cutils/properties.h>
+#endif
+
+#define FB_DEBUG 0
+
+#if defined(HDMI_DUAL_DISPLAY)
+#define AS_1080_RATIO_H (4.25/100)  // Default Action Safe vertical limit for 1080p
+#define AS_1080_RATIO_W (4.25/100)  // Default Action Safe horizontal limit for 1080p
+#define AS_720_RATIO_H (6.0/100)  // Default Action Safe vertical limit for 720p
+#define AS_720_RATIO_W (4.25/100)  // Default Action Safe horizontal limit for 720p
+#define AS_480_RATIO_H (8.0/100)  // Default Action Safe vertical limit for 480p
+#define AS_480_RATIO_W (5.0/100)  // Default Action Safe horizontal limit for 480p
+#define HEIGHT_1080P 1080
+#define HEIGHT_720P 720
+#define HEIGHT_480P 480
+#define EVEN_OUT(x) if (x & 0x0001) {x--;}
+using overlay::Overlay;
+/** min of int a, b */
+static inline int min(int a, int b) {
+    return (a<b) ? a : b;
+}
+/** max of int a, b */
+static inline int max(int a, int b) {
+    return (a>b) ? a : b;
+}
+/** align */
+static inline size_t ALIGN(size_t x, size_t align) {
+    return (x + align-1) & ~(align-1);
+}
+#endif
+
+char framebufferStateName[] = {'S', 'R', 'A'};
+
+#ifdef DEBUG_CALC_FPS
+
+#define MAX_FPS_CALC_PERIOD_IN_FRAMES 128
+#define MAX_FRAMARRIVAL_STEPS          50
+#define MAX_DEBUG_FPS_LEVEL             2
+
+struct debug_fps_metadata_t {
+    /*fps calculation based on time or number of frames*/
+    enum DfmType {
+      DFM_FRAMES = 0,
+      DFM_TIME   = 1,
+    };
+
+    DfmType type;
+
+    /* indicates how much time do we wait till we calculate FPS */
+    unsigned long time_period;
+
+    /*indicates how much time elapsed since we report fps*/
+    float time_elapsed;
+
+    /* indicates how many frames do we wait till we calculate FPS */
+    unsigned int period;
+    /* current frame, will go upto period, and then reset */
+    unsigned int curr_frame;
+    /* frame will arrive at a multiple of 16666 us at the display.
+       This indicates how many steps to consider for our calculations.
+       For example, if framearrival_steps = 10, then the frame that arrived
+       after 166660 us or more will be ignored.
+    */
+    unsigned int framearrival_steps;
+    /* ignorethresh_us = framearrival_steps * 16666 */
+    nsecs_t      ignorethresh_us;
+    /* used to calculate the actual frame arrival step, the times might not be
+       accurate
+    */
+    unsigned int margin_us;
+    /* actual data storage */
+    nsecs_t      framearrivals[MAX_FPS_CALC_PERIOD_IN_FRAMES];
+    nsecs_t      accum_framearrivals[MAX_FRAMARRIVAL_STEPS];
+};
+
+#endif
+
+/*****************************************************************************/
+
+enum {
+    MDDI_PANEL = '1',
+    EBI2_PANEL = '2',
+    LCDC_PANEL = '3',
+    EXT_MDDI_PANEL = '4',
+    TV_PANEL = '5'
+};
+
+enum {
+    PAGE_FLIP = 0x00000001,
+    LOCKED = 0x00000002
+};
+
+struct fb_context_t {
+    framebuffer_device_t  device;
+};
+
+static int neworientation;
+
+#ifdef DEBUG_CALC_FPS
+static debug_fps_metadata_t debug_fps_metadata;
+static unsigned int debug_fps_level = 0;
+#endif
+
+/*****************************************************************************/
+
+static void
+msm_copy_buffer(buffer_handle_t handle, int fd,
+                int width, int height, int format,
+                int x, int y, int w, int h);
+
+static int fb_setSwapInterval(struct framebuffer_device_t* dev,
+            int interval)
+{
+    fb_context_t* ctx = (fb_context_t*)dev;
+    private_module_t* m = reinterpret_cast<private_module_t*>(
+            dev->common.module);
+    if (interval < dev->minSwapInterval || interval > dev->maxSwapInterval)
+        return -EINVAL;
+
+    m->swapInterval = interval;
+    return 0;
+}
+
+static int fb_setUpdateRect(struct framebuffer_device_t* dev,
+        int l, int t, int w, int h)
+{
+    if (((w|h) <= 0) || ((l|t)<0))
+        return -EINVAL;
+        
+    fb_context_t* ctx = (fb_context_t*)dev;
+    private_module_t* m = reinterpret_cast<private_module_t*>(
+            dev->common.module);
+    m->info.reserved[0] = 0x54445055; // "UPDT";
+    m->info.reserved[1] = (uint16_t)l | ((uint32_t)t << 16);
+    m->info.reserved[2] = (uint16_t)(l+w) | ((uint32_t)(t+h) << 16);
+    return 0;
+}
+
+#ifdef DEBUG_CALC_FPS
+
+static void populate_debug_fps_metadata(void)
+{
+    char prop[PROPERTY_VALUE_MAX];
+
+    /*defaults calculation of fps to based on number of frames*/
+    property_get("debug.gr.calcfps.type", prop, "0");
+    debug_fps_metadata.type = (debug_fps_metadata_t::DfmType) atoi(prop);
+
+    /*defaults to 1000ms*/
+    property_get("debug.gr.calcfps.timeperiod", prop, "1000");
+    debug_fps_metadata.time_period = atoi(prop);
+
+    property_get("debug.gr.calcfps.period", prop, "10");
+    debug_fps_metadata.period = atoi(prop);
+
+    if (debug_fps_metadata.period > MAX_FPS_CALC_PERIOD_IN_FRAMES) {
+        debug_fps_metadata.period = MAX_FPS_CALC_PERIOD_IN_FRAMES;
+    }
+
+    /* default ignorethresh_us: 500 milli seconds */
+    property_get("debug.gr.calcfps.ignorethresh_us", prop, "500000");
+    debug_fps_metadata.ignorethresh_us = atoi(prop);
+
+    debug_fps_metadata.framearrival_steps =
+                       (debug_fps_metadata.ignorethresh_us / 16666);
+
+    if (debug_fps_metadata.framearrival_steps > MAX_FRAMARRIVAL_STEPS) {
+        debug_fps_metadata.framearrival_steps = MAX_FRAMARRIVAL_STEPS;
+        debug_fps_metadata.ignorethresh_us =
+                        debug_fps_metadata.framearrival_steps * 16666;
+    }
+
+    /* 2ms margin of error for the gettimeofday */
+    debug_fps_metadata.margin_us = 2000;
+
+    for (int i = 0; i < MAX_FRAMARRIVAL_STEPS; i++)
+        debug_fps_metadata.accum_framearrivals[i] = 0;
+
+    LOGE("period: %d", debug_fps_metadata.period);
+    LOGE("ignorethresh_us: %lld", debug_fps_metadata.ignorethresh_us);
+}
+
+static void print_fps(float fps)
+{
+    if (debug_fps_metadata_t::DFM_FRAMES == debug_fps_metadata.type)
+        LOGE("FPS for last %d frames: %3.2f", debug_fps_metadata.period, fps);
+    else
+        LOGE("FPS for last (%f ms, %d frames): %3.2f",
+             debug_fps_metadata.time_elapsed,
+             debug_fps_metadata.curr_frame, fps);
+
+    debug_fps_metadata.curr_frame = 0;
+    debug_fps_metadata.time_elapsed = 0.0;
+
+    if (debug_fps_level > 1) {
+        LOGE("Frame Arrival Distribution:");
+        for (unsigned int i = 0;
+             i < ((debug_fps_metadata.framearrival_steps / 6) + 1);
+             i++) {
+            LOGE("%lld %lld %lld %lld %lld %lld",
+                 debug_fps_metadata.accum_framearrivals[i*6],
+                 debug_fps_metadata.accum_framearrivals[i*6+1],
+                 debug_fps_metadata.accum_framearrivals[i*6+2],
+                 debug_fps_metadata.accum_framearrivals[i*6+3],
+                 debug_fps_metadata.accum_framearrivals[i*6+4],
+                 debug_fps_metadata.accum_framearrivals[i*6+5]);
+        }
+
+        /* We are done with displaying, now clear the stats */
+        for (unsigned int i = 0;
+             i < debug_fps_metadata.framearrival_steps;
+             i++)
+            debug_fps_metadata.accum_framearrivals[i] = 0;
+    }
+    return;
+}
+
+static void calc_fps(nsecs_t currtime_us)
+{
+    static nsecs_t oldtime_us = 0;
+
+    nsecs_t diff = currtime_us - oldtime_us;
+
+    oldtime_us = currtime_us;
+
+    if (debug_fps_metadata_t::DFM_FRAMES == debug_fps_metadata.type &&
+        diff > debug_fps_metadata.ignorethresh_us) {
+        return;
+    }
+
+    if (debug_fps_metadata.curr_frame < MAX_FPS_CALC_PERIOD_IN_FRAMES) {
+        debug_fps_metadata.framearrivals[debug_fps_metadata.curr_frame++] = diff;
+    }
+
+    if (debug_fps_level > 1) {
+        unsigned int currstep = (diff + debug_fps_metadata.margin_us) / 16666;
+
+        if (currstep < debug_fps_metadata.framearrival_steps) {
+            debug_fps_metadata.accum_framearrivals[currstep-1]++;
+        }
+    }
+
+    if (debug_fps_metadata_t::DFM_FRAMES == debug_fps_metadata.type) {
+        if (debug_fps_metadata.curr_frame == debug_fps_metadata.period) {
+            /* time to calculate and display FPS */
+            nsecs_t sum = 0;
+            for (unsigned int i = 0; i < debug_fps_metadata.period; i++)
+                sum += debug_fps_metadata.framearrivals[i];
+            print_fps((debug_fps_metadata.period * float(1000000))/float(sum));
+        }
+    }
+    else if (debug_fps_metadata_t::DFM_TIME == debug_fps_metadata.type) {
+        debug_fps_metadata.time_elapsed += ((float)diff/1000.0);
+        if (debug_fps_metadata.time_elapsed >= debug_fps_metadata.time_period) {
+            float fps = (1000.0 * debug_fps_metadata.curr_frame)/
+                        (float)debug_fps_metadata.time_elapsed;
+            print_fps(fps);
+        }
+    }
+    return;
+}
+
+#endif // DEBUG_CALC_FPS
+
+static void *disp_loop(void *ptr)
+{
+    struct qbuf_t nxtBuf;
+    static int cur_buf=-1;
+    private_module_t *m = reinterpret_cast<private_module_t*>(ptr);
+
+    while (1) {
+        pthread_mutex_lock(&(m->qlock));
+
+        // wait (sleep) while display queue is empty;
+        if (m->disp.isEmpty()) {
+            pthread_cond_wait(&(m->qpost),&(m->qlock));
+        }
+
+        // dequeue next buff to display and lock it
+        nxtBuf = m->disp.getHeadValue();
+        m->disp.pop();
+        pthread_mutex_unlock(&(m->qlock));
+
+        // post buf out to display synchronously
+        private_handle_t const* hnd = reinterpret_cast<private_handle_t const*>
+                                                (nxtBuf.buf);
+        const size_t offset = hnd->base - m->framebuffer->base;
+        m->info.activate = FB_ACTIVATE_VBL;
+        m->info.yoffset = offset / m->finfo.line_length;
+
+#if defined(HDMI_DUAL_DISPLAY)
+        pthread_mutex_lock(&m->overlayLock);
+        m->orientation = neworientation;
+        m->currentOffset = offset;
+        m->hdmiStateChanged = true;
+        pthread_cond_signal(&(m->overlayPost));
+        pthread_mutex_unlock(&m->overlayLock);
+#endif
+        if (ioctl(m->framebuffer->fd, FBIOPUT_VSCREENINFO, &m->info) == -1) {
+            LOGE("ERROR FBIOPUT_VSCREENINFO failed; frame not displayed");
+        }
+
+#ifdef DEBUG_CALC_FPS
+        if (debug_fps_level > 0) calc_fps(ns2us(systemTime()));
+#endif
+
+        if (cur_buf == -1) {
+            int nxtAvail = ((nxtBuf.idx + 1) % m->numBuffers);
+            pthread_mutex_lock(&(m->avail[nxtBuf.idx].lock));
+            m->avail[nxtBuf.idx].is_avail = true;
+            m->avail[nxtBuf.idx].state = REF;
+            pthread_cond_broadcast(&(m->avail[nxtBuf.idx].cond));
+            pthread_mutex_unlock(&(m->avail[nxtBuf.idx].lock));
+        } else {
+            pthread_mutex_lock(&(m->avail[nxtBuf.idx].lock));
+            if (m->avail[nxtBuf.idx].state != SUB) {
+                LOGE_IF(m->swapInterval != 0, "[%d] state %c, expected %c", nxtBuf.idx,
+                    framebufferStateName[m->avail[nxtBuf.idx].state],
+                    framebufferStateName[SUB]);
+            }
+            m->avail[nxtBuf.idx].state = REF;
+            pthread_mutex_unlock(&(m->avail[nxtBuf.idx].lock));
+
+            pthread_mutex_lock(&(m->avail[cur_buf].lock));
+            m->avail[cur_buf].is_avail = true;
+            if (m->avail[cur_buf].state != REF) {
+                LOGE_IF(m->swapInterval != 0, "[%d] state %c, expected %c", cur_buf,
+                    framebufferStateName[m->avail[cur_buf].state],
+                    framebufferStateName[REF]);
+            }
+            m->avail[cur_buf].state = AVL;
+            pthread_cond_broadcast(&(m->avail[cur_buf].cond));
+            pthread_mutex_unlock(&(m->avail[cur_buf].lock));
+        }
+        cur_buf = nxtBuf.idx;
+    }
+    return NULL;
+}
+
+#if defined(HDMI_DUAL_DISPLAY)
+static void *hdmi_ui_loop(void *ptr)
+{
+    private_module_t* m = reinterpret_cast<private_module_t*>(
+            ptr);
+    while (1) {
+        pthread_mutex_lock(&m->overlayLock);
+        while(!(m->hdmiStateChanged))
+            pthread_cond_wait(&(m->overlayPost), &(m->overlayLock));
+        m->hdmiStateChanged = false;
+        if (m->exitHDMIUILoop) {
+            pthread_mutex_unlock(&m->overlayLock);
+            return NULL;
+        }
+        float asWidthRatio = m->actionsafeWidthRatio/100.0f;
+        float asHeightRatio = m->actionsafeHeightRatio/100.0f;
+
+        if (m->pobjOverlay) {
+            Overlay* pTemp = m->pobjOverlay;
+            if (!m->enableHDMIOutput)
+                pTemp->closeChannel();
+            else if (m->enableHDMIOutput && !m->videoOverlay) {
+                if (!pTemp->isChannelUP()) {
+                   int alignedW = ALIGN(m->info.xres, 32);
+
+                   private_handle_t const* hnd =
+                      reinterpret_cast<private_handle_t const*>(m->framebuffer);
+                   overlay_buffer_info info;
+                   info.width = alignedW;
+                   info.height = hnd->height;
+                   info.format = hnd->format;
+                   info.size = hnd->size;
+
+                   if (pTemp->startChannel(info, 1,
+                                           false, true, 0, VG0_PIPE, true)) {
+                        pTemp->setFd(m->framebuffer->fd);
+                        pTemp->setCrop(0, 0, m->info.xres, m->info.yres);
+                   } else
+                       pTemp->closeChannel();
+                }
+
+                if (pTemp->isChannelUP()) {
+                    int width = pTemp->getFBWidth();
+                    int height = pTemp->getFBHeight();
+                    int aswidth = width, asheight = height;
+                    int asX = 0, asY = 0; // Action safe x, y co-ordinates
+                    int fbwidth = m->info.xres, fbheight = m->info.yres;
+                    float defaultASWidthRatio = 0.0f, defaultASHeightRatio = 0.0f;
+                    if(HEIGHT_1080P == height) {
+                        defaultASHeightRatio = AS_1080_RATIO_H;
+                        defaultASWidthRatio = AS_1080_RATIO_W;
+                    } else if(HEIGHT_720P == height) {
+                        defaultASHeightRatio = AS_720_RATIO_H;
+                        defaultASWidthRatio = AS_720_RATIO_W;
+                    } else if(HEIGHT_480P == height) {
+                        defaultASHeightRatio = AS_480_RATIO_H;
+                        defaultASWidthRatio = AS_480_RATIO_W;
+                    }
+                    if(asWidthRatio <= 0.0f)
+                        asWidthRatio = defaultASWidthRatio;
+                    if(asHeightRatio <= 0.0f)
+                        asHeightRatio = defaultASHeightRatio;
+
+                    aswidth = (int)((float)width  - (float)(width * asWidthRatio));
+                    asheight = (int)((float)height  - (float)(height * asHeightRatio));
+                    asX = (width - aswidth) / 2;
+                    asY = (height - asheight) / 2;
+                    int rot = m->orientation;
+                    if (fbwidth < fbheight) {
+                         switch(rot) {
+                         // ROT_0
+                         case 0:
+                         // ROT_180
+                         case HAL_TRANSFORM_ROT_180: {
+                                aswidth = (asheight * fbwidth) / fbheight;
+                                asX = (width - aswidth) / 2;
+                                if(rot ==  HAL_TRANSFORM_ROT_180)
+                                  rot = OVERLAY_TRANSFORM_ROT_180;
+                                else
+                                  rot = 0;
+                            }
+                            break;
+                         // ROT_90
+                         case HAL_TRANSFORM_ROT_90:
+                            rot = OVERLAY_TRANSFORM_ROT_270;
+                            break;
+                         // ROT_270
+                         case HAL_TRANSFORM_ROT_270:
+                            rot = OVERLAY_TRANSFORM_ROT_90;
+                            break;
+                        }
+                    }
+                    else if (fbwidth > fbheight) {
+                         switch(rot) {
+                         // ROT_0
+                         case 0:
+                            rot = 0;
+                            break;
+                         // ROT_180
+                         case HAL_TRANSFORM_ROT_180:
+                            rot = OVERLAY_TRANSFORM_ROT_180;
+                            break;
+                         // ROT_90
+                         case HAL_TRANSFORM_ROT_90:
+                         // ROT_270
+                         case HAL_TRANSFORM_ROT_270: {
+                                //Swap width and height
+                                int t = fbwidth;
+                                fbwidth = fbheight;
+                                fbheight = t;
+                                aswidth = (asheight * fbwidth) / fbheight;
+                                asX = (width - aswidth) / 2;
+                                if(rot == HAL_TRANSFORM_ROT_90)
+                                    rot = OVERLAY_TRANSFORM_ROT_270;
+                                else
+                                    rot = OVERLAY_TRANSFORM_ROT_90;
+                            }
+                            break;
+                        }
+                    }
+                    int currOrientation = 0;
+                    pTemp->getOrientation(currOrientation);
+                    if(rot != currOrientation) {
+                        pTemp->setParameter(OVERLAY_TRANSFORM,
+                                              rot);
+                    }
+                    EVEN_OUT(asX);
+                    EVEN_OUT(asY);
+                    EVEN_OUT(aswidth);
+                    EVEN_OUT(asheight);
+                    int currentX = 0, currentY = 0;
+                    uint32_t currentW = width, currentH = height;
+                    if (pTemp->getPosition(currentX, currentY, currentW, currentH)) {
+                        if ((currentX != asX) || (currentY != asY) || (currentW != aswidth)
+                            || (currentH != asheight)) {
+                            pTemp->setPosition(asX, asY, aswidth, asheight);
+                        }
+                    }
+                    pTemp->queueBuffer(m->currentOffset);
+                }
+            }
+            else
+                pTemp->closeChannel();
+        }
+        pthread_mutex_unlock(&m->overlayLock);
+    }
+    return NULL;
+}
+
+static int fb_videoOverlayStarted(struct framebuffer_device_t* dev, int started)
+{
+    private_module_t* m = reinterpret_cast<private_module_t*>(
+            dev->common.module);
+    pthread_mutex_lock(&m->overlayLock);
+    Overlay* pTemp = m->pobjOverlay;
+    if(started != m->videoOverlay) {
+        m->hdmiStateChanged = true;
+        if (started && pTemp) {
+            pTemp->closeChannel();
+            m->videoOverlay = true;
+            pthread_cond_signal(&(m->overlayPost));
+        }
+        else {
+           m->videoOverlay = false;
+           pthread_cond_signal(&(m->overlayPost));
+        }
+    }
+    pthread_mutex_unlock(&m->overlayLock);
+    return 0;
+}
+
+static int fb_enableHDMIOutput(struct framebuffer_device_t* dev, int enable)
+{
+    private_module_t* m = reinterpret_cast<private_module_t*>(
+            dev->common.module);
+    pthread_mutex_lock(&m->overlayLock);
+    Overlay* pTemp = m->pobjOverlay;
+    if (!enable && pTemp)
+        pTemp->closeChannel();
+    m->enableHDMIOutput = enable;
+    m->hdmiStateChanged = true;
+    pthread_cond_signal(&(m->overlayPost));
+    pthread_mutex_unlock(&m->overlayLock);
+    return 0;
+}
+
+static int fb_setActionSafeWidthRatio(struct framebuffer_device_t* dev, float asWidthRatio)
+{
+    private_module_t* m = reinterpret_cast<private_module_t*>(
+            dev->common.module);
+    pthread_mutex_lock(&m->overlayLock);
+    m->actionsafeWidthRatio = asWidthRatio;
+    pthread_mutex_unlock(&m->overlayLock);
+    return 0;
+}
+
+static int fb_setActionSafeHeightRatio(struct framebuffer_device_t* dev, float asHeightRatio)
+{
+    private_module_t* m = reinterpret_cast<private_module_t*>(
+            dev->common.module);
+    pthread_mutex_lock(&m->overlayLock);
+    m->actionsafeHeightRatio = asHeightRatio;
+    pthread_mutex_unlock(&m->overlayLock);
+    return 0;
+}
+static int fb_orientationChanged(struct framebuffer_device_t* dev, int orientation)
+{
+    private_module_t* m = reinterpret_cast<private_module_t*>(
+            dev->common.module);
+    pthread_mutex_lock(&m->overlayLock);
+    neworientation = orientation;
+    pthread_mutex_unlock(&m->overlayLock);
+    return 0;
+}
+#endif
+
+static int fb_post(struct framebuffer_device_t* dev, buffer_handle_t buffer)
+{
+    if (private_handle_t::validate(buffer) < 0)
+        return -EINVAL;
+
+    int nxtIdx, futureIdx = -1;
+    bool reuse;
+    struct qbuf_t qb;
+    fb_context_t* ctx = (fb_context_t*)dev;
+
+    private_handle_t const* hnd = reinterpret_cast<private_handle_t const*>(buffer);
+    private_module_t* m = reinterpret_cast<private_module_t*>(
+            dev->common.module);
+
+    if (hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER) {
+
+        reuse = false;
+        nxtIdx = (m->currentIdx + 1) % m->numBuffers;
+        futureIdx = (nxtIdx + 1) % m->numBuffers;
+
+        if (m->swapInterval == 0) {
+            // if SwapInterval = 0 and no buffers available then reuse
+            // current buf for next rendering so don't post new buffer
+            if (pthread_mutex_trylock(&(m->avail[nxtIdx].lock))) {
+                reuse = true;
+            } else {
+                if (! m->avail[nxtIdx].is_avail)
+                    reuse = true;
+                pthread_mutex_unlock(&(m->avail[nxtIdx].lock));
+            }
+        }
+
+        if(!reuse){
+            // unlock previous ("current") Buffer and lock the new buffer
+            m->base.lock(&m->base, buffer,
+                    private_module_t::PRIV_USAGE_LOCKED_FOR_POST,
+                    0,0, m->info.xres, m->info.yres, NULL);
+
+            // post/queue the new buffer
+            pthread_mutex_lock(&(m->avail[nxtIdx].lock));
+            if (m->avail[nxtIdx].is_avail != true) {
+                LOGE_IF(m->swapInterval != 0, "Found %d buf to be not avail", nxtIdx);
+            }
+
+            m->avail[nxtIdx].is_avail = false;
+
+            if (m->avail[nxtIdx].state != AVL) {
+                LOGD("[%d] state %c, expected %c", nxtIdx,
+                    framebufferStateName[m->avail[nxtIdx].state],
+                    framebufferStateName[AVL]);
+            }
+
+            m->avail[nxtIdx].state = SUB;
+            pthread_mutex_unlock(&(m->avail[nxtIdx].lock));
+
+            qb.idx = nxtIdx;
+            qb.buf = buffer;
+            pthread_mutex_lock(&(m->qlock));
+            m->disp.push(qb);
+            pthread_cond_signal(&(m->qpost));
+            pthread_mutex_unlock(&(m->qlock));
+
+            if (m->currentBuffer)
+                m->base.unlock(&m->base, m->currentBuffer);
+
+            m->currentBuffer = buffer;
+            m->currentIdx = nxtIdx;
+        } else {
+            if (m->currentBuffer)
+                m->base.unlock(&m->base, m->currentBuffer);
+            m->base.lock(&m->base, buffer,
+                         private_module_t::PRIV_USAGE_LOCKED_FOR_POST,
+                         0,0, m->info.xres, m->info.yres, NULL);
+            m->currentBuffer = buffer;
+        }
+
+    } else {
+        void* fb_vaddr;
+        void* buffer_vaddr;
+        
+        m->base.lock(&m->base, m->framebuffer, 
+                GRALLOC_USAGE_SW_WRITE_RARELY, 
+                0, 0, m->info.xres, m->info.yres,
+                &fb_vaddr);
+
+        m->base.lock(&m->base, buffer, 
+                GRALLOC_USAGE_SW_READ_RARELY, 
+                0, 0, m->info.xres, m->info.yres,
+                &buffer_vaddr);
+
+        //memcpy(fb_vaddr, buffer_vaddr, m->finfo.line_length * m->info.yres);
+
+        msm_copy_buffer(
+                m->framebuffer, m->framebuffer->fd,
+                m->info.xres, m->info.yres, m->fbFormat,
+                m->info.xoffset, m->info.yoffset,
+                m->info.width, m->info.height);
+
+        m->base.unlock(&m->base, buffer); 
+        m->base.unlock(&m->base, m->framebuffer); 
+    }
+
+    LOGD_IF(FB_DEBUG, "Framebuffer state: [0] = %c [1] = %c [2] = %c",
+        framebufferStateName[m->avail[0].state],
+        framebufferStateName[m->avail[1].state],
+        framebufferStateName[m->avail[2].state]);
+    return 0;
+}
+
+static int fb_compositionComplete(struct framebuffer_device_t* dev)
+{
+    // TODO: Properly implement composition complete callback
+    glFinish();
+
+    return 0;
+}
+
+static int fb_lockBuffer(struct framebuffer_device_t* dev, int index)
+{
+    private_module_t* m = reinterpret_cast<private_module_t*>(
+            dev->common.module);
+
+    // Return immediately if the buffer is available
+    if ((m->avail[index].state == AVL) || (m->swapInterval == 0))
+        return 0;
+
+    pthread_mutex_lock(&(m->avail[index].lock));
+    while (m->avail[index].state != AVL) {
+        pthread_cond_wait(&(m->avail[index].cond),
+                         &(m->avail[index].lock));
+    }
+    pthread_mutex_unlock(&(m->avail[index].lock));
+
+    return 0;
+}
+
+/*****************************************************************************/
+
+int mapFrameBufferLocked(struct private_module_t* module)
+{
+    // already initialized...
+    if (module->framebuffer) {
+        return 0;
+    }
+        
+    char const * const device_template[] = {
+            "/dev/graphics/fb%u",
+            "/dev/fb%u",
+            0 };
+
+    int fd = -1;
+    int i=0;
+    char name[64];
+    char property[PROPERTY_VALUE_MAX];
+
+    while ((fd==-1) && device_template[i]) {
+        snprintf(name, 64, device_template[i], 0);
+        fd = open(name, O_RDWR, 0);
+        i++;
+    }
+    if (fd < 0)
+        return -errno;
+
+    struct fb_fix_screeninfo finfo;
+    if (ioctl(fd, FBIOGET_FSCREENINFO, &finfo) == -1)
+        return -errno;
+
+    struct fb_var_screeninfo info;
+    if (ioctl(fd, FBIOGET_VSCREENINFO, &info) == -1)
+        return -errno;
+
+    info.reserved[0] = 0;
+    info.reserved[1] = 0;
+    info.reserved[2] = 0;
+    info.xoffset = 0;
+    info.yoffset = 0;
+    info.activate = FB_ACTIVATE_NOW;
+
+    /* Interpretation of offset for color fields: All offsets are from the right,
+    * inside a "pixel" value, which is exactly 'bits_per_pixel' wide (means: you
+    * can use the offset as right argument to <<). A pixel afterwards is a bit
+    * stream and is written to video memory as that unmodified. This implies
+    * big-endian byte order if bits_per_pixel is greater than 8.
+    */
+
+    if(info.bits_per_pixel == 32) {
+	/*
+	* Explicitly request RGBA_8888
+	*/
+	info.bits_per_pixel = 32;
+	info.red.offset     = 24;
+	info.red.length     = 8;
+	info.green.offset   = 16;
+	info.green.length   = 8;
+	info.blue.offset    = 8;
+	info.blue.length    = 8;
+	info.transp.offset  = 0;
+	info.transp.length  = 8;
+
+	/* Note: the GL driver does not have a r=8 g=8 b=8 a=0 config, so if we do
+	* not use the MDP for composition (i.e. hw composition == 0), ask for
+	* RGBA instead of RGBX. */
+	if (property_get("debug.sf.hw", property, NULL) > 0 && atoi(property) == 0)
+		module->fbFormat = HAL_PIXEL_FORMAT_RGBX_8888;
+	else if(property_get("debug.composition.type", property, NULL) > 0 && (strncmp(property, "mdp", 3) == 0))
+		module->fbFormat = HAL_PIXEL_FORMAT_RGBX_8888;
+	else
+		module->fbFormat = HAL_PIXEL_FORMAT_RGBA_8888;
+    } else {
+	/*
+	* Explicitly request 5/6/5
+	*/
+	info.bits_per_pixel = 16;
+	info.red.offset     = 11;
+	info.red.length     = 5;
+	info.green.offset   = 5;
+	info.green.length   = 6;
+	info.blue.offset    = 0;
+	info.blue.length    = 5;
+	info.transp.offset  = 0;
+	info.transp.length  = 0;
+	module->fbFormat = HAL_PIXEL_FORMAT_RGB_565;
+    }
+    /*
+     * Request NUM_BUFFERS screens (at lest 2 for page flipping)
+     */
+    int numberOfBuffers = (int)(finfo.smem_len/(info.yres * info.xres * (info.bits_per_pixel/8)));
+    LOGV("num supported framebuffers in kernel = %d", numberOfBuffers);
+
+    if (property_get("debug.gr.numframebuffers", property, NULL) > 0) {
+        int num = atoi(property);
+        if ((num >= NUM_FRAMEBUFFERS_MIN) && (num <= NUM_FRAMEBUFFERS_MAX)) {
+            numberOfBuffers = num;
+        }
+    }
+
+    if (numberOfBuffers > NUM_FRAMEBUFFERS_MAX)
+        numberOfBuffers = NUM_FRAMEBUFFERS_MAX;
+
+    LOGE("We support %d buffers", numberOfBuffers);
+
+    info.yres_virtual = info.yres * numberOfBuffers;
+
+    uint32_t flags = PAGE_FLIP;
+    if (ioctl(fd, FBIOPUT_VSCREENINFO, &info) == -1) {
+        info.yres_virtual = info.yres;
+        flags &= ~PAGE_FLIP;
+        LOGW("FBIOPUT_VSCREENINFO failed, page flipping not supported");
+    }
+
+    if (info.yres_virtual < info.yres * 2) {
+        // we need at least 2 for page-flipping
+        info.yres_virtual = info.yres;
+        flags &= ~PAGE_FLIP;
+        LOGW("page flipping not supported (yres_virtual=%d, requested=%d)",
+                info.yres_virtual, info.yres*2);
+    }
+
+    if (ioctl(fd, FBIOGET_VSCREENINFO, &info) == -1)
+        return -errno;
+
+    if (int(info.width) <= 0 || int(info.height) <= 0) {
+        // the driver doesn't return that information
+        // default to 160 dpi
+        info.width  = ((info.xres * 25.4f)/160.0f + 0.5f);
+        info.height = ((info.yres * 25.4f)/160.0f + 0.5f);
+    }
+
+    float xdpi = (info.xres * 25.4f) / info.width;
+    float ydpi = (info.yres * 25.4f) / info.height;
+    //The reserved[4] field is used to store FPS by the driver.
+    float fps  = info.reserved[4];
+
+    LOGI(   "using (fd=%d)\n"
+            "id           = %s\n"
+            "xres         = %d px\n"
+            "yres         = %d px\n"
+            "xres_virtual = %d px\n"
+            "yres_virtual = %d px\n"
+            "bpp          = %d\n"
+            "r            = %2u:%u\n"
+            "g            = %2u:%u\n"
+            "b            = %2u:%u\n",
+            fd,
+            finfo.id,
+            info.xres,
+            info.yres,
+            info.xres_virtual,
+            info.yres_virtual,
+            info.bits_per_pixel,
+            info.red.offset, info.red.length,
+            info.green.offset, info.green.length,
+            info.blue.offset, info.blue.length
+    );
+
+    LOGI(   "width        = %d mm (%f dpi)\n"
+            "height       = %d mm (%f dpi)\n"
+            "refresh rate = %.2f Hz\n",
+            info.width,  xdpi,
+            info.height, ydpi,
+            fps
+    );
+
+
+    if (ioctl(fd, FBIOGET_FSCREENINFO, &finfo) == -1)
+        return -errno;
+
+    if (finfo.smem_len <= 0)
+        return -errno;
+
+    module->flags = flags;
+    module->info = info;
+    module->finfo = finfo;
+    module->xdpi = xdpi;
+    module->ydpi = ydpi;
+    module->fps = fps;
+
+#ifdef NO_SURFACEFLINGER_SWAPINTERVAL
+    char pval[PROPERTY_VALUE_MAX];
+    property_get("debug.gr.swapinterval", pval, "1");
+    module->swapInterval = atoi(pval);
+    if (module->swapInterval < private_module_t::PRIV_MIN_SWAP_INTERVAL ||
+        module->swapInterval > private_module_t::PRIV_MAX_SWAP_INTERVAL) {
+        module->swapInterval = 1;
+        LOGW("Out of range (%d to %d) value for debug.gr.swapinterval, using 1",
+             private_module_t::PRIV_MIN_SWAP_INTERVAL,
+             private_module_t::PRIV_MAX_SWAP_INTERVAL);
+    }
+
+#else
+    /* when surfaceflinger supports swapInterval then can just do this */
+    module->swapInterval = 1;
+#endif
+
+#ifdef DEBUG_CALC_FPS
+    char prop[PROPERTY_VALUE_MAX];
+    property_get("debug.gr.calcfps", prop, "0");
+    debug_fps_level = atoi(prop);
+    if (debug_fps_level > MAX_DEBUG_FPS_LEVEL) {
+        LOGW("out of range value for debug.gr.calcfps, using 0");
+        debug_fps_level = 0;
+    }
+
+    LOGE("DEBUG_CALC_FPS: %d", debug_fps_level);
+    populate_debug_fps_metadata();
+#endif
+
+    module->currentIdx = -1;
+    pthread_cond_init(&(module->qpost), NULL);
+    pthread_mutex_init(&(module->qlock), NULL);
+    for (i = 0; i < NUM_FRAMEBUFFERS_MAX; i++) {
+        pthread_mutex_init(&(module->avail[i].lock), NULL);
+        pthread_cond_init(&(module->avail[i].cond), NULL);
+        module->avail[i].is_avail = true;
+        module->avail[i].state = AVL;
+    }    
+
+    /* create display update thread */
+    pthread_t thread1;
+    if (pthread_create(&thread1, NULL, &disp_loop, (void *) module)) {
+         return -errno;
+    }
+
+    /*
+     * map the framebuffer
+     */
+
+    int err;
+    size_t fbSize = roundUpToPageSize(finfo.line_length * info.yres_virtual);
+    module->framebuffer = new private_handle_t(dup(fd), fbSize,
+            private_handle_t::PRIV_FLAGS_USES_PMEM, BUFFER_TYPE_UI, module->fbFormat, info.xres, info.yres);
+
+    module->numBuffers = info.yres_virtual / info.yres;
+    module->bufferMask = 0;
+
+    void* vaddr = mmap(0, fbSize, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
+    if (vaddr == MAP_FAILED) {
+        LOGE("Error mapping the framebuffer (%s)", strerror(errno));
+        return -errno;
+    }
+    module->framebuffer->base = intptr_t(vaddr);
+    memset(vaddr, 0, fbSize);
+
+#if defined(HDMI_DUAL_DISPLAY)
+    /* Overlay for HDMI*/
+    pthread_mutex_init(&(module->overlayLock), NULL);
+    pthread_cond_init(&(module->overlayPost), NULL);
+    module->pobjOverlay = new Overlay();
+    module->currentOffset = 0;
+    module->exitHDMIUILoop = false;
+    module->hdmiStateChanged = false;
+    pthread_t hdmiUIThread;
+    pthread_create(&hdmiUIThread, NULL, &hdmi_ui_loop, (void *) module);
+#endif
+
+    return 0;
+}
+
+static int mapFrameBuffer(struct private_module_t* module)
+{
+    pthread_mutex_lock(&module->lock);
+    int err = mapFrameBufferLocked(module);
+    pthread_mutex_unlock(&module->lock);
+    return err;
+}
+
+/*****************************************************************************/
+
+static int fb_close(struct hw_device_t *dev)
+{
+    fb_context_t* ctx = (fb_context_t*)dev;
+#if defined(HDMI_DUAL_DISPLAY)
+    private_module_t* m = reinterpret_cast<private_module_t*>(
+            ctx->device.common.module);
+    pthread_mutex_lock(&m->overlayLock);
+    m->exitHDMIUILoop = true;
+    pthread_cond_signal(&(m->overlayPost));
+    pthread_mutex_unlock(&m->overlayLock);
+#endif
+    if (ctx) {
+        free(ctx);
+    }
+    return 0;
+}
+
+int fb_device_open(hw_module_t const* module, const char* name,
+        hw_device_t** device)
+{
+    int status = -EINVAL;
+    if (!strcmp(name, GRALLOC_HARDWARE_FB0)) {
+        alloc_device_t* gralloc_device;
+        status = gralloc_open(module, &gralloc_device);
+        if (status < 0)
+            return status;
+
+        /* initialize our state here */
+        fb_context_t *dev = (fb_context_t*)malloc(sizeof(*dev));
+        memset(dev, 0, sizeof(*dev));
+
+        /* initialize the procs */
+        dev->device.common.tag = HARDWARE_DEVICE_TAG;
+        dev->device.common.version = 0;
+        dev->device.common.module = const_cast<hw_module_t*>(module);
+        dev->device.common.close = fb_close;
+        dev->device.setSwapInterval = fb_setSwapInterval;
+        dev->device.post            = fb_post;
+        dev->device.setUpdateRect = 0;
+        dev->device.compositionComplete = fb_compositionComplete;
+        dev->device.lockBuffer = fb_lockBuffer;
+#if defined(HDMI_DUAL_DISPLAY)
+        dev->device.orientationChanged = fb_orientationChanged;
+        dev->device.videoOverlayStarted = fb_videoOverlayStarted;
+        dev->device.enableHDMIOutput = fb_enableHDMIOutput;
+        dev->device.setActionSafeWidthRatio = fb_setActionSafeWidthRatio;
+        dev->device.setActionSafeHeightRatio = fb_setActionSafeHeightRatio;
+#endif
+
+        private_module_t* m = (private_module_t*)module;
+        status = mapFrameBuffer(m);
+        if (status >= 0) {
+            int stride = m->finfo.line_length / (m->info.bits_per_pixel >> 3);
+            const_cast<uint32_t&>(dev->device.flags) = 0;
+            const_cast<uint32_t&>(dev->device.width) = m->info.xres;
+            const_cast<uint32_t&>(dev->device.height) = m->info.yres;
+            const_cast<int&>(dev->device.stride) = stride;
+            const_cast<int&>(dev->device.format) = m->fbFormat;
+            const_cast<float&>(dev->device.xdpi) = m->xdpi;
+            const_cast<float&>(dev->device.ydpi) = m->ydpi;
+            const_cast<float&>(dev->device.fps) = m->fps;
+            const_cast<int&>(dev->device.minSwapInterval) = private_module_t::PRIV_MIN_SWAP_INTERVAL;
+            const_cast<int&>(dev->device.maxSwapInterval) = private_module_t::PRIV_MAX_SWAP_INTERVAL;
+            const_cast<int&>(dev->device.numFramebuffers) = m->numBuffers;
+
+            if (m->finfo.reserved[0] == 0x5444 &&
+                    m->finfo.reserved[1] == 0x5055) {
+                dev->device.setUpdateRect = fb_setUpdateRect;
+                LOGD("UPDATE_ON_DEMAND supported");
+            }
+
+            *device = &dev->device.common;
+        }
+
+        // Close the gralloc module
+        gralloc_close(gralloc_device);
+    }
+    return status;
+}
+
+/* Copy a pmem buffer to the framebuffer */
+
+static void
+msm_copy_buffer(buffer_handle_t handle, int fd,
+                int width, int height, int format,
+                int x, int y, int w, int h)
+{
+    struct {
+        unsigned int count;
+        mdp_blit_req req;
+    } blit;
+    private_handle_t *priv = (private_handle_t*) handle;
+
+    memset(&blit, 0, sizeof(blit));
+    blit.count = 1;
+
+    blit.req.flags = 0;
+    blit.req.alpha = 0xff;
+    blit.req.transp_mask = 0xffffffff;
+
+    blit.req.src.width = width;
+    blit.req.src.height = height;
+    blit.req.src.offset = 0;
+    blit.req.src.memory_id = priv->fd;
+
+    blit.req.dst.width = width;
+    blit.req.dst.height = height;
+    blit.req.dst.offset = 0;
+    blit.req.dst.memory_id = fd; 
+    blit.req.dst.format = format;
+
+    blit.req.src_rect.x = blit.req.dst_rect.x = x;
+    blit.req.src_rect.y = blit.req.dst_rect.y = y;
+    blit.req.src_rect.w = blit.req.dst_rect.w = w;
+    blit.req.src_rect.h = blit.req.dst_rect.h = h;
+
+    if (ioctl(fd, MSMFB_BLIT, &blit))
+        LOGE("MSMFB_BLIT failed = %d", -errno);
+}
diff --git a/libgralloc-qsd8k/gpu.cpp b/libgralloc-qsd8k/gpu.cpp
new file mode 100755
index 0000000..cabcda9
--- /dev/null
+++ b/libgralloc-qsd8k/gpu.cpp
@@ -0,0 +1,505 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <limits.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+#include <sys/mman.h>
+
+#include <cutils/properties.h>
+#ifdef HOST
+#include <linux/ashmem.h>
+#endif
+
+#include "gr.h"
+#include "gpu.h"
+
+static const int OMX_QCOM_COLOR_FormatYVU420SemiPlanar = 0x7FA30C00;
+static const int QOMX_COLOR_FormatYUV420PackedSemiPlanar64x32Tile2m8ka = 0x7FA30C03;
+static const int QOMX_INTERLACE_FLAG = 0x49283654;
+static const int QOMX_3D_VIDEO_FLAG = 0x23784238;
+
+gpu_context_t::gpu_context_t(Deps& deps, PmemAllocator& pmemAllocator,
+        PmemAllocator& pmemAdspAllocator, const private_module_t* module) :
+    deps(deps),
+    pmemAllocator(pmemAllocator),
+    pmemAdspAllocator(pmemAdspAllocator)
+{
+    // Zero out the alloc_device_t
+    memset(static_cast<alloc_device_t*>(this), 0, sizeof(alloc_device_t));
+
+    char property[PROPERTY_VALUE_MAX];
+    if (property_get("debug.sf.hw", property, NULL) > 0) {
+        if(atoi(property) == 0) {
+            //debug.sf.hw = 0
+            compositionType = CPU_COMPOSITION;
+        } else { //debug.sf.hw = 1
+            // Get the composition type
+            property_get("debug.composition.type", property, NULL);
+            if (property == NULL) {
+                compositionType = GPU_COMPOSITION;
+            } else if ((strncmp(property, "mdp", 3)) == 0) {
+                compositionType = MDP_COMPOSITION;
+            } else if ((strncmp(property, "c2d", 3)) == 0) {
+                compositionType = C2D_COMPOSITION;
+            } else {
+                compositionType = GPU_COMPOSITION;
+            }
+        }
+    } else { //debug.sf.hw is not set. Use cpu composition
+        compositionType = CPU_COMPOSITION;
+    }
+
+    // Initialize the procs
+    common.tag     = HARDWARE_DEVICE_TAG;
+    common.version = 0;
+    common.module  = const_cast<hw_module_t*>(&module->base.common);
+    common.close   = gralloc_close;
+    alloc          = gralloc_alloc;
+    allocSize      = gralloc_alloc_size;
+    free           = gralloc_free;
+}
+
+int gpu_context_t::gralloc_alloc_framebuffer_locked(size_t size, int usage,
+        buffer_handle_t* pHandle)
+{
+    private_module_t* m = reinterpret_cast<private_module_t*>(common.module);
+
+    // we don't support allocations with both the FB and PMEM_ADSP flags
+    if (usage & GRALLOC_USAGE_PRIVATE_ADSP_HEAP) {
+        return -EINVAL;
+    }
+
+    // allocate the framebuffer
+    if (m->framebuffer == NULL) {
+        // initialize the framebuffer, the framebuffer is mapped once
+        // and forever.
+        int err = deps.mapFrameBufferLocked(m);
+        if (err < 0) {
+            return err;
+        }
+    }
+
+    const uint32_t bufferMask = m->bufferMask;
+    const uint32_t numBuffers = m->numBuffers;
+    const size_t bufferSize = m->finfo.line_length * m->info.yres;
+    if (numBuffers == 1) {
+        // If we have only one buffer, we never use page-flipping. Instead,
+        // we return a regular buffer which will be memcpy'ed to the main
+        // screen when post is called.
+        int newUsage = (usage & ~GRALLOC_USAGE_HW_FB) | GRALLOC_USAGE_HW_2D;
+        return gralloc_alloc_buffer(bufferSize, newUsage, pHandle, BUFFER_TYPE_UI, m->fbFormat, m->info.xres, m->info.yres);
+    }
+
+    if (bufferMask >= ((1LU<<numBuffers)-1)) {
+        // We ran out of buffers.
+        return -ENOMEM;
+    }
+
+    // create a "fake" handles for it
+    intptr_t vaddr = intptr_t(m->framebuffer->base);
+    private_handle_t* hnd = new private_handle_t(dup(m->framebuffer->fd), bufferSize,
+                                                 private_handle_t::PRIV_FLAGS_USES_PMEM |
+                                                 private_handle_t::PRIV_FLAGS_FRAMEBUFFER,
+                                                 BUFFER_TYPE_UI, m->fbFormat, m->info.xres, m->info.yres);
+
+    // find a free slot
+    for (uint32_t i=0 ; i<numBuffers ; i++) {
+        if ((bufferMask & (1LU<<i)) == 0) {
+            m->bufferMask |= (1LU<<i);
+            break;
+        }
+        vaddr += bufferSize;
+    }
+
+    hnd->base = vaddr;
+    hnd->offset = vaddr - intptr_t(m->framebuffer->base);
+    *pHandle = hnd;
+
+    return 0;
+}
+
+
+int gpu_context_t::gralloc_alloc_framebuffer(size_t size, int usage,
+        buffer_handle_t* pHandle)
+{
+    private_module_t* m = reinterpret_cast<private_module_t*>(common.module);
+    pthread_mutex_lock(&m->lock);
+    int err = gralloc_alloc_framebuffer_locked(size, usage, pHandle);
+    pthread_mutex_unlock(&m->lock);
+    return err;
+}
+
+int gpu_context_t::alloc_ashmem_buffer(size_t size, unsigned int postfix, void** pBase,
+            int* pOffset, int* pFd)
+{
+    int err = 0;
+    int fd = -1;
+    void* base = 0;
+    int offset = 0;
+
+    char name[ASHMEM_NAME_LEN];
+    snprintf(name, ASHMEM_NAME_LEN, "gralloc-buffer-%x", postfix);
+    int prot = PROT_READ | PROT_WRITE;
+    fd = ashmem_create_region(name, size);
+    if (fd < 0) {
+        LOGE("couldn't create ashmem (%s)", strerror(errno));
+        err = -errno;
+    } else {
+        if (ashmem_set_prot_region(fd, prot) < 0) {
+            LOGE("ashmem_set_prot_region(fd=%d, prot=%x) failed (%s)",
+                 fd, prot, strerror(errno));
+            close(fd);
+            err = -errno;
+        } else {
+            base = mmap(0, size, prot, MAP_SHARED|MAP_POPULATE|MAP_LOCKED, fd, 0);
+            if (base == MAP_FAILED) {
+                LOGE("alloc mmap(fd=%d, size=%d, prot=%x) failed (%s)",
+                     fd, size, prot, strerror(errno));
+                close(fd);
+                err = -errno;
+            } else {
+                memset((char*)base + offset, 0, size);
+            }
+        }
+    }
+    if(err == 0) {
+        *pFd = fd;
+        *pBase = base;
+        *pOffset = offset;
+#ifdef HOST
+        if (ioctl(fd, ASHMEM_CACHE_INV_RANGE, NULL)) {
+            LOGE("ASHMEM_CACHE_INV_RANGE failed fd = %d", fd);
+        }
+#endif
+    }
+    return err;
+}
+
+int gpu_context_t::gralloc_alloc_buffer(size_t size, int usage, buffer_handle_t* pHandle,
+                                        int bufferType, int format, int width, int height)
+{
+    int err = 0;
+    int flags = 0;
+
+    int fd = -1;
+    void* base = 0; // XXX JMG: This should change to just get an address from
+                    // the PmemAllocator rather than getting the base & offset separately
+    int offset = 0;
+    int lockState = 0;
+
+    size = roundUpToPageSize(size);
+#ifndef USE_ASHMEM
+    if (usage & GRALLOC_USAGE_HW_TEXTURE) {
+        // enable pmem in that case, so our software GL can fallback to
+        // the copybit module.
+        flags |= private_handle_t::PRIV_FLAGS_USES_PMEM;
+    }
+
+    if (usage & GRALLOC_USAGE_HW_2D) {
+        flags |= private_handle_t::PRIV_FLAGS_USES_PMEM;
+    }
+#else
+    // Enable use of PMEM only when MDP composition is used (and other conditions apply).
+    // Else fall back on using ASHMEM
+    if ((get_composition_type() == MDP_COMPOSITION) &&
+        ((usage & GRALLOC_USAGE_HW_TEXTURE) || (usage & GRALLOC_USAGE_HW_2D)) ) {
+        flags |= private_handle_t::PRIV_FLAGS_USES_PMEM;
+    }
+
+    if (usage & GRALLOC_USAGE_PRIVATE_EBI_HEAP) {
+        flags |= private_handle_t::PRIV_FLAGS_USES_PMEM;
+    }
+#endif
+    if ((usage & GRALLOC_USAGE_PRIVATE_ADSP_HEAP) || (usage & GRALLOC_USAGE_PRIVATE_SMI_HEAP)
+        || (usage & GRALLOC_USAGE_EXTERNAL_DISP) || (usage & GRALLOC_USAGE_PROTECTED)) {
+        flags |= private_handle_t::PRIV_FLAGS_USES_PMEM_ADSP;
+        flags &= ~private_handle_t::PRIV_FLAGS_USES_PMEM;
+    }
+
+    private_module_t* m = reinterpret_cast<private_module_t*>(common.module);
+    if((flags & private_handle_t::PRIV_FLAGS_USES_PMEM) == 0 &&
+       (flags & private_handle_t::PRIV_FLAGS_USES_PMEM_ADSP) == 0) {
+       flags |= private_handle_t::PRIV_FLAGS_USES_ASHMEM;
+       err = alloc_ashmem_buffer(size, (unsigned int)pHandle, &base, &offset, &fd);
+       if(err >= 0)
+            lockState |= private_handle_t::LOCK_STATE_MAPPED; 
+    }
+    else if ((flags & private_handle_t::PRIV_FLAGS_USES_PMEM) != 0 ||
+        (flags & private_handle_t::PRIV_FLAGS_USES_PMEM_ADSP) != 0) {
+
+        PmemAllocator* pma = 0;
+
+        if ((flags & private_handle_t::PRIV_FLAGS_USES_PMEM) != 0) {
+          if ((flags & private_handle_t::PRIV_FLAGS_USES_PMEM_ADSP) != 0) {
+              LOGE("attempting to allocate a gralloc buffer with both the "
+                   "USES_PMEM and USES_PMEM_ADSP flags.  Unsetting the "
+                   "USES_PMEM_ADSP flag.");
+              flags &= ~private_handle_t::PRIV_FLAGS_USES_PMEM_ADSP;
+          }
+          pma = &pmemAllocator;
+        } else { // (flags & private_handle_t::PRIV_FLAGS_USES_PMEM_ADSP) != 0
+          pma = &pmemAdspAllocator;
+        }
+
+        // PMEM buffers are always mmapped
+        lockState |= private_handle_t::LOCK_STATE_MAPPED;
+
+        err = pma->alloc_pmem_buffer(size, usage, &base, &offset, &fd, format);
+        if (err < 0) {
+            // Pmem allocation failed. Try falling back to ashmem iff we are:
+            // a. not using MDP composition
+            // b. not allocating memory for a buffer to be used by overlays
+            // c. The client has not explicitly requested a PMEM buffer
+            if ((get_composition_type() != MDP_COMPOSITION) &&
+                (bufferType != BUFFER_TYPE_VIDEO) &&
+                ((usage & GRALLOC_USAGE_PRIVATE_EBI_HEAP) == 0) &&
+                ((usage & GRALLOC_USAGE_PRIVATE_ADSP_HEAP) == 0)) {
+                // the caller didn't request PMEM, so we can try something else
+                flags &= ~private_handle_t::PRIV_FLAGS_USES_PMEM;
+                err = 0;
+                LOGE("Pmem allocation failed. Trying ashmem");
+                goto try_ashmem;
+            } else {
+                LOGE("couldn't open pmem (%s)", strerror(errno));
+            }
+        }
+    } else {
+try_ashmem:
+        err = alloc_ashmem_buffer(size, (unsigned int)pHandle, &base, &offset, &fd);
+        if (err >= 0) {
+            lockState |= private_handle_t::LOCK_STATE_MAPPED;
+            flags |= private_handle_t::PRIV_FLAGS_USES_ASHMEM;
+        } else {
+            LOGE("Ashmem fallback failed");
+        }
+    }
+
+    if (err == 0) {
+        private_handle_t* hnd = new private_handle_t(fd, size, flags, bufferType, format, width, height);
+        hnd->offset = offset;
+        hnd->base = int(base)+offset;
+        hnd->lockState = lockState;
+        *pHandle = hnd;
+    }
+
+    LOGE_IF(err, "gralloc failed err=%s", strerror(-err));
+
+    return err;
+}
+
+static inline size_t ALIGN(size_t x, size_t align) {
+    return (x + align-1) & ~(align-1);
+}
+
+void gpu_context_t::getGrallocInformationFromFormat(int inputFormat, int *colorFormat, int *bufferType)
+{
+    *bufferType = BUFFER_TYPE_VIDEO;
+    *colorFormat = inputFormat;
+
+    if (inputFormat == HAL_PIXEL_FORMAT_YV12) {
+        *bufferType = BUFFER_TYPE_VIDEO;
+    } else if (inputFormat & S3D_FORMAT_MASK) {
+        // S3D format
+        *colorFormat = COLOR_FORMAT(inputFormat);
+    } else if (inputFormat & INTERLACE_MASK) {
+        // Interlaced
+        *colorFormat = inputFormat ^ HAL_PIXEL_FORMAT_INTERLACE;
+    } else if (inputFormat < 0x7) {
+        // RGB formats
+        *colorFormat = inputFormat;
+        *bufferType = BUFFER_TYPE_UI;
+    } else if ((inputFormat == HAL_PIXEL_FORMAT_R_8) ||
+               (inputFormat == HAL_PIXEL_FORMAT_RG_88)) {
+        *colorFormat = inputFormat;
+        *bufferType = BUFFER_TYPE_UI;
+    }
+}
+
+int gpu_context_t::alloc_impl(int w, int h, int format, int usage,
+        buffer_handle_t* pHandle, int* pStride, int bufferSize) {
+    if (!pHandle || !pStride)
+        return -EINVAL;
+
+    size_t size, alignedw, alignedh;
+
+    alignedw = ALIGN(w, 32);
+    alignedh = ALIGN(h, 32);
+    int colorFormat, bufferType;
+    getGrallocInformationFromFormat(format, &colorFormat, &bufferType);
+	
+    switch (colorFormat) {
+        case HAL_PIXEL_FORMAT_RGBA_8888:
+        case HAL_PIXEL_FORMAT_RGBX_8888:
+        case HAL_PIXEL_FORMAT_BGRA_8888:
+            size = alignedw * alignedh * 4;
+            break;
+        case HAL_PIXEL_FORMAT_RGB_888:
+            size = alignedw * alignedh * 3;
+            break;
+        case HAL_PIXEL_FORMAT_RGB_565:
+        case HAL_PIXEL_FORMAT_RGBA_5551:
+        case HAL_PIXEL_FORMAT_RGBA_4444:
+            size = alignedw * alignedh * 2;
+            break;
+
+        // adreno formats
+        case HAL_PIXEL_FORMAT_YCrCb_420_SP_ADRENO:  // NV21
+            size  = ALIGN(alignedw*alignedh, 4096);
+            size += ALIGN(2 * ALIGN(w/2, 32) * ALIGN(h/2, 32), 4096);
+            break;
+        case HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED:   // NV12
+            // The chroma plane is subsampled,
+            // but the pitch in bytes is unchanged
+            // The GPU needs 4K alignment, but the video decoder needs 8K
+            alignedw = ALIGN(w, 128);
+            size  = ALIGN( alignedw * alignedh, 8192);
+            size += ALIGN( alignedw * ALIGN(h/2, 32), 8192);
+            break;
+        case HAL_PIXEL_FORMAT_YCbCr_420_SP:
+	case HAL_PIXEL_FORMAT_YCrCb_420_SP:
+        case HAL_PIXEL_FORMAT_YV12:
+            if ((w&1) || (h&1)) {
+                LOGE("w or h is odd for the YUV format");
+                return -EINVAL;
+            }
+            alignedw = ALIGN(w, 16);
+            alignedh = h;
+            size = alignedw*alignedh +
+                    (ALIGN(alignedw/2, 16) * (alignedh/2))*2;
+            size = ALIGN(size, 4096);
+            break;
+
+        default:
+            LOGE("unrecognized pixel format: %d", format);
+            return -EINVAL;
+    }
+
+    if ((ssize_t)size <= 0)
+        return -EINVAL;
+
+    size = (bufferSize >= size)? bufferSize : size;
+
+    // All buffers marked as protected or for external
+    // display need to go to overlay
+    if ((usage & GRALLOC_USAGE_EXTERNAL_DISP) ||
+        (usage & GRALLOC_USAGE_PROTECTED)) {
+            bufferType = BUFFER_TYPE_VIDEO;
+    }
+    int err;
+    if (usage & GRALLOC_USAGE_HW_FB) {
+        err = gralloc_alloc_framebuffer(size, usage, pHandle);
+    } else {
+        err = gralloc_alloc_buffer(size, usage, pHandle, bufferType, format, alignedw, alignedh);
+    }
+
+    if (err < 0) {
+        return err;
+    }
+
+    *pStride = alignedw;
+    return 0;
+}
+
+int gpu_context_t::free_impl(private_handle_t const* hnd) {
+    private_module_t* m = reinterpret_cast<private_module_t*>(common.module);
+    if (hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER) {
+        // free this buffer
+        const size_t bufferSize = m->finfo.line_length * m->info.yres;
+        int index = (hnd->base - m->framebuffer->base) / bufferSize;
+        m->bufferMask &= ~(1<<index); 
+    } else {
+        PmemAllocator* pmem_allocator = 0;
+        if (hnd->flags & private_handle_t::PRIV_FLAGS_USES_PMEM) {
+            pmem_allocator = &pmemAllocator;
+        } else if (hnd->flags & private_handle_t::PRIV_FLAGS_USES_PMEM_ADSP) {
+            pmem_allocator = &pmemAdspAllocator;
+        } else if (hnd->flags & private_handle_t::PRIV_FLAGS_USES_ASHMEM) {
+            // free ashmem
+            if (hnd->fd >= 0) {
+                if (hnd->base) {
+                    int err = munmap((void*)hnd->base, hnd->size);
+                    LOGE_IF(err<0, "ASHMEM_UNMAP failed (%s), "
+                        "fd=%d, sub.offset=%d, sub.size=%d",
+                        strerror(errno), hnd->fd, hnd->offset, hnd->size);
+                }
+            }
+        }
+        if (pmem_allocator) {
+            pmem_allocator->free_pmem_buffer(hnd->size, (void*)hnd->base,
+                    hnd->offset, hnd->fd);
+        }
+
+        deps.terminateBuffer(&m->base, const_cast<private_handle_t*>(hnd));
+    }
+
+    deps.close(hnd->fd);
+    delete hnd; // XXX JMG: move this to the deps
+    return 0;
+}
+
+/******************************************************************************
+ * Static functions
+ *****************************************************************************/
+
+int gpu_context_t::gralloc_alloc(alloc_device_t* dev, int w, int h, int format,
+        int usage, buffer_handle_t* pHandle, int* pStride)
+{
+    if (!dev) {
+        return -EINVAL;
+    }
+    gpu_context_t* gpu = reinterpret_cast<gpu_context_t*>(dev);
+    return gpu->alloc_impl(w, h, format, usage, pHandle, pStride, 0);
+}
+
+int gpu_context_t::gralloc_alloc_size(alloc_device_t* dev, int w, int h, int format,
+        int usage, buffer_handle_t* pHandle, int* pStride, int bufferSize)
+{
+    if (!dev) {
+        return -EINVAL;
+    }
+    gpu_context_t* gpu = reinterpret_cast<gpu_context_t*>(dev);
+    return gpu->alloc_impl(w, h, format, usage, pHandle, pStride, bufferSize);
+}
+
+int gpu_context_t::gralloc_free(alloc_device_t* dev,
+                                    buffer_handle_t handle)
+{
+    if (private_handle_t::validate(handle) < 0)
+        return -EINVAL;
+
+    private_handle_t const* hnd = reinterpret_cast<private_handle_t const*>(handle);
+    gpu_context_t* gpu = reinterpret_cast<gpu_context_t*>(dev);
+    return gpu->free_impl(hnd);
+}
+
+/*****************************************************************************/
+
+int gpu_context_t::gralloc_close(struct hw_device_t *dev)
+{
+    gpu_context_t* ctx = reinterpret_cast<gpu_context_t*>(dev);
+    if (ctx) {
+        /* TODO: keep a list of all buffer_handle_t created, and free them
+         * all here.
+         */
+        delete ctx;
+    }
+    return 0;
+}
+
+
+gpu_context_t::Deps::~Deps() {}
diff --git a/libgralloc-qsd8k/gpu.h b/libgralloc-qsd8k/gpu.h
new file mode 100755
index 0000000..3ef57d3
--- /dev/null
+++ b/libgralloc-qsd8k/gpu.h
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef GRALLOC_QSD8K_GPU_H_
+#define GRALLOC_QSD8K_GPU_H_
+
+#include <errno.h>
+#include <pthread.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <cutils/log.h>
+#include <cutils/ashmem.h>
+
+#include "gralloc_priv.h"
+#include "pmemalloc.h"
+
+
+class gpu_context_t : public alloc_device_t {
+ public:
+
+    class Deps {
+     public:
+
+        virtual ~Deps();
+
+        // ashmem
+        virtual int ashmem_create_region(const char *name, size_t size) = 0;
+
+        // POSIX
+        virtual int close(int fd) = 0;
+
+        // Framebuffer (locally defined)
+        virtual int mapFrameBufferLocked(struct private_module_t* module) = 0;
+        virtual int terminateBuffer(gralloc_module_t const* module,
+            private_handle_t* hnd) = 0;
+    };
+
+    gpu_context_t(Deps& deps, PmemAllocator& pmemAllocator,
+            PmemAllocator& pmemAdspAllocator, const private_module_t* module);
+
+    int gralloc_alloc_framebuffer_locked(size_t size, int usage,
+            buffer_handle_t* pHandle);
+    int gralloc_alloc_framebuffer(size_t size, int usage,
+            buffer_handle_t* pHandle);
+    int gralloc_alloc_buffer(size_t size, int usage, buffer_handle_t* pHandle, int bufferType, int format,
+                             int width, int height);
+    int free_impl(private_handle_t const* hnd);
+    int alloc_impl(int w, int h, int format, int usage,
+            buffer_handle_t* pHandle, int* pStride, int bufferSize = 0);
+
+    static int gralloc_alloc(alloc_device_t* dev, int w, int h, int format,
+            int usage, buffer_handle_t* pHandle, int* pStride);
+    static int gralloc_free(alloc_device_t* dev, buffer_handle_t handle);
+    static int gralloc_alloc_size(alloc_device_t* dev, int w, int h, int format,
+            int usage, buffer_handle_t* pHandle, int* pStride, int bufferSize);
+    static int gralloc_close(struct hw_device_t *dev);
+    int get_composition_type() const { return compositionType; }
+
+ private:
+
+    Deps& deps;
+    PmemAllocator& pmemAllocator;
+    PmemAllocator& pmemAdspAllocator;
+    int compositionType;
+    int alloc_ashmem_buffer(size_t size, unsigned int postfix, void** pBase,
+            int* pOffset, int* pFd);
+    void getGrallocInformationFromFormat(int inputFormat, int *colorFormat, int *bufferType);
+};
+
+#endif  // GRALLOC_QSD8K_GPU_H
diff --git a/libgralloc-qsd8k/gr.h b/libgralloc-qsd8k/gr.h
new file mode 100644
index 0000000..49a0513
--- /dev/null
+++ b/libgralloc-qsd8k/gr.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef GR_H_
+#define GR_H_
+
+#include <stdint.h>
+#ifdef HAVE_ANDROID_OS      // just want PAGE_SIZE define
+# include <asm/page.h>
+#else
+# include <sys/user.h>
+#endif
+#include <limits.h>
+#include <sys/cdefs.h>
+#include <hardware/gralloc.h>
+#include <pthread.h>
+#include <errno.h>
+
+#include <cutils/native_handle.h>
+
+/*****************************************************************************/
+
+struct private_module_t;
+struct private_handle_t;
+
+inline size_t roundUpToPageSize(size_t x) {
+    return (x + (PAGE_SIZE-1)) & ~(PAGE_SIZE-1);
+}
+
+#define FALSE 0
+#define TRUE  1
+
+int mapFrameBufferLocked(struct private_module_t* module);
+int terminateBuffer(gralloc_module_t const* module, private_handle_t* hnd);
+size_t calculateBufferSize(int width, int height, int format);
+int decideBufferHandlingMechanism(int format, const char *compositionUsed,
+                                   int hasBlitEngine, int *needConversion,
+                                   int *useBufferDirectly);
+/*****************************************************************************/
+
+class Locker {
+    pthread_mutex_t mutex;
+public:
+    class Autolock {
+        Locker& locker;
+    public:
+        inline Autolock(Locker& locker) : locker(locker) {  locker.lock(); }
+        inline ~Autolock() { locker.unlock(); }
+    };
+    inline Locker()        { pthread_mutex_init(&mutex, 0); }
+    inline ~Locker()       { pthread_mutex_destroy(&mutex); }
+    inline void lock()     { pthread_mutex_lock(&mutex); }
+    inline void unlock()   { pthread_mutex_unlock(&mutex); }
+};
+
+#endif /* GR_H_ */
diff --git a/libgralloc-qsd8k/gralloc.cpp b/libgralloc-qsd8k/gralloc.cpp
new file mode 100755
index 0000000..bfade0a
--- /dev/null
+++ b/libgralloc-qsd8k/gralloc.cpp
@@ -0,0 +1,231 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <unistd.h>
+#include <fcntl.h>
+
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/ioctl.h>
+
+#include <linux/android_pmem.h>
+
+#include "allocator.h"
+#include "gr.h"
+#include "gpu.h"
+
+/*****************************************************************************/
+
+static int gralloc_alloc_buffer(alloc_device_t* dev,
+        size_t size, int usage, buffer_handle_t* pHandle);
+
+/*****************************************************************************/
+
+int fb_device_open(const hw_module_t* module, const char* name,
+        hw_device_t** device);
+
+static int gralloc_device_open(const hw_module_t* module, const char* name,
+        hw_device_t** device);
+
+extern int gralloc_lock(gralloc_module_t const* module,
+        buffer_handle_t handle, int usage,
+        int l, int t, int w, int h,
+        void** vaddr);
+
+extern int gralloc_unlock(gralloc_module_t const* module, 
+        buffer_handle_t handle);
+
+extern int gralloc_register_buffer(gralloc_module_t const* module,
+        buffer_handle_t handle);
+
+extern int gralloc_unregister_buffer(gralloc_module_t const* module,
+        buffer_handle_t handle);
+
+extern int gralloc_perform(struct gralloc_module_t const* module,
+        int operation, ... );
+
+/*****************************************************************************/
+
+/* On-device dependency implementation */
+class PmemAllocatorDepsDeviceImpl : public PmemUserspaceAllocator::Deps,
+        public PmemKernelAllocator::Deps {
+
+    const private_module_t* module;
+
+    virtual size_t getPmemTotalSize(int fd, size_t* size) {
+        int err = 0;
+#ifndef TARGET_MSM7x27
+        pmem_region region;
+        err = ioctl(fd, PMEM_GET_TOTAL_SIZE, &region);
+        if (err == 0) {
+            *size = region.len;
+        }
+#else
+#ifdef USE_ASHMEM
+        if(module != NULL)
+            *size = module->info.xres * module->info.yres * 2 * 2;
+        else
+            return -ENOMEM;
+#else
+	*size = 23<<20; //23MB for 7x27
+#endif
+#endif
+        return err;
+    }
+
+    virtual int connectPmem(int fd, int master_fd) {
+        return ioctl(fd, PMEM_CONNECT, master_fd);
+    }
+
+    virtual int mapPmem(int fd, int offset, size_t size) {
+        struct pmem_region sub = { offset, size };
+        return ioctl(fd, PMEM_MAP, &sub);
+    }
+
+    virtual int unmapPmem(int fd, int offset, size_t size) {
+        struct pmem_region sub = { offset, size };
+        return ioctl(fd, PMEM_UNMAP, &sub);
+    }
+
+    virtual int alignPmem(int fd, size_t size, int align) {
+        struct pmem_allocation allocation;
+        allocation.size = size;
+        allocation.align = align;
+        return ioctl(fd, PMEM_ALLOCATE_ALIGNED, &allocation);
+    }
+
+    virtual int cleanPmem(int fd, unsigned long base, int offset, size_t size) {
+        struct pmem_addr pmem_addr;
+        pmem_addr.vaddr = base;
+        pmem_addr.offset = offset;
+        pmem_addr.length = size;
+        return ioctl(fd, PMEM_CLEAN_INV_CACHES, &pmem_addr);
+    }
+
+    virtual int getErrno() {
+        return errno;
+    }
+
+    virtual void* mmap(void* start, size_t length, int prot, int flags, int fd,
+            off_t offset) {
+        return ::mmap(start, length, prot, flags, fd, offset);
+    }
+
+    virtual int munmap(void* start, size_t length) {
+        return ::munmap(start, length);
+    }
+
+    virtual int open(const char* pathname, int flags, int mode) {
+        return ::open(pathname, flags, mode);
+    }
+
+    virtual int close(int fd) {
+        return ::close(fd);
+    }
+
+public:
+    void setModule(const private_module_t* m) {
+        module = m;
+    }
+
+};
+
+class GpuContextDepsDeviceImpl : public gpu_context_t::Deps {
+
+ public:
+
+    virtual int ashmem_create_region(const char *name, size_t size) {
+        return ::ashmem_create_region(name, size);
+    }
+
+    virtual int mapFrameBufferLocked(struct private_module_t* module) {
+        return ::mapFrameBufferLocked(module);
+    }
+
+    virtual int terminateBuffer(gralloc_module_t const* module,
+            private_handle_t* hnd) {
+        return ::terminateBuffer(module, hnd);
+    }
+
+    virtual int close(int fd) {
+        return ::close(fd);
+    }
+};
+
+static PmemAllocatorDepsDeviceImpl pmemAllocatorDeviceDepsImpl;
+static GpuContextDepsDeviceImpl gpuContextDeviceDepsImpl;
+
+/*****************************************************************************/
+
+static SimpleBestFitAllocator pmemAllocMgr;
+static PmemUserspaceAllocator pmemAllocator(pmemAllocatorDeviceDepsImpl, pmemAllocMgr,
+        "/dev/pmem");
+
+static PmemKernelAllocator pmemAdspAllocator(pmemAllocatorDeviceDepsImpl);
+
+/*****************************************************************************/
+
+static struct hw_module_methods_t gralloc_module_methods = {
+    open: gralloc_device_open
+};
+
+struct private_module_t HAL_MODULE_INFO_SYM = {
+    base: {
+        common: {
+            tag: HARDWARE_MODULE_TAG,
+            version_major: 1,
+            version_minor: 0,
+            id: GRALLOC_HARDWARE_MODULE_ID,
+            name: "Graphics Memory Allocator Module",
+            author: "The Android Open Source Project",
+            methods: &gralloc_module_methods
+        },
+        registerBuffer: gralloc_register_buffer,
+        unregisterBuffer: gralloc_unregister_buffer,
+        lock: gralloc_lock,
+        unlock: gralloc_unlock,
+        perform: gralloc_perform,
+    },
+    framebuffer: 0,
+    fbFormat: 0,
+    flags: 0,
+    numBuffers: 0,
+    bufferMask: 0,
+    lock: PTHREAD_MUTEX_INITIALIZER,
+    currentBuffer: 0,
+};
+
+/*****************************************************************************/
+
+int gralloc_device_open(const hw_module_t* module, const char* name,
+        hw_device_t** device)
+{
+    int status = -EINVAL;
+    if (!strcmp(name, GRALLOC_HARDWARE_GPU0)) {
+        const private_module_t* m = reinterpret_cast<const private_module_t*>(
+                module);
+        pmemAllocatorDeviceDepsImpl.setModule(m);
+        gpu_context_t *dev;
+        dev = new gpu_context_t(gpuContextDeviceDepsImpl, pmemAllocator,
+                pmemAdspAllocator, m);
+        *device = &dev->common;
+        status = 0;
+    } else {
+        status = fb_device_open(module, name, device);
+    }
+    return status;
+}
diff --git a/libgralloc-qsd8k/gralloc_priv.h b/libgralloc-qsd8k/gralloc_priv.h
new file mode 100755
index 0000000..8037812
--- /dev/null
+++ b/libgralloc-qsd8k/gralloc_priv.h
@@ -0,0 +1,344 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef GRALLOC_PRIV_H_
+#define GRALLOC_PRIV_H_
+
+#include <stdint.h>
+#include <limits.h>
+#include <sys/cdefs.h>
+#include <hardware/gralloc.h>
+#include <pthread.h>
+#include <errno.h>
+#include <unistd.h>
+
+#include <cutils/native_handle.h>
+
+#include <linux/fb.h>
+
+#if defined(__cplusplus) && defined(HDMI_DUAL_DISPLAY)
+#include "overlayLib.h"
+using namespace overlay;
+#endif
+
+enum {
+    /* gralloc usage bits indicating the type
+     * of allocation that should be used */
+    GRALLOC_USAGE_PRIVATE_ADSP_HEAP = GRALLOC_USAGE_PRIVATE_0,
+    GRALLOC_USAGE_PRIVATE_EBI_HEAP = GRALLOC_USAGE_PRIVATE_1,
+    GRALLOC_USAGE_PRIVATE_SMI_HEAP = GRALLOC_USAGE_PRIVATE_2,
+    GRALLOC_USAGE_PRIVATE_SYSTEM_HEAP = GRALLOC_USAGE_PRIVATE_3,
+    /* Set this for allocating uncached memory (using O_DSYNC)
+     * cannot be used with the system heap */
+    GRALLOC_USAGE_PRIVATE_UNCACHED = 0x00010000,
+};
+
+enum {
+    GPU_COMPOSITION,
+    C2D_COMPOSITION,
+    MDP_COMPOSITION,
+    CPU_COMPOSITION,
+};
+
+/* numbers of max buffers for page flipping */
+#define NUM_FRAMEBUFFERS_MIN 2
+#define NUM_FRAMEBUFFERS_MAX 3
+
+/* number of default bufers for page flipping */
+#define NUM_DEF_FRAME_BUFFERS 2
+#define NO_SURFACEFLINGER_SWAPINTERVAL
+#define INTERLACE_MASK 0x80
+#define S3D_FORMAT_MASK 0xFF000
+#define COLOR_FORMAT(x) (x & 0xFFF) // Max range for colorFormats is 0 - FFF
+#define DEVICE_PMEM_ADSP "/dev/pmem_adsp"
+#define DEVICE_PMEM_SMIPOOL "/dev/pmem_smipool"
+/*****************************************************************************/
+#ifdef __cplusplus
+template <class T>
+struct Node
+{
+    T data;
+    Node<T> *next;
+};
+
+template <class T>
+class Queue
+{
+public:
+    Queue(): front(NULL), back(NULL), len(0) {dummy = new T;}
+    ~Queue()
+    {
+        clear();
+        delete dummy;
+    }
+    void push(const T& item)   //add an item to the back of the queue
+    {
+        if(len != 0) {         //if the queue is not empty
+            back->next = new Node<T>; //create a new node
+            back = back->next; //set the new node as the back node
+            back->data = item;
+            back->next = NULL;
+        } else {
+            back = new Node<T>;
+            back->data = item;
+            back->next = NULL;
+            front = back;
+       }
+       len++;
+    }
+    void pop()                 //remove the first item from the queue
+    {
+        if (isEmpty())
+            return;            //if the queue is empty, no node to dequeue
+        T item = front->data;
+        Node<T> *tmp = front;
+        front = front->next;
+        delete tmp;
+        if(front == NULL)      //if the queue is empty, update the back pointer
+            back = NULL;
+        len--;
+        return;
+    }
+    T& getHeadValue() const    //return the value of the first item in the queue
+    {                          //without modification to the structure
+        if (isEmpty()) {
+            LOGE("Error can't get head of empty queue");
+            return *dummy;
+        }
+        return front->data;
+    }
+
+    bool isEmpty() const       //returns true if no elements are in the queue
+    {
+        return (front == NULL);
+    }
+
+    size_t size() const        //returns the amount of elements in the queue
+    {
+        return len;
+    }
+
+private:
+    Node<T> *front;
+    Node<T> *back;
+    size_t len;
+    void clear()
+    {
+        while (!isEmpty())
+            pop();
+    }
+    T *dummy;
+};
+#endif
+
+enum {
+    /* OEM specific HAL formats */
+    //HAL_PIXEL_FORMAT_YCbCr_422_SP = 0x100, // defined in hardware.h
+    //HAL_PIXEL_FORMAT_YCrCb_420_SP = 0x101, // defined in hardware.h
+    HAL_PIXEL_FORMAT_YCbCr_422_P  = 0x102,
+    HAL_PIXEL_FORMAT_YCbCr_420_P  = 0x103,
+    //HAL_PIXEL_FORMAT_YCbCr_422_I  = 0x104, // defined in hardware.h
+    HAL_PIXEL_FORMAT_YCbCr_420_I  = 0x105,
+    HAL_PIXEL_FORMAT_CbYCrY_422_I = 0x106,
+    HAL_PIXEL_FORMAT_CbYCrY_420_I = 0x107,
+    HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED     = 0x108,
+    HAL_PIXEL_FORMAT_YCbCr_420_SP           = 0x109,
+    HAL_PIXEL_FORMAT_YCrCb_420_SP_ADRENO    = 0x10A,
+    HAL_PIXEL_FORMAT_YCrCb_422_SP           = 0x10B,
+    HAL_PIXEL_FORMAT_R_8                    = 0x10D,
+    HAL_PIXEL_FORMAT_RG_88                  = 0x10E,
+    HAL_PIXEL_FORMAT_INTERLACE              = 0x180,
+
+};
+
+/* possible formats for 3D content*/
+enum {
+    HAL_NO_3D                         = 0x0000,
+    HAL_3D_IN_SIDE_BY_SIDE_L_R        = 0x10000,
+    HAL_3D_IN_TOP_BOTTOM              = 0x20000,
+    HAL_3D_IN_INTERLEAVE              = 0x40000,
+    HAL_3D_IN_SIDE_BY_SIDE_R_L        = 0x80000,
+    HAL_3D_OUT_SIDE_BY_SIDE           = 0x1000,
+    HAL_3D_OUT_TOP_BOTTOM             = 0x2000,
+    HAL_3D_OUT_INTERLEAVE             = 0x4000,
+    HAL_3D_OUT_MONOSCOPIC             = 0x8000
+};
+
+enum {
+	BUFFER_TYPE_UI = 0,
+	BUFFER_TYPE_VIDEO
+};
+/*****************************************************************************/
+
+struct private_module_t;
+struct private_handle_t;
+struct PmemAllocator;
+
+struct qbuf_t {
+    buffer_handle_t buf;
+    int  idx;
+};
+
+enum buf_state {
+    SUB,
+    REF,
+    AVL
+};
+
+struct avail_t {
+    pthread_mutex_t lock;
+    pthread_cond_t cond;
+#ifdef __cplusplus
+    bool is_avail;
+    buf_state state;
+#endif
+};
+
+struct private_module_t {
+    gralloc_module_t base;
+
+    struct private_handle_t* framebuffer;
+    uint32_t fbFormat;
+    uint32_t flags;
+    uint32_t numBuffers;
+    uint32_t bufferMask;
+    pthread_mutex_t lock;
+    buffer_handle_t currentBuffer;
+
+    struct fb_var_screeninfo info;
+    struct fb_fix_screeninfo finfo;
+    float xdpi;
+    float ydpi;
+    float fps;
+    int swapInterval;
+#ifdef __cplusplus
+    Queue<struct qbuf_t> disp; // non-empty when buffer is ready for display    
+#endif
+    int currentIdx;
+    struct avail_t avail[NUM_FRAMEBUFFERS_MAX];
+    pthread_mutex_t qlock;
+    pthread_cond_t qpost;
+
+    enum {
+        // flag to indicate we'll post this buffer
+        PRIV_USAGE_LOCKED_FOR_POST = 0x80000000,
+        PRIV_MIN_SWAP_INTERVAL = 0,
+        PRIV_MAX_SWAP_INTERVAL = 1,
+    };
+#if defined(__cplusplus) && defined(HDMI_DUAL_DISPLAY)
+    Overlay* pobjOverlay;
+    int orientation;
+    bool videoOverlay;
+    uint32_t currentOffset;
+    bool enableHDMIOutput;
+    bool exitHDMIUILoop;
+    float actionsafeWidthRatio;
+    float actionsafeHeightRatio;
+    bool hdmiStateChanged;
+    pthread_mutex_t overlayLock;
+    pthread_cond_t overlayPost;
+#endif
+};
+
+/*****************************************************************************/
+
+#ifdef __cplusplus
+struct private_handle_t : public native_handle {
+#else
+struct private_handle_t {
+    native_handle_t nativeHandle;
+#endif
+    
+    enum {
+        PRIV_FLAGS_FRAMEBUFFER    = 0x00000001,
+        PRIV_FLAGS_USES_PMEM      = 0x00000002,
+        PRIV_FLAGS_USES_PMEM_ADSP = 0x00000004,
+        PRIV_FLAGS_USES_ION       = 0x00000008,
+        PRIV_FLAGS_USES_ASHMEM    = 0x00000010,
+        PRIV_FLAGS_NEEDS_FLUSH    = 0x00000020,
+        PRIV_FLAGS_DO_NOT_FLUSH   = 0x00000040,
+    };
+
+    enum {
+        LOCK_STATE_WRITE     =   1<<31,
+        LOCK_STATE_MAPPED    =   1<<30,
+        LOCK_STATE_READ_MASK =   0x3FFFFFFF
+    };
+
+    // file-descriptors
+    int     fd;
+    // ints
+    int     magic;
+    int     flags;
+    int     size;
+    int     offset;
+    int     bufferType;
+
+    // FIXME: the attributes below should be out-of-line
+    int     base;
+    int     lockState;
+    int     writeOwner;
+    int     gpuaddr; // The gpu address mapped into the mmu. If using ashmem, set to 0 They don't care
+    int     pid;
+    int     format;
+    int     width;
+    int     height;
+
+#ifdef __cplusplus
+    static const int sNumInts = 13;
+    static const int sNumFds = 1;
+    static const int sMagic = 'gmsm';
+
+    private_handle_t(int fd, int size, int flags, int bufferType, int format, int width, int height) :
+        fd(fd), magic(sMagic), flags(flags), size(size), offset(0), bufferType(bufferType),
+        base(0), lockState(0), writeOwner(0), gpuaddr(0), pid(getpid()), format(format), width(width),
+        height(height)
+    {
+        version = sizeof(native_handle);
+        numInts = sNumInts;
+        numFds = sNumFds;
+    }
+    ~private_handle_t() {
+        magic = 0;
+    }
+
+    bool usesPhysicallyContiguousMemory() {
+        return (flags & PRIV_FLAGS_USES_PMEM) != 0;
+    }
+
+    static int validate(const native_handle* h) {
+        const private_handle_t* hnd = (const private_handle_t*)h;
+        if (!h || h->version != sizeof(native_handle) ||
+                h->numInts != sNumInts || h->numFds != sNumFds ||
+                hnd->magic != sMagic) 
+        {
+            LOGE("invalid gralloc handle (at %p)", h);
+            return -EINVAL;
+        }
+        return 0;
+    }
+
+    static private_handle_t* dynamicCast(const native_handle* in) {
+        if (validate(in) == 0) {
+            return (private_handle_t*) in;
+        }
+        return NULL;
+    }
+#endif
+};
+
+#endif /* GRALLOC_PRIV_H_ */
diff --git a/libgralloc-qsd8k/mapper.cpp b/libgralloc-qsd8k/mapper.cpp
new file mode 100755
index 0000000..0e495be
--- /dev/null
+++ b/libgralloc-qsd8k/mapper.cpp
@@ -0,0 +1,386 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <limits.h>
+#include <errno.h>
+#include <pthread.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdarg.h>
+
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <linux/ashmem.h>
+
+#include <cutils/log.h>
+#include <cutils/atomic.h>
+#include <cutils/ashmem.h>
+
+#include <hardware/hardware.h>
+#include <hardware/gralloc.h>
+
+#include <linux/android_pmem.h>
+
+#include "gralloc_priv.h"
+#include "gr.h"
+
+// we need this for now because pmem cannot mmap at an offset
+#define PMEM_HACK   1
+
+/* desktop Linux needs a little help with gettid() */
+#if defined(ARCH_X86) && !defined(HAVE_ANDROID_OS)
+#define __KERNEL__
+# include <linux/unistd.h>
+pid_t gettid() { return syscall(__NR_gettid);}
+#undef __KERNEL__
+#endif
+
+/*****************************************************************************/
+
+static int gralloc_map(gralloc_module_t const* module,
+        buffer_handle_t handle,
+        void** vaddr)
+{
+    private_handle_t* hnd = (private_handle_t*)handle;
+    void *mappedAddress;
+    if (!(hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER)) {
+        size_t size = hnd->size;
+#if PMEM_HACK
+        size += hnd->offset;
+#endif
+        if (hnd->flags & private_handle_t::PRIV_FLAGS_USES_ASHMEM) {
+            mappedAddress = mmap(0, size,
+                PROT_READ|PROT_WRITE, MAP_SHARED | MAP_POPULATE, hnd->fd, 0);
+        } else {
+            mappedAddress = mmap(0, size,
+                PROT_READ|PROT_WRITE, MAP_SHARED, hnd->fd, 0);
+        }
+        if (mappedAddress == MAP_FAILED) {
+            LOGE("Could not mmap handle %p, fd=%d (%s)",
+                    handle, hnd->fd, strerror(errno));
+            hnd->base = 0;
+            return -errno;
+        }
+        hnd->base = intptr_t(mappedAddress) + hnd->offset;
+        //LOGD("gralloc_map() succeeded fd=%d, off=%d, size=%d, vaddr=%p", 
+        //        hnd->fd, hnd->offset, hnd->size, mappedAddress);
+    }
+    *vaddr = (void*)hnd->base;
+    return 0;
+}
+
+static int gralloc_unmap(gralloc_module_t const* module,
+        buffer_handle_t handle)
+{
+    private_handle_t* hnd = (private_handle_t*)handle;
+    if (!(hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER)) {
+        void* base = (void*)hnd->base;
+        size_t size = hnd->size;
+#if PMEM_HACK
+        base = (void*)(intptr_t(base) - hnd->offset);
+        size += hnd->offset;
+#endif
+        //LOGD("unmapping from %p, size=%d", base, size);
+        if (munmap(base, size) < 0) {
+            LOGE("Could not unmap %s", strerror(errno));
+        }
+    }
+    hnd->base = 0;
+    return 0;
+}
+
+/*****************************************************************************/
+
+static pthread_mutex_t sMapLock = PTHREAD_MUTEX_INITIALIZER; 
+
+/*****************************************************************************/
+
+int gralloc_register_buffer(gralloc_module_t const* module,
+        buffer_handle_t handle)
+{
+    if (private_handle_t::validate(handle) < 0)
+        return -EINVAL;
+
+    // In this implementation, we don't need to do anything here
+
+    /* NOTE: we need to initialize the buffer as not mapped/not locked
+     * because it shouldn't when this function is called the first time
+     * in a new process. Ideally these flags shouldn't be part of the
+     * handle, but instead maintained in the kernel or at least 
+     * out-of-line
+     */ 
+
+    // if this handle was created in this process, then we keep it as is.
+    private_handle_t* hnd = (private_handle_t*)handle;
+    if (hnd->pid != getpid()) {
+        hnd->base = 0;
+        hnd->lockState  = 0;
+        hnd->writeOwner = 0;
+    }
+    return 0;
+}
+
+int gralloc_unregister_buffer(gralloc_module_t const* module,
+        buffer_handle_t handle)
+{
+    if (private_handle_t::validate(handle) < 0)
+        return -EINVAL;
+
+    /*
+     * If the buffer has been mapped during a lock operation, it's time
+     * to un-map it. It's an error to be here with a locked buffer.
+     * NOTE: the framebuffer is handled differently and is never unmapped.
+     */
+
+    private_handle_t* hnd = (private_handle_t*)handle;
+    
+    LOGE_IF(hnd->lockState & private_handle_t::LOCK_STATE_READ_MASK,
+            "[unregister] handle %p still locked (state=%08x)",
+            hnd, hnd->lockState);
+
+    // never unmap buffers that were created in this process
+    if (hnd->pid != getpid()) {
+        if (hnd->lockState & private_handle_t::LOCK_STATE_MAPPED) {
+            gralloc_unmap(module, handle);
+        }
+        hnd->base = 0;
+        hnd->lockState  = 0;
+        hnd->writeOwner = 0;
+    }
+    return 0;
+}
+
+int terminateBuffer(gralloc_module_t const* module,
+        private_handle_t* hnd)
+{
+    /*
+     * If the buffer has been mapped during a lock operation, it's time
+     * to un-map it. It's an error to be here with a locked buffer.
+     */
+
+    LOGE_IF(hnd->lockState & private_handle_t::LOCK_STATE_READ_MASK,
+            "[terminate] handle %p still locked (state=%08x)",
+            hnd, hnd->lockState);
+
+    if (hnd->lockState & private_handle_t::LOCK_STATE_MAPPED) {
+        // this buffer was mapped, unmap it now
+        if (hnd->flags & (private_handle_t::PRIV_FLAGS_USES_PMEM |
+                          private_handle_t::PRIV_FLAGS_USES_PMEM_ADSP |
+                          private_handle_t::PRIV_FLAGS_USES_ASHMEM)) {
+            if (hnd->pid != getpid()) {
+                // ... unless it's a "master" pmem buffer, that is a buffer
+                // mapped in the process it's been allocated.
+                // (see gralloc_alloc_buffer())
+                gralloc_unmap(module, hnd);
+            }
+        } else {
+            LOGE("terminateBuffer: unmapping a non pmem/ashmem buffer flags = 0x%x", hnd->flags);
+            gralloc_unmap(module, hnd);
+        }
+    }
+
+    return 0;
+}
+
+int gralloc_lock(gralloc_module_t const* module,
+        buffer_handle_t handle, int usage,
+        int l, int t, int w, int h,
+        void** vaddr)
+{
+    if (private_handle_t::validate(handle) < 0)
+        return -EINVAL;
+
+    int err = 0;
+    private_handle_t* hnd = (private_handle_t*)handle;
+    int32_t current_value, new_value;
+    int retry;
+
+    do {
+        current_value = hnd->lockState;
+        new_value = current_value;
+
+        if (current_value & private_handle_t::LOCK_STATE_WRITE) {
+            // already locked for write 
+            LOGE("handle %p already locked for write", handle);
+            return -EBUSY;
+        } else if (current_value & private_handle_t::LOCK_STATE_READ_MASK) {
+            // already locked for read
+            if (usage & (GRALLOC_USAGE_SW_WRITE_MASK | GRALLOC_USAGE_HW_RENDER)) {
+                LOGE("handle %p already locked for read", handle);
+                return -EBUSY;
+            } else {
+                // this is not an error
+                //LOGD("%p already locked for read... count = %d", 
+                //        handle, (current_value & ~(1<<31)));
+            }
+        }
+
+        // not currently locked
+        if (usage & (GRALLOC_USAGE_SW_WRITE_MASK | GRALLOC_USAGE_HW_RENDER)) {
+            // locking for write
+            new_value |= private_handle_t::LOCK_STATE_WRITE;
+        }
+        new_value++;
+
+        retry = android_atomic_cmpxchg(current_value, new_value, 
+                (volatile int32_t*)&hnd->lockState);
+    } while (retry);
+
+    if (new_value & private_handle_t::LOCK_STATE_WRITE) {
+        // locking for write, store the tid
+        hnd->writeOwner = gettid();
+    }
+
+    // if requesting sw write for non-framebuffer handles, flag for
+    // flushing at unlock
+
+    if ((usage & GRALLOC_USAGE_SW_WRITE_MASK) &&
+            !(hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER)) {
+        hnd->flags |= private_handle_t::PRIV_FLAGS_NEEDS_FLUSH;
+    }
+
+    if (usage & (GRALLOC_USAGE_SW_READ_MASK | GRALLOC_USAGE_SW_WRITE_MASK)) {
+        if (!(current_value & private_handle_t::LOCK_STATE_MAPPED)) {
+            // we need to map for real
+            pthread_mutex_t* const lock = &sMapLock;
+            pthread_mutex_lock(lock);
+            if (!(hnd->lockState & private_handle_t::LOCK_STATE_MAPPED)) {
+                err = gralloc_map(module, handle, vaddr);
+                if (err == 0) {
+                    android_atomic_or(private_handle_t::LOCK_STATE_MAPPED,
+                            (volatile int32_t*)&(hnd->lockState));
+                }
+            }
+            pthread_mutex_unlock(lock);
+        }
+        *vaddr = (void*)hnd->base;
+    }
+
+    return err;
+}
+
+int gralloc_unlock(gralloc_module_t const* module, 
+        buffer_handle_t handle)
+{
+    if (private_handle_t::validate(handle) < 0)
+        return -EINVAL;
+
+    private_handle_t* hnd = (private_handle_t*)handle;
+    int32_t current_value, new_value;
+
+    if (hnd->flags & private_handle_t::PRIV_FLAGS_NEEDS_FLUSH) {
+        int err;
+        if (hnd->flags & (private_handle_t::PRIV_FLAGS_USES_PMEM |
+                          private_handle_t::PRIV_FLAGS_USES_PMEM_ADSP)) {
+            struct pmem_addr pmem_addr;
+            pmem_addr.vaddr = hnd->base;
+            pmem_addr.offset = hnd->offset;
+            pmem_addr.length = hnd->size;
+            err = ioctl( hnd->fd, PMEM_CLEAN_CACHES,  &pmem_addr);
+        } else if ((hnd->flags & private_handle_t::PRIV_FLAGS_USES_ASHMEM)) {
+            unsigned long addr = hnd->base + hnd->offset;
+            err = ioctl(hnd->fd, ASHMEM_CACHE_FLUSH_RANGE, NULL);
+        }         
+
+        LOGE_IF(err < 0, "cannot flush handle %p (offs=%x len=%x, flags = 0x%x) err=%s\n",
+                hnd, hnd->offset, hnd->size, hnd->flags, strerror(errno));
+        hnd->flags &= ~private_handle_t::PRIV_FLAGS_NEEDS_FLUSH;
+    }
+
+    do {
+        current_value = hnd->lockState;
+        new_value = current_value;
+
+        if (current_value & private_handle_t::LOCK_STATE_WRITE) {
+            // locked for write
+            if (hnd->writeOwner == gettid()) {
+                hnd->writeOwner = 0;
+                new_value &= ~private_handle_t::LOCK_STATE_WRITE;
+            }
+        }
+
+        if ((new_value & private_handle_t::LOCK_STATE_READ_MASK) == 0) {
+            LOGE("handle %p not locked", handle);
+            return -EINVAL;
+        }
+
+        new_value--;
+
+    } while (android_atomic_cmpxchg(current_value, new_value, 
+            (volatile int32_t*)&hnd->lockState));
+
+    return 0;
+}
+
+/*****************************************************************************/
+
+int gralloc_perform(struct gralloc_module_t const* module,
+        int operation, ... )
+{
+    int res = -EINVAL;
+    va_list args;
+    va_start(args, operation);
+
+    switch (operation) {
+        case GRALLOC_MODULE_PERFORM_CREATE_HANDLE_FROM_BUFFER: {
+            int fd = va_arg(args, int);
+            size_t size = va_arg(args, size_t);
+            size_t offset = va_arg(args, size_t);
+            void* base = va_arg(args, void*);
+
+            // validate that it's indeed a pmem buffer
+            pmem_region region;
+            if (ioctl(fd, PMEM_GET_SIZE, &region) < 0) {
+                break;
+            }
+
+            native_handle_t** handle = va_arg(args, native_handle_t**);
+            private_handle_t* hnd = (private_handle_t*)native_handle_create(
+                    private_handle_t::sNumFds, private_handle_t::sNumInts);
+            hnd->magic = private_handle_t::sMagic;
+            hnd->fd = fd;
+            hnd->flags = private_handle_t::PRIV_FLAGS_USES_PMEM;
+            hnd->size = size;
+            hnd->offset = offset;
+            hnd->base = intptr_t(base) + offset;
+            hnd->lockState = private_handle_t::LOCK_STATE_MAPPED;
+            hnd->gpuaddr = 0;
+            *handle = (native_handle_t *)hnd;
+            res = 0;
+            break;
+        }
+        case GRALLOC_MODULE_PERFORM_UPDATE_BUFFER_HANDLE: {
+            native_handle_t* handle = va_arg(args, native_handle_t*);
+            int w = va_arg(args, int);
+            int h = va_arg(args, int);
+            int f = va_arg(args, int);
+            private_handle_t* hnd = (private_handle_t*)handle;
+            hnd->width = w;
+            hnd->height = h;
+            if (hnd->format != f) {
+                hnd->format = f;
+            }
+            break;
+        }
+	default:
+	    break;
+    }
+
+    va_end(args);
+    return res;
+}
diff --git a/libgralloc-qsd8k/pmemalloc.cpp b/libgralloc-qsd8k/pmemalloc.cpp
new file mode 100755
index 0000000..fce2d87
--- /dev/null
+++ b/libgralloc-qsd8k/pmemalloc.cpp
@@ -0,0 +1,360 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+
+#include <limits.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <pthread.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <sys/mman.h>
+
+#include <cutils/log.h>
+#include <cutils/ashmem.h>
+
+#include "gralloc_priv.h"
+#include "pmemalloc.h"
+
+
+#define BEGIN_FUNC LOGV("%s begin", __PRETTY_FUNCTION__)
+#define END_FUNC LOGV("%s end", __PRETTY_FUNCTION__)
+
+
+static int get_open_flags(int usage) {
+    int openFlags = O_RDWR | O_SYNC;
+    uint32_t uread = usage & GRALLOC_USAGE_SW_READ_MASK;
+    uint32_t uwrite = usage & GRALLOC_USAGE_SW_WRITE_MASK;
+    if (uread == GRALLOC_USAGE_SW_READ_OFTEN ||
+        uwrite == GRALLOC_USAGE_SW_WRITE_OFTEN) {
+        openFlags &= ~O_SYNC;
+    }
+    return openFlags;
+}
+
+PmemAllocator::~PmemAllocator()
+{
+    BEGIN_FUNC;
+    END_FUNC;
+}
+
+
+PmemUserspaceAllocator::PmemUserspaceAllocator(Deps& deps, Deps::Allocator& allocator, const char* pmemdev):
+    deps(deps),
+    allocator(allocator),
+    pmemdev(pmemdev),
+    master_fd(MASTER_FD_INIT)
+{
+    BEGIN_FUNC;
+    pthread_mutex_init(&lock, NULL);
+    END_FUNC;
+}
+
+
+PmemUserspaceAllocator::~PmemUserspaceAllocator()
+{
+    BEGIN_FUNC;
+    END_FUNC;
+}
+
+
+void* PmemUserspaceAllocator::get_base_address() {
+    BEGIN_FUNC;
+    END_FUNC;
+    return master_base;
+}
+
+
+int PmemUserspaceAllocator::init_pmem_area_locked()
+{
+    BEGIN_FUNC;
+    int err = 0;
+    int fd = deps.open(pmemdev, O_RDWR, 0);
+    if (fd >= 0) {
+        size_t size = 0;
+        err = deps.getPmemTotalSize(fd, &size);
+        if (err < 0) {
+            LOGE("%s: PMEM_GET_TOTAL_SIZE failed (%d), limp mode", pmemdev,
+                    err);
+            size = 8<<20;   // 8 MiB
+        }
+        allocator.setSize(size);
+
+        void* base = deps.mmap(0, size, PROT_READ|PROT_WRITE, MAP_SHARED, fd,
+                0);
+        if (base == MAP_FAILED) {
+            LOGE("%s: failed to map pmem master fd: %s", pmemdev,
+                    strerror(deps.getErrno()));
+            err = -deps.getErrno();
+            base = 0;
+            deps.close(fd);
+            fd = -1;
+        } else {
+            master_fd = fd;
+            master_base = base;
+        }
+    } else {
+        LOGE("%s: failed to open pmem device: %s", pmemdev,
+                strerror(deps.getErrno()));
+        err = -deps.getErrno();
+    }
+    END_FUNC;
+    return err;
+}
+
+
+int PmemUserspaceAllocator::init_pmem_area()
+{
+    BEGIN_FUNC;
+    pthread_mutex_lock(&lock);
+    int err = master_fd;
+    if (err == MASTER_FD_INIT) {
+        // first time, try to initialize pmem
+        err = init_pmem_area_locked();
+        if (err) {
+            LOGE("%s: failed to initialize pmem area", pmemdev);
+            master_fd = err;
+        }
+    } else if (err < 0) {
+        // pmem couldn't be initialized, never use it
+    } else {
+        // pmem OK
+        err = 0;
+    }
+    pthread_mutex_unlock(&lock);
+    END_FUNC;
+    return err;
+}
+
+
+int PmemUserspaceAllocator::alloc_pmem_buffer(size_t size, int usage,
+        void** pBase, int* pOffset, int* pFd, int format)
+{
+    BEGIN_FUNC;
+    int err = init_pmem_area();
+    if (err == 0) {
+        void* base = master_base;
+        int offset = allocator.allocate(size);
+        if (offset < 0) {
+            // no more pmem memory
+            LOGE("%s: no more pmem available", pmemdev);
+            err = -ENOMEM;
+        } else {
+            int openFlags = get_open_flags(usage);
+
+            //LOGD("%s: allocating pmem at offset 0x%p", pmemdev, offset);
+
+            // now create the "sub-heap"
+            int fd = deps.open(pmemdev, openFlags, 0);
+            err = fd < 0 ? fd : 0;
+
+            // and connect to it
+            if (err == 0)
+                err = deps.connectPmem(fd, master_fd);
+
+            // and make it available to the client process
+            if (err == 0)
+                err = deps.mapPmem(fd, offset, size);
+
+            if (err < 0) {
+                LOGE("%s: failed to initialize pmem sub-heap: %d", pmemdev,
+                        err);
+                err = -deps.getErrno();
+                deps.close(fd);
+                allocator.deallocate(offset);
+                fd = -1;
+            } else {
+                LOGV("%s: mapped fd %d at offset %d, size %d", pmemdev, fd, offset, size);
+                memset((char*)base + offset, 0, size);
+                //Clean cache before flushing to ensure pmem is properly flushed
+                err = deps.cleanPmem(fd, (unsigned long) base + offset, offset, size);
+                if (err < 0) {
+                    LOGE("cleanPmem failed: (%s)", strerror(deps.getErrno()));
+                }
+#ifdef HOST
+                 cacheflush(intptr_t(base) + offset, intptr_t(base) + offset + size, 0);
+#endif
+                *pBase = base;
+                *pOffset = offset;
+                *pFd = fd;
+            }
+            //LOGD_IF(!err, "%s: allocating pmem size=%d, offset=%d", pmemdev, size, offset);
+        }
+    }
+    END_FUNC;
+    return err;
+}
+
+
+int PmemUserspaceAllocator::free_pmem_buffer(size_t size, void* base, int offset, int fd)
+{
+    BEGIN_FUNC;
+    int err = 0;
+    if (fd >= 0) {
+        int err = deps.unmapPmem(fd, offset, size);
+        LOGE_IF(err<0, "PMEM_UNMAP failed (%s), fd=%d, sub.offset=%u, "
+                "sub.size=%u", strerror(deps.getErrno()), fd, offset, size);
+        if (err == 0) {
+            // we can't deallocate the memory in case of UNMAP failure
+            // because it would give that process access to someone else's
+            // surfaces, which would be a security breach.
+            allocator.deallocate(offset);
+        }
+    }
+    END_FUNC;
+    return err;
+}
+
+PmemUserspaceAllocator::Deps::Allocator::~Allocator()
+{
+    BEGIN_FUNC;
+    END_FUNC;
+}
+
+PmemUserspaceAllocator::Deps::~Deps()
+{
+    BEGIN_FUNC;
+    END_FUNC;
+}
+
+PmemKernelAllocator::PmemKernelAllocator(Deps& deps):
+    deps(deps)
+{
+    BEGIN_FUNC;
+    END_FUNC;
+}
+
+
+PmemKernelAllocator::~PmemKernelAllocator()
+{
+    BEGIN_FUNC;
+    END_FUNC;
+}
+
+
+void* PmemKernelAllocator::get_base_address() {
+    BEGIN_FUNC;
+    END_FUNC;
+    return 0;
+}
+
+
+static unsigned clp2(unsigned x) {
+    x = x - 1;
+    x = x | (x >> 1);
+    x = x | (x >> 2);
+    x = x | (x >> 4);
+    x = x | (x >> 8);
+    x = x | (x >>16);
+    return x + 1;
+}
+
+
+int PmemKernelAllocator::alloc_pmem_buffer(size_t size, int usage,
+        void** pBase,int* pOffset, int* pFd, int format)
+{
+    BEGIN_FUNC;
+
+    *pBase = 0;
+    *pOffset = 0;
+    *pFd = -1;
+
+    int err, offset = 0;
+    int openFlags = get_open_flags(usage);
+    const char *device;
+    
+    if (usage & GRALLOC_USAGE_PRIVATE_ADSP_HEAP) {
+        device = DEVICE_PMEM_ADSP;
+    } else if (usage & GRALLOC_USAGE_PRIVATE_SMI_HEAP) {
+        device = DEVICE_PMEM_SMIPOOL;
+    } else if ((usage & GRALLOC_USAGE_EXTERNAL_DISP) ||
+               (usage & GRALLOC_USAGE_PROTECTED)) {
+        int tempFd = deps.open(DEVICE_PMEM_SMIPOOL, openFlags, 0);
+        if (tempFd < 0) {
+            device = DEVICE_PMEM_ADSP;
+        } else {
+            close(tempFd);
+            device = DEVICE_PMEM_SMIPOOL;
+        }
+    } else {
+        LOGE("Invalid device");
+        return -EINVAL;
+    }
+
+    int fd = deps.open(device, openFlags, 0);
+    if (fd < 0) {
+        err = -deps.getErrno();
+        END_FUNC;
+        LOGE("Error opening %s", device);
+        return err;
+    }
+
+    // The size should already be page aligned, now round it up to a power of 2.
+    //size = clp2(size);
+
+    if (format == HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED) {
+        // Tile format buffers need physical alignment to 8K
+        err = deps.alignPmem(fd, size, 8192);
+        if (err < 0) {
+            LOGE("alignPmem failed");
+        }
+    }
+
+    void* base = deps.mmap(0, size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
+    if (base == MAP_FAILED) {
+        LOGE("%s: failed to map pmem fd: %s", device,
+             strerror(deps.getErrno()));
+        err = -deps.getErrno();
+        deps.close(fd);
+        END_FUNC;
+        return err;
+    }
+    memset(base, 0, size);
+
+    *pBase = base;
+    *pOffset = 0;
+    *pFd = fd;
+
+    END_FUNC;
+    return 0;
+}
+
+
+int PmemKernelAllocator::free_pmem_buffer(size_t size, void* base, int offset, int fd)
+{
+    BEGIN_FUNC;
+    // The size should already be page aligned, now round it up to a power of 2
+    // like we did when allocating.
+    //size = clp2(size);
+
+    int err = deps.munmap(base, size);
+    if (err < 0) {
+        err = deps.getErrno();
+        LOGW("error unmapping pmem fd: %s", strerror(err));
+        return -err;
+    }
+
+    END_FUNC;
+    return 0;
+}
+
+PmemKernelAllocator::Deps::~Deps()
+{
+    BEGIN_FUNC;
+    END_FUNC;
+}
diff --git a/libgralloc-qsd8k/pmemalloc.h b/libgralloc-qsd8k/pmemalloc.h
new file mode 100755
index 0000000..2a1c6fd
--- /dev/null
+++ b/libgralloc-qsd8k/pmemalloc.h
@@ -0,0 +1,161 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef GRALLOC_QSD8K_PMEMALLOC_H
+#define GRALLOC_QSD8K_PMEMALLOC_H
+
+#include <limits.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <unistd.h>
+
+
+/**
+ * An interface to the PMEM allocators.
+ */
+class PmemAllocator {
+
+ public:
+
+    virtual ~PmemAllocator();
+
+    // Only valid after init_pmem_area() has completed successfully.
+    virtual void* get_base_address() = 0;
+
+    virtual int alloc_pmem_buffer(size_t size, int usage, void** pBase,
+            int* pOffset, int* pFd, int format) = 0;
+    virtual int free_pmem_buffer(size_t size, void* base, int offset, int fd) = 0;
+};
+
+
+/**
+ * A PMEM allocator that allocates the entire pmem memory from the kernel and
+ * then uses a user-space allocator to suballocate from that.  This requires
+ * that the PMEM device driver have kernel allocation disabled.
+ */
+class PmemUserspaceAllocator: public PmemAllocator {
+
+ public:
+
+    class Deps {
+     public:
+
+        class Allocator {
+         public:
+            virtual ~Allocator();
+            virtual ssize_t setSize(size_t size) = 0;
+            virtual size_t  size() const = 0;
+            virtual ssize_t allocate(size_t size, uint32_t flags = 0) = 0;
+            virtual ssize_t deallocate(size_t offset) = 0;
+        };
+
+        virtual ~Deps();
+
+        // pmem
+        virtual size_t getPmemTotalSize(int fd, size_t* size) = 0;
+        virtual int connectPmem(int fd, int master_fd) = 0;
+        virtual int mapPmem(int fd, int offset, size_t size) = 0;
+        virtual int unmapPmem(int fd, int offset, size_t size) = 0;
+        virtual int cleanPmem(int fd, unsigned long base, int offset, size_t size) = 0;
+
+        // C99
+        virtual int getErrno() = 0;
+
+        // POSIX
+        virtual void* mmap(void* start, size_t length, int prot, int flags, int fd,
+                off_t offset) = 0;
+        virtual int open(const char* pathname, int flags, int mode) = 0;
+        virtual int close(int fd) = 0;
+    };
+
+    PmemUserspaceAllocator(Deps& deps, Deps::Allocator& allocator, const char* pmemdev);
+    virtual ~PmemUserspaceAllocator();
+
+    // Only valid after init_pmem_area() has completed successfully.
+    virtual void* get_base_address();
+
+    virtual int init_pmem_area_locked();
+    virtual int init_pmem_area();
+    virtual int alloc_pmem_buffer(size_t size, int usage, void** pBase,
+            int* pOffset, int* pFd, int format);
+    virtual int free_pmem_buffer(size_t size, void* base, int offset, int fd);
+
+#ifndef ANDROID_OS
+    // DO NOT USE: For testing purposes only.
+    void set_master_values(int fd, void* base) {
+        master_fd = fd;
+        master_base = base;
+    }
+#endif // ANDROID_OS
+
+ private:
+
+    enum {
+        MASTER_FD_INIT = -1,
+    };
+
+    Deps& deps;
+    Deps::Allocator& allocator;
+
+    pthread_mutex_t lock;
+    const char* pmemdev;
+    int master_fd;
+    void* master_base;
+};
+
+
+/**
+ * A PMEM allocator that allocates each individual allocation from the kernel
+ * (using the kernel's allocator).  This requires the kernel driver for the
+ * particular PMEM device being allocated from to support kernel allocation.
+ */
+class PmemKernelAllocator: public PmemAllocator {
+
+ public:
+
+    class Deps {
+     public:
+
+        virtual ~Deps();
+
+        // C99
+        virtual int getErrno() = 0;
+
+        // POSIX
+        virtual void* mmap(void* start, size_t length, int prot, int flags, int fd,
+                off_t offset) = 0;
+        virtual int munmap(void* start, size_t length) = 0;
+        virtual int open(const char* pathname, int flags, int mode) = 0;
+        virtual int close(int fd) = 0;
+        virtual int alignPmem(int fd, size_t size, int align) = 0;
+    };
+
+    PmemKernelAllocator(Deps& deps);
+    virtual ~PmemKernelAllocator();
+
+    // Only valid after init_pmem_area() has completed successfully.
+    virtual void* get_base_address();
+
+    virtual int alloc_pmem_buffer(size_t size, int usage, void** pBase,
+            int* pOffset, int* pFd, int format);
+    virtual int free_pmem_buffer(size_t size, void* base, int offset, int fd);
+
+ private:
+
+    Deps& deps;
+};
+
+#endif  // GRALLOC_QSD8K_PMEMALLOC_H
diff --git a/libgralloc-qsd8k/tests/Android.mk b/libgralloc-qsd8k/tests/Android.mk
new file mode 100644
index 0000000..b9a7459
--- /dev/null
+++ b/libgralloc-qsd8k/tests/Android.mk
@@ -0,0 +1,55 @@
+# Copyright (C) 2008 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+LOCAL_PATH := $(call my-dir)
+
+# you can use EXTRA_CFLAGS to indicate additional CFLAGS to use
+# in the build. The variables will be cleaned on exit
+#
+#
+
+libgralloc_test_includes:= \
+    bionic/libstdc++/include \
+    external/astl/include \
+    external/gtest/include \
+    $(LOCAL_PATH)/..
+
+libgralloc_test_static_libs := \
+    libgralloc_qsd8k_host \
+    libgtest_main_host \
+	libgtest_host  \
+	libastl_host \
+    liblog
+
+define host-test
+  $(foreach file,$(1), \
+    $(eval include $(CLEAR_VARS)) \
+    $(eval LOCAL_CPP_EXTENSION := .cpp) \
+    $(eval LOCAL_SRC_FILES := $(file)) \
+    $(eval LOCAL_C_INCLUDES := $(libgralloc_test_includes)) \
+    $(eval LOCAL_MODULE := $(notdir $(file:%.cpp=%))) \
+    $(eval LOCAL_CFLAGS += $(EXTRA_CFLAGS)) \
+    $(eval LOCAL_LDLIBS += $(EXTRA_LDLIBS)) \
+    $(eval LOCAL_STATIC_LIBRARIES := $(libgralloc_test_static_libs)) \
+    $(eval LOCAL_MODULE_TAGS := eng tests) \
+    $(eval include $(BUILD_HOST_EXECUTABLE)) \
+  ) \
+  $(eval EXTRA_CFLAGS :=) \
+  $(eval EXTRA_LDLIBS :=)
+endef
+
+TEST_SRC_FILES := \
+	pmemalloc_test.cpp
+
+$(call host-test, $(TEST_SRC_FILES))
diff --git a/libgralloc-qsd8k/tests/pmemalloc_test.cpp b/libgralloc-qsd8k/tests/pmemalloc_test.cpp
new file mode 100644
index 0000000..94e86bf
--- /dev/null
+++ b/libgralloc-qsd8k/tests/pmemalloc_test.cpp
@@ -0,0 +1,601 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gtest/gtest.h>
+
+#include <errno.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+
+#include "pmemalloc.h"
+
+class DepsStub : public PmemUserspaceAllocator::Deps, public PmemKernelAllocator::Deps {
+
+ public:
+
+    virtual size_t getPmemTotalSize(int fd, size_t* size) {
+        return 0;
+    }
+
+    virtual int connectPmem(int fd, int master_fd) {
+        return 0;
+    }
+
+    virtual int mapPmem(int fd, int offset, size_t size) {
+        return 0;
+    }
+
+    virtual int unmapPmem(int fd, int offset, size_t size) {
+        return 0;
+    }
+
+    virtual int getErrno() {
+        return 0;
+    }
+
+    virtual void* mmap(void* start, size_t length, int prot, int flags, int fd,
+            off_t offset) {
+        return 0;
+    }
+
+    virtual int munmap(void* start, size_t length) {
+        return 0;
+    }
+
+    virtual int open(const char* pathname, int flags, int mode) {
+        return 0;
+    }
+
+    virtual int close(int fd) {
+        return 0;
+    }
+};
+
+/******************************************************************************/
+
+class AllocatorStub : public PmemUserspaceAllocator::Deps::Allocator {
+    virtual ssize_t setSize(size_t size) {
+        return 0;
+    }
+
+    virtual size_t  size() const {
+        return 0;
+    }
+
+    virtual ssize_t allocate(size_t size, uint32_t flags = 0) {
+        return 0;
+    }
+
+    virtual ssize_t deallocate(size_t offset) {
+        return 0;
+    }
+};
+
+/******************************************************************************/
+
+static const char* fakePmemDev = "/foo/bar";
+
+/******************************************************************************/
+
+struct Deps_InitPmemAreaLockedWithSuccessfulCompletion : public DepsStub {
+
+    virtual int open(const char* pathname, int flags, int mode) {
+        EXPECT_EQ(fakePmemDev, pathname);
+        EXPECT_EQ(O_RDWR, flags);
+        EXPECT_EQ(0, mode);
+        return 1234;
+    }
+
+    virtual size_t getPmemTotalSize(int fd, size_t* size) {
+        EXPECT_EQ(1234, fd);
+        *size = 16 << 20;
+        return 0;
+    }
+
+    virtual void* mmap(void* start, size_t length, int prot, int flags, int fd,
+            off_t offset) {
+        EXPECT_EQ(1234, fd);
+        return (void*)0x87654321;
+    }
+
+};
+
+struct Allocator_InitPmemAreaLockedWithSuccessfulCompletion : public AllocatorStub {
+    
+    virtual ssize_t setSize(size_t size) {
+        EXPECT_EQ(size_t(16 << 20), size);
+        return 0;
+    }
+};
+
+TEST(test_pmem_userspace_allocator, testInitPmemAreaLockedWithSuccessfulCompletion) {
+    Deps_InitPmemAreaLockedWithSuccessfulCompletion depsMock;
+    Allocator_InitPmemAreaLockedWithSuccessfulCompletion allocMock;
+    PmemUserspaceAllocator pma(depsMock, allocMock, fakePmemDev);
+
+    int result = pma.init_pmem_area_locked();
+    ASSERT_EQ(0, result);
+}
+
+/******************************************************************************/
+
+struct Deps_InitPmemAreaLockedWithEnomemOnMmap : public DepsStub {
+
+    virtual int open(const char* pathname, int flags, int mode) {
+        EXPECT_EQ(fakePmemDev, pathname);
+        EXPECT_EQ(O_RDWR, flags);
+        EXPECT_EQ(0, mode);
+        return 1234;
+    }
+
+    virtual size_t getPmemTotalSize(int fd, size_t* size) {
+        EXPECT_EQ(1234, fd);
+        *size = 16 << 20;
+        return 0;
+    }
+
+    virtual int getErrno() {
+        return ENOMEM;
+    }
+
+    virtual void* mmap(void* start, size_t length, int prot, int flags, int fd,
+            off_t offset) {
+        return (void*)MAP_FAILED;
+    }
+
+};
+
+struct Allocator_InitPmemAreaLockedWithEnomemOnMmap : public AllocatorStub {
+    
+    virtual ssize_t setSize(size_t size) {
+        EXPECT_EQ(size_t(16 << 20), size);
+        return 0;
+    }
+};
+
+TEST(test_pmem_userspace_allocator, testInitPmemAreaLockedWthEnomemOnMmap) {
+    Deps_InitPmemAreaLockedWithEnomemOnMmap depsMock;
+    Allocator_InitPmemAreaLockedWithEnomemOnMmap allocMock;
+    PmemUserspaceAllocator pma(depsMock, allocMock, fakePmemDev);
+
+    int result = pma.init_pmem_area_locked();
+    ASSERT_EQ(-ENOMEM, result);
+}
+
+/******************************************************************************/
+
+struct Deps_InitPmemAreaLockedWithEaccesOnGetPmemTotalSize : public DepsStub {
+
+    virtual int open(const char* pathname, int flags, int mode) {
+        EXPECT_EQ(fakePmemDev, pathname);
+        EXPECT_EQ(O_RDWR, flags);
+        EXPECT_EQ(0, mode);
+        return 1234;
+    }
+
+    virtual size_t getPmemTotalSize(int fd, size_t* size) {
+        EXPECT_EQ(1234, fd);
+        return -EACCES;
+    }
+};
+
+TEST(test_pmem_userspace_allocator, testInitPmemAreaLockedWthEaccesOnGetPmemTotalSize) {
+    Deps_InitPmemAreaLockedWithEaccesOnGetPmemTotalSize depsMock;
+    AllocatorStub allocStub;
+    PmemUserspaceAllocator pma(depsMock, allocStub, fakePmemDev);
+
+    int result = pma.init_pmem_area_locked();
+    ASSERT_EQ(-EACCES, result);
+}
+
+/******************************************************************************/
+
+struct Deps_InitPmemAreaLockedWithEaccesOnOpen : public DepsStub {
+
+    virtual int getErrno() {
+        return EACCES;
+    }
+
+    virtual int open(const char* pathname, int flags, int mode) {
+        EXPECT_EQ(fakePmemDev, pathname);
+        EXPECT_EQ(O_RDWR, flags);
+        EXPECT_EQ(0, mode);
+        return -1;
+    }
+};
+
+TEST(test_pmem_userspace_allocator, testInitPmemAreaLockedWithEaccesOnOpenMaster) {
+    Deps_InitPmemAreaLockedWithEaccesOnOpen depsMock;
+    AllocatorStub allocStub;
+    PmemUserspaceAllocator pma(depsMock, allocStub, fakePmemDev);
+
+    int result = pma.init_pmem_area_locked();
+    ASSERT_EQ(-EACCES, result);
+}
+
+/******************************************************************************/
+
+typedef Deps_InitPmemAreaLockedWithSuccessfulCompletion Deps_InitPmemAreaWithSuccessfulInitialCompletion;
+
+TEST(test_pmem_userspace_allocator, testInitPmemAreaWithSuccessfulInitialCompletion) {
+    Deps_InitPmemAreaWithSuccessfulInitialCompletion depsMock;
+    AllocatorStub allocStub;
+    PmemUserspaceAllocator pma(depsMock, allocStub, fakePmemDev);
+
+    int result = pma.init_pmem_area();
+    ASSERT_EQ(0, result);
+}
+
+/******************************************************************************/
+
+typedef Deps_InitPmemAreaLockedWithEaccesOnOpen Deps_InitPmemAreaWithEaccesOnInitLocked;
+
+TEST(test_pmem_userspace_allocator, testInitPmemAreaWithEaccesOnInitLocked) {
+    Deps_InitPmemAreaWithEaccesOnInitLocked depsMock;
+    AllocatorStub allocStub;
+    PmemUserspaceAllocator pma(depsMock, allocStub, fakePmemDev);
+
+    int result = pma.init_pmem_area();
+    ASSERT_EQ(-EACCES, result);
+}
+
+/******************************************************************************/
+
+TEST(test_pmem_userspace_allocator, testInitPmemAreaAfterSuccessfulInitialCompletion) {
+    DepsStub depsStub;
+    AllocatorStub allocStub;
+    PmemUserspaceAllocator pma(depsStub, allocStub, fakePmemDev);
+
+    pma.set_master_values(1234, 0); // Indicate that the pma has been successfully init'd
+
+    int result = pma.init_pmem_area();
+    ASSERT_EQ(0, result);
+    //XXX JMG: Add this back in maybe? ASSERT_EQ(1234, pmi.master); // Make sure the master fd wasn't changed
+}
+
+/******************************************************************************/
+
+TEST(test_pmem_userspace_allocator, testInitPmemAreaAfterFailedInit) {
+    DepsStub depsStub;
+    AllocatorStub allocStub;
+    PmemUserspaceAllocator pma(depsStub, allocStub, fakePmemDev);
+
+    pma.set_master_values(-EACCES, 0); // Indicate that the pma has failed init
+
+    int result = pma.init_pmem_area();
+    ASSERT_EQ(-EACCES, result);
+}
+
+/******************************************************************************/
+
+struct Deps_InitPmemAreaLockedWithSuccessfulCompletionWithNoFlags : public DepsStub {
+
+    virtual int open(const char* pathname, int flags, int mode) {
+        EXPECT_EQ(fakePmemDev, pathname);
+        EXPECT_EQ(O_RDWR, flags & O_RDWR);
+        EXPECT_EQ(0, mode);
+        return 5678;
+    }
+
+    virtual int connectPmem(int fd, int master_fd) {
+        EXPECT_EQ(5678, fd);
+        EXPECT_EQ(1234, master_fd);
+        return 0;
+    }
+
+    virtual int mapPmem(int fd, int offset, size_t size) {
+        EXPECT_EQ(5678, fd);
+        EXPECT_EQ(0x300, offset);
+        EXPECT_EQ(size_t(0x100), size);
+        return 0;
+    }
+};
+
+
+struct Allocator_AllocPmemBufferWithSuccessfulCompletionWithNoFlags : public AllocatorStub {
+
+    virtual ssize_t allocate(size_t size, uint32_t flags = 0) {
+        EXPECT_EQ(size_t(0x100), size);
+        EXPECT_EQ(uint32_t(0x0), flags);
+        return 0x300;
+    }
+};
+
+TEST(test_pmem_userspace_allocator, testAllocPmemBufferWithSuccessfulCompletionWithNoFlags) {
+    Deps_InitPmemAreaLockedWithSuccessfulCompletionWithNoFlags depsMock;
+    Allocator_AllocPmemBufferWithSuccessfulCompletionWithNoFlags allocMock;
+    PmemUserspaceAllocator pma(depsMock, allocMock, fakePmemDev);
+
+    uint8_t buf[0x300 + 0x100]; // Create a buffer to get memzero'd
+    pma.set_master_values(1234, buf); // Indicate that the pma has been successfully init'd
+
+    void* base = 0;
+    int offset = -9182, fd = -9182;
+    int size = 0x100;
+    int flags = 0;
+    int result = pma.alloc_pmem_buffer(size, flags, &base, &offset, &fd);
+    ASSERT_EQ(0, result);
+    ASSERT_EQ(0x300, offset);
+    ASSERT_EQ(5678, fd);
+    for (int i = 0x300; i < 0x400; ++i) {
+        ASSERT_EQ(uint8_t(0), buf[i]);
+    }
+}
+
+/******************************************************************************/
+
+typedef Deps_InitPmemAreaLockedWithSuccessfulCompletionWithNoFlags Deps_InitPmemAreaLockedWithSuccessfulCompletionWithAllFlags;
+
+typedef Allocator_AllocPmemBufferWithSuccessfulCompletionWithNoFlags Allocator_AllocPmemBufferWithSuccessfulCompletionWithAllFlags;
+
+TEST(test_pmem_userspace_allocator, testAllocPmemBufferWithSuccessfulCompletionWithAllFlags) {
+    Deps_InitPmemAreaLockedWithSuccessfulCompletionWithAllFlags depsMock;
+    Allocator_AllocPmemBufferWithSuccessfulCompletionWithAllFlags allocMock;
+    PmemUserspaceAllocator pma(depsMock, allocMock, fakePmemDev);
+
+    uint8_t buf[0x300 + 0x100]; // Create a buffer to get memzero'd
+    pma.set_master_values(1234, buf); // Indicate that the pma has been successfully init'd
+
+    void* base = 0;
+    int offset = -9182, fd = -9182;
+    int size = 0x100;
+    int flags = ~0;
+    int result = pma.alloc_pmem_buffer(size, flags, &base, &offset, &fd);
+    ASSERT_EQ(0, result);
+    ASSERT_EQ(0x300, offset);
+    ASSERT_EQ(5678, fd);
+    for (int i = 0x300; i < 0x400; ++i) {
+        ASSERT_EQ(0, buf[i]);
+    }
+}
+
+/******************************************************************************/
+
+struct Deps_InitPmemAreaLockedWithEnodevOnOpen : public Deps_InitPmemAreaLockedWithSuccessfulCompletionWithNoFlags {
+
+    virtual int getErrno() {
+        return ENODEV;
+    }
+
+    virtual int open(const char* pathname, int flags, int mode) {
+        EXPECT_EQ(fakePmemDev, pathname);
+        EXPECT_EQ(O_RDWR, flags & O_RDWR);
+        EXPECT_EQ(0, mode);
+        return -1;
+    }
+};
+
+typedef Allocator_AllocPmemBufferWithSuccessfulCompletionWithNoFlags Allocator_AllocPmemBufferWithEnodevOnOpen;
+
+TEST(test_pmem_userspace_allocator, testAllocPmemBufferWithSuccessfulCompletionWithEnodevOnOpen) {
+    Deps_InitPmemAreaLockedWithEnodevOnOpen depsMock;
+    Allocator_AllocPmemBufferWithEnodevOnOpen allocMock;
+    PmemUserspaceAllocator pma(depsMock, allocMock, fakePmemDev);
+
+    uint8_t buf[0x300 + 0x100]; // Create a buffer to get memzero'd
+    pma.set_master_values(1234, buf); // Indicate that the pma has been successfully init'd
+
+    void* base = 0;
+    int offset = -9182, fd = -9182;
+    int size = 0x100;
+    int flags = ~0;
+    int result = pma.alloc_pmem_buffer(size, flags, &base, &offset, &fd);
+    ASSERT_EQ(-ENODEV, result);
+}
+
+/******************************************************************************/
+
+struct Deps_InitPmemAreaLockedWithEnomemOnConnectPmem : public Deps_InitPmemAreaLockedWithSuccessfulCompletionWithNoFlags {
+
+    virtual int getErrno() {
+        return ENOMEM;
+    }
+
+    virtual int connectPmem(int fd, int master_fd) {
+        EXPECT_EQ(5678, fd);
+        EXPECT_EQ(1234, master_fd);
+        return -1;
+    }
+};
+
+typedef Allocator_AllocPmemBufferWithSuccessfulCompletionWithNoFlags Allocator_AllocPmemBufferWithEnomemOnConnectPmem;
+
+TEST(test_pmem_userspace_allocator, testAllocPmemBufferWithSuccessfulCompletionWithEnomemOnConnectPmem) {
+    Deps_InitPmemAreaLockedWithEnomemOnConnectPmem depsMock;
+    Allocator_AllocPmemBufferWithEnomemOnConnectPmem allocMock;
+    PmemUserspaceAllocator pma(depsMock, allocMock, fakePmemDev);
+
+    uint8_t buf[0x300 + 0x100]; // Create a buffer to get memzero'd
+    pma.set_master_values(1234, buf); // Indicate that the pma has been successfully init'd
+
+    void* base = 0;
+    int offset = -9182, fd = -9182;
+    int size = 0x100;
+    int flags = ~0;
+    int result = pma.alloc_pmem_buffer(size, flags, &base, &offset, &fd);
+    ASSERT_EQ(-ENOMEM, result);
+}
+
+/******************************************************************************/
+
+struct Deps_InitPmemAreaLockedWithEnomemOnMapPmem : public Deps_InitPmemAreaLockedWithSuccessfulCompletionWithNoFlags {
+
+    virtual int getErrno() {
+        return ENOMEM;
+    }
+
+    virtual int mapPmem(int fd, int offset, size_t size) {
+        EXPECT_EQ(5678, fd);
+        EXPECT_EQ(0x300, offset);
+        EXPECT_EQ(size_t(0x100), size);
+        return -1;
+    }
+};
+
+typedef Allocator_AllocPmemBufferWithSuccessfulCompletionWithNoFlags Allocator_AllocPmemBufferWithEnomemOnMapPmem;
+
+TEST(test_pmem_userspace_allocator, testAllocPmemBufferWithEnomemOnMapPmem) {
+    Deps_InitPmemAreaLockedWithEnomemOnMapPmem depsMock;
+    Allocator_AllocPmemBufferWithEnomemOnMapPmem allocMock;
+    PmemUserspaceAllocator pma(depsMock, allocMock, fakePmemDev);
+
+    uint8_t buf[0x300 + 0x100]; // Create a buffer to get memzero'd
+    pma.set_master_values(1234, buf); // Indicate that the pma has been successfully init'd
+
+    void* base = 0;
+    int offset = -9182, fd = -9182;
+    int size = 0x100;
+    int flags = ~0;
+    int result = pma.alloc_pmem_buffer(size, flags, &base, &offset, &fd);
+    ASSERT_EQ(-ENOMEM, result);
+}
+
+/******************************************************************************/
+
+struct Deps_KernelAllocPmemBufferWithSuccessfulCompletionWithNoFlags : public DepsStub {
+
+    void* mmapResult;
+
+    Deps_KernelAllocPmemBufferWithSuccessfulCompletionWithNoFlags(void* mmapResult) :
+            mmapResult(mmapResult) {}
+
+    virtual int open(const char* pathname, int flags, int mode) {
+        EXPECT_EQ(fakePmemDev, pathname);
+        EXPECT_EQ(O_RDWR, flags & O_RDWR);
+        EXPECT_EQ(0, mode);
+        return 5678;
+    }
+
+    virtual void* mmap(void* start, size_t length, int prot, int flags, int fd,
+            off_t offset) {
+        EXPECT_EQ(5678, fd);
+        return mmapResult;
+    }
+};
+
+TEST(test_pmem_kernel_allocator, testAllocPmemBufferWithSuccessfulCompletionWithNoFlags) {
+    uint8_t buf[0x100]; // Create a buffer to get memzero'd
+    Deps_KernelAllocPmemBufferWithSuccessfulCompletionWithNoFlags depsMock(buf);
+    PmemKernelAllocator pma(depsMock, fakePmemDev);
+
+    void* base = 0;
+    int offset = -9182, fd = -9182;
+    int size = 0x100;
+    int flags = 0;
+    int result = pma.alloc_pmem_buffer(size, flags, &base, &offset, &fd);
+    ASSERT_EQ(0, result);
+    ASSERT_EQ(buf, base);
+    ASSERT_EQ(0, offset);
+    ASSERT_EQ(5678, fd);
+    for (int i = 0; i < 0x100; ++i) {
+        ASSERT_EQ(0, buf[i]);
+    }
+}
+
+/******************************************************************************/
+
+typedef Deps_KernelAllocPmemBufferWithSuccessfulCompletionWithNoFlags Deps_KernelAllocPmemBufferWithSuccessfulCompletionWithAllFlags;
+
+TEST(test_pmem_kernel_allocator, testAllocPmemBufferWithSuccessfulCompletionWithAllFlags) {
+    uint8_t buf[0x100]; // Create a buffer to get memzero'd
+    Deps_KernelAllocPmemBufferWithSuccessfulCompletionWithAllFlags depsMock(buf);
+    PmemKernelAllocator pma(depsMock, fakePmemDev);
+
+    void* base = 0;
+    int offset = -9182, fd = -9182;
+    int size = 0x100;
+    int flags = ~0;
+    int result = pma.alloc_pmem_buffer(size, flags, &base, &offset, &fd);
+    ASSERT_EQ(0, result);
+    ASSERT_EQ(buf, base);
+    ASSERT_EQ(0, offset);
+    ASSERT_EQ(5678, fd);
+    for (int i = 0; i < 0x100; ++i) {
+        ASSERT_EQ(0, buf[i]);
+    }
+}
+
+/******************************************************************************/
+
+struct Deps_KernelAllocPmemBufferWithEpermOnOpen : public DepsStub {
+
+    virtual int getErrno() {
+        return EPERM;
+    }
+
+    virtual int open(const char* pathname, int flags, int mode) {
+        EXPECT_EQ(fakePmemDev, pathname);
+        EXPECT_EQ(O_RDWR, flags & O_RDWR);
+        EXPECT_EQ(0, mode);
+        return -1;
+    }
+};
+
+
+TEST(test_pmem_kernel_allocator, testAllocPmemBufferWithEpermOnOpen) {
+    Deps_KernelAllocPmemBufferWithEpermOnOpen depsMock;
+    PmemKernelAllocator pma(depsMock, fakePmemDev);
+
+    void* base = 0;
+    int offset = -9182, fd = -9182;
+    int size = 0x100;
+    int flags = ~0;
+    int result = pma.alloc_pmem_buffer(size, flags, &base, &offset, &fd);
+    ASSERT_EQ(-EPERM, result);
+    ASSERT_EQ(0, base);
+    ASSERT_EQ(0, offset);
+    ASSERT_EQ(-1, fd);
+}
+
+/******************************************************************************/
+
+struct Deps_KernelAllocPmemBufferWithEnomemOnMmap : DepsStub {
+
+    virtual int open(const char* pathname, int flags, int mode) {
+        EXPECT_EQ(fakePmemDev, pathname);
+        EXPECT_EQ(O_RDWR, flags & O_RDWR);
+        EXPECT_EQ(0, mode);
+        return 5678;
+    }
+
+    virtual void* mmap(void* start, size_t length, int prot, int flags, int fd,
+            off_t offset) {
+        return (void*)MAP_FAILED;
+    }
+
+    virtual int getErrno() {
+        return ENOMEM;
+    }
+};
+
+
+TEST(test_pmem_kernel_allocator, testAllocPmemBufferWithEnomemOnMmap) {
+    Deps_KernelAllocPmemBufferWithEnomemOnMmap depsMock;
+    PmemKernelAllocator pma(depsMock, fakePmemDev);
+
+    void* base = 0;
+    int offset = -9182, fd = -9182;
+    int size = 0x100;
+    int flags = ~0;
+    int result = pma.alloc_pmem_buffer(size, flags, &base, &offset, &fd);
+    ASSERT_EQ(-ENOMEM, result);
+    ASSERT_EQ(0, base);
+    ASSERT_EQ(0, offset);
+    ASSERT_EQ(-1, fd);
+}
+
+/******************************************************************************/
diff --git a/libhwcomposer/Android.mk b/libhwcomposer/Android.mk
new file mode 100644
index 0000000..ffc30bd
--- /dev/null
+++ b/libhwcomposer/Android.mk
@@ -0,0 +1,28 @@
+LOCAL_PATH := $(call my-dir)
+
+# HAL module implemenation, not prelinked and stored in
+# hw/<OVERLAY_HARDWARE_MODULE_ID>.<ro.product.board>.so
+include $(CLEAR_VARS)
+LOCAL_PRELINK_MODULE := false
+LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw
+LOCAL_SHARED_LIBRARIES := liblog libcutils libEGL libhardware libutils liboverlay
+
+LOCAL_SRC_FILES := 	\
+	hwcomposer.cpp
+	
+LOCAL_MODULE := hwcomposer.$(TARGET_BOARD_PLATFORM)
+LOCAL_CFLAGS:= -DLOG_TAG=\"$(TARGET_BOARD_PLATFORM).hwcomposer\"
+LOCAL_C_INCLUDES += hardware/qcom/display/libgralloc
+LOCAL_C_INCLUDES += hardware/msm7k/liboverlay
+LOCAL_C_INCLUDES += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr/include
+LOCAL_ADDITIONAL_DEPENDENCIES += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr
+ifeq ($(TARGET_HAVE_HDMI_OUT),true)
+LOCAL_CFLAGS += -DHDMI_DUAL_DISPLAY
+endif
+ifeq ($(TARGET_HAVE_BYPASS),true)
+LOCAL_CFLAGS += -DCOMPOSITION_BYPASS
+endif
+ifeq ($(TARGET_USE_HDMI_AS_PRIMARY),true)
+LOCAL_CFLAGS += -DHDMI_AS_PRIMARY
+endif
+include $(BUILD_SHARED_LIBRARY)
diff --git a/libhwcomposer/hwcomposer.cpp b/libhwcomposer/hwcomposer.cpp
new file mode 100644
index 0000000..034d74d
--- /dev/null
+++ b/libhwcomposer/hwcomposer.cpp
@@ -0,0 +1,1162 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <hardware/hardware.h>
+#include <hardware/overlay.h>
+
+#include <fcntl.h>
+#include <errno.h>
+
+#include <cutils/log.h>
+#include <cutils/atomic.h>
+#include <cutils/properties.h>
+
+#include <hardware/hwcomposer.h>
+#include <hardware/overlay.h>
+#include <hardware/copybit.h>
+#include <overlayLib.h>
+#include <overlayLibUI.h>
+
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+#include <ui/android_native_buffer.h>
+#include <gralloc_priv.h>
+
+/*****************************************************************************/
+#define ALIGN(x, align) (((x) + ((align)-1)) & ~((align)-1))
+#define LIKELY( exp )       (__builtin_expect( (exp) != 0, true  ))
+#define UNLIKELY( exp )     (__builtin_expect( (exp) != 0, false ))
+
+// Enum containing the supported composition types
+enum {
+    COMPOSITION_TYPE_GPU = 0,
+    COMPOSITION_TYPE_MDP = 0x1,
+    COMPOSITION_TYPE_C2D = 0x2,
+    COMPOSITION_TYPE_CPU = 0x4,
+    COMPOSITION_TYPE_DYN = 0x8
+};
+
+enum HWCCompositionType {
+    HWC_USE_GPU = HWC_FRAMEBUFFER, // This layer is to be handled by Surfaceflinger
+    HWC_USE_OVERLAY = HWC_OVERLAY, // This layer is to be handled by the overlay
+    HWC_USE_COPYBIT                // This layer is to be handled by copybit
+};
+
+enum HWCPrivateFlags {
+    HWC_USE_ORIGINAL_RESOLUTION = HWC_FLAGS_PRIVATE_0, // This layer is to be drawn using overlays
+    HWC_DO_NOT_USE_OVERLAY      = HWC_FLAGS_PRIVATE_1, // Do not use overlays to draw this layer
+    HWC_COMP_BYPASS             = HWC_FLAGS_PRIVATE_3, // Layer "might" use or have used bypass
+};
+
+enum HWCLayerType{
+    HWC_SINGLE_VIDEO           = 0x1,
+    HWC_ORIG_RESOLUTION        = 0x2,
+    HWC_S3D_LAYER              = 0x4,
+    HWC_STOP_UI_MIRRORING_MASK = 0xF
+};
+
+#ifdef COMPOSITION_BYPASS
+enum BypassState {
+    BYPASS_ON,
+    BYPASS_OFF,
+    BYPASS_OFF_PENDING,
+};
+
+enum {
+    MAX_BYPASS_LAYERS = 2,
+    ANIM_FRAME_COUNT = 30,
+};
+#endif
+
+enum eHWCOverlayStatus {
+    HWC_OVERLAY_OPEN,
+    HWC_OVERLAY_PREPARE_TO_CLOSE,
+    HWC_OVERLAY_CLOSED
+};
+
+struct hwc_context_t {
+    hwc_composer_device_t device;
+    /* our private state goes below here */
+    overlay::Overlay* mOverlayLibObject;
+#ifdef COMPOSITION_BYPASS
+    overlay::OverlayUI* mOvUI[MAX_BYPASS_LAYERS];
+    int animCount;
+    BypassState bypassState;
+#endif
+#if defined HDMI_DUAL_DISPLAY
+    bool mHDMIEnabled;
+    bool pendingHDMI;
+#endif
+    int previousLayerCount;
+    eHWCOverlayStatus hwcOverlayStatus;
+};
+
+static int hwc_device_open(const struct hw_module_t* module, const char* name,
+        struct hw_device_t** device);
+
+static struct hw_module_methods_t hwc_module_methods = {
+    open: hwc_device_open
+};
+
+
+struct private_hwc_module_t {
+    hwc_module_t base;
+    overlay_control_device_t *overlayEngine;
+    copybit_device_t *copybitEngine;
+    framebuffer_device_t *fbDevice;
+    int compositionType;
+    bool isBypassEnabled; //from build.prop debug.compbypass.enable
+};
+
+struct private_hwc_module_t HAL_MODULE_INFO_SYM = {
+    base: {
+        common: {
+            tag: HARDWARE_MODULE_TAG,
+            version_major: 1,
+            version_minor: 0,
+            id: HWC_HARDWARE_MODULE_ID,
+            name: "Hardware Composer Module",
+            author: "The Android Open Source Project",
+            methods: &hwc_module_methods,
+        }
+   },
+   overlayEngine: NULL,
+   copybitEngine: NULL,
+   fbDevice: NULL,
+   compositionType: 0,
+   isBypassEnabled: false,
+};
+
+/*****************************************************************************/
+
+static void dump_layer(hwc_layer_t const* l) {
+    LOGD("\ttype=%d, flags=%08x, handle=%p, tr=%02x, blend=%04x, {%d,%d,%d,%d}, {%d,%d,%d,%d}",
+            l->compositionType, l->flags, l->handle, l->transform, l->blending,
+            l->sourceCrop.left,
+            l->sourceCrop.top,
+            l->sourceCrop.right,
+            l->sourceCrop.bottom,
+            l->displayFrame.left,
+            l->displayFrame.top,
+            l->displayFrame.right,
+            l->displayFrame.bottom);
+}
+
+static inline int min(const int& a, const int& b) {
+    return (a < b) ? a : b;
+}
+
+static inline int max(const int& a, const int& b) {
+    return (a > b) ? a : b;
+}
+
+static int setVideoOverlayStatusInGralloc(hwc_context_t* ctx, const bool enable) {
+#if defined HDMI_DUAL_DISPLAY
+    private_hwc_module_t* hwcModule = reinterpret_cast<private_hwc_module_t*>(
+                                                           ctx->device.common.module);
+    if(!hwcModule) {
+        LOGE("%s: invalid params", __FUNCTION__);
+        return -1;
+    }
+
+    framebuffer_device_t *fbDev = hwcModule->fbDevice;
+    if (!fbDev) {
+        LOGE("%s: fbDev is NULL", __FUNCTION__);
+        return -1;
+    }
+
+    // Inform the gralloc to stop or start UI mirroring
+    fbDev->videoOverlayStarted(fbDev, enable);
+#endif
+    return 0;
+}
+
+static void setHWCOverlayStatus(hwc_context_t *ctx, bool isVideoPresent) {
+
+    switch (ctx->hwcOverlayStatus) {
+        case HWC_OVERLAY_OPEN:
+            ctx->hwcOverlayStatus =
+                isVideoPresent ? HWC_OVERLAY_OPEN : HWC_OVERLAY_PREPARE_TO_CLOSE;
+        break;
+        case HWC_OVERLAY_PREPARE_TO_CLOSE:
+            ctx->hwcOverlayStatus =
+                isVideoPresent ? HWC_OVERLAY_OPEN : HWC_OVERLAY_CLOSED;
+        break;
+        case HWC_OVERLAY_CLOSED:
+            ctx->hwcOverlayStatus =
+                isVideoPresent ? HWC_OVERLAY_OPEN : HWC_OVERLAY_CLOSED;
+        break;
+        default:
+          LOGE("%s: Invalid hwcOverlayStatus (status =%d)", __FUNCTION__,
+                ctx->hwcOverlayStatus);
+        break;
+    }
+}
+
+static int hwc_closeOverlayChannels(hwc_context_t* ctx) {
+    overlay::Overlay *ovLibObject = ctx->mOverlayLibObject;
+    if(!ovLibObject) {
+        LOGE("%s: invalid params", __FUNCTION__);
+        return -1;
+    }
+
+    if (HWC_OVERLAY_PREPARE_TO_CLOSE == ctx->hwcOverlayStatus) {
+        // Video mirroring is going on, and we do not have any layers to
+        // mirror directly. Close the current video channel and inform the
+        // gralloc to start UI mirroring
+        ovLibObject->closeChannel();
+        // Inform the gralloc that video overlay has stopped.
+        setVideoOverlayStatusInGralloc(ctx, false);
+    }
+    return 0;
+}
+
+/*
+ * Configures mdp pipes
+ */
+static int prepareOverlay(hwc_context_t *ctx, hwc_layer_t *layer, const bool waitForVsync) {
+     int ret = 0;
+     if (LIKELY(ctx && ctx->mOverlayLibObject)) {
+        private_hwc_module_t* hwcModule =
+            reinterpret_cast<private_hwc_module_t*>(ctx->device.common.module);
+        if (UNLIKELY(!hwcModule)) {
+            LOGE("prepareOverlay null module ");
+            return -1;
+        }
+
+        private_handle_t *hnd = (private_handle_t *)layer->handle;
+        overlay::Overlay *ovLibObject = ctx->mOverlayLibObject;
+        overlay_buffer_info info;
+        info.width = hnd->width;
+        info.height = hnd->height;
+        info.format = hnd->format;
+        info.size = hnd->size;
+
+        ret = ovLibObject->setSource(info, layer->transform,
+                            (ovLibObject->getHDMIStatus()?true:false), waitForVsync);
+        if (!ret) {
+            LOGE("prepareOverlay setSource failed");
+            return -1;
+        }
+
+        ret = ovLibObject->setParameter(OVERLAY_TRANSFORM, layer->transform);
+        if (!ret) {
+            LOGE("prepareOverlay setParameter failed transform %x",
+                    layer->transform);
+            return -1;
+        }
+
+        hwc_rect_t sourceCrop = layer->sourceCrop;
+        ret = ovLibObject->setCrop(sourceCrop.left, sourceCrop.top,
+                                  (sourceCrop.right - sourceCrop.left),
+                                  (sourceCrop.bottom - sourceCrop.top));
+        if (!ret) {
+            LOGE("prepareOverlay setCrop failed");
+            return -1;
+        }
+
+        if (layer->flags == HWC_USE_ORIGINAL_RESOLUTION) {
+            framebuffer_device_t* fbDev = hwcModule->fbDevice;
+            ret = ovLibObject->setPosition(0, 0,
+                                           fbDev->width, fbDev->height);
+        } else {
+            hwc_rect_t displayFrame = layer->displayFrame;
+            ret = ovLibObject->setPosition(displayFrame.left, displayFrame.top,
+                                    (displayFrame.right - displayFrame.left),
+                                    (displayFrame.bottom - displayFrame.top));
+        }
+        if (!ret) {
+            LOGE("prepareOverlay setPosition failed");
+            return -1;
+        }
+     }
+     return 0;
+}
+
+bool canSkipComposition(hwc_context_t* ctx, int yuvBufferCount, int currentLayerCount,
+                        int numLayersNotUpdating)
+{
+    if (!ctx) {
+        LOGE("canSkipComposition invalid context");
+        return false;
+    }
+
+    bool compCountChanged = false;
+    if (yuvBufferCount == 1) {
+        if (currentLayerCount != ctx->previousLayerCount) {
+            compCountChanged = true;
+            ctx->previousLayerCount = currentLayerCount;
+        }
+
+        if (!compCountChanged) {
+            if ((currentLayerCount == 1) ||
+                ((currentLayerCount-1) == numLayersNotUpdating)) {
+                // We either have only one overlay layer or we have
+                // all the non-UI layers not updating. In this case
+                // we can skip the composition of the UI layers.
+                return true;
+            }
+        }
+    } else {
+        ctx->previousLayerCount = -1;
+    }
+    return false;
+}
+
+static bool isFullScreenUpdate(const framebuffer_device_t* fbDev, const hwc_layer_list_t* list) {
+
+    if(!fbDev) {
+       LOGE("ERROR: %s : fb device is invalid",__func__);
+       return false;
+    }
+
+    int fb_w = fbDev->width;
+    int fb_h = fbDev->height;
+
+    /*
+     *  We have full screen condition when
+     * 1. We have 1 layer to compose
+     *    a. layers dest rect equals display resolution.
+     * 2. We have 2 layers to compose
+     *    a. Sum of their dest rects equals display resolution.
+     */
+
+    if(list->numHwLayers == 1)
+    {
+        hwc_rect_t rect = list->hwLayers[0].displayFrame;
+
+        int w = rect.right - rect.left;
+        int h = rect.bottom - rect.top;
+
+        int transform = list->hwLayers[0].transform;
+
+        if(transform & (HWC_TRANSFORM_ROT_90 | HWC_TRANSFORM_ROT_270))
+            return ((fb_w == h) && (fb_h == w));
+        else
+            return ((fb_h == h) && (fb_w == w));
+    }
+
+    if(list->numHwLayers == 2) {
+
+        hwc_rect_t rect_1 = list->hwLayers[0].displayFrame;
+        hwc_rect_t rect_2 = list->hwLayers[1].displayFrame;
+
+        int transform_1 = list->hwLayers[0].transform;
+        int transform_2 = list->hwLayers[1].transform;
+
+        int w1 = rect_1.right - rect_1.left;
+        int h1 = rect_1.bottom - rect_1.top;
+        int w2 = rect_2.right - rect_2.left;
+        int h2 = rect_2.bottom - rect_2.top;
+
+        if(transform_1 == transform_2) {
+            if(transform_1 & (HWC_TRANSFORM_ROT_90 | HWC_TRANSFORM_ROT_270)) {
+                if((fb_w == (w1 + w2)) && (fb_h == h1) && (fb_h == h2))
+                    return true;
+            } else {
+                if((fb_w == w1) && (fb_w == w2) && (fb_h == (h1 + h2)))
+                    return true;
+            }
+        }
+    }
+    return false;
+}
+
+#ifdef COMPOSITION_BYPASS
+/*
+ * Configures pipe(s) for composition bypass
+ */
+static int prepareBypass(hwc_context_t *ctx, hwc_layer_t *layer, int index,
+        int lastLayerIndex) {
+    if (ctx && ctx->mOvUI[index]) {
+        private_hwc_module_t* hwcModule = reinterpret_cast<
+                private_hwc_module_t*>(ctx->device.common.module);
+        if (!hwcModule) {
+            LOGE("prepareBypass null module ");
+            return -1;
+        }
+        private_handle_t *hnd = (private_handle_t *)layer->handle;
+        if(!hnd) {
+            LOGE("prepareBypass handle null");
+            return -1;
+        }
+        hwc_rect_t sourceCrop = layer->sourceCrop;
+        if((sourceCrop.right - sourceCrop.left) > hwcModule->fbDevice->width ||
+                (sourceCrop.bottom - sourceCrop.top) > hwcModule->fbDevice->height) {
+            ctx->animCount = ANIM_FRAME_COUNT;
+            return -1;
+        }
+        overlay::OverlayUI *ovUI = ctx->mOvUI[index];
+        int ret = 0;
+        int orientation = layer->transform;
+        overlay_buffer_info info;
+        info.width = sourceCrop.right - sourceCrop.left;
+        info.height = sourceCrop.bottom - sourceCrop.top;
+        info.format = hnd->format;
+        info.size = hnd->size;
+        const bool useVGPipe = true;
+        //only last layer should wait for vsync
+        const bool waitForVsync = (index == lastLayerIndex);
+        const int fbnum = 0;
+        //Just to differentiate zorders for different layers
+        const int zorder = index;
+        ret = ovUI->setSource(info, orientation, useVGPipe, waitForVsync,
+                fbnum, zorder);
+        if (ret) {
+            LOGE("prepareBypass setSource failed");
+            return -1;
+        }
+
+        hwc_rect_t displayFrame = layer->displayFrame;
+        ret = ovUI->setPosition(displayFrame.left, displayFrame.top,
+                (displayFrame.right - displayFrame.left),
+                (displayFrame.bottom - displayFrame.top));
+        if (ret) {
+            LOGE("prepareBypass setPosition failed");
+            return -1;
+        }
+    }
+    return 0;
+}
+
+static int drawLayerUsingBypass(hwc_context_t *ctx, hwc_layer_t *layer,
+        int index) {
+    if (ctx && ctx->mOvUI[index]) {
+        overlay::OverlayUI *ovUI = ctx->mOvUI[index];
+        int ret = 0;
+        private_handle_t *hnd = (private_handle_t *)layer->handle;
+        ret = ovUI->queueBuffer(hnd);
+        if (ret) {
+            LOGE("drawLayerUsingBypass queueBuffer failed");
+            return -1;
+        }
+    }
+    return 0;
+}
+
+/* Checks if 2 layers intersect */
+static bool isIntersect(const hwc_rect_t& one, const hwc_rect_t& two) {
+    hwc_rect_t result;
+    result.left = max(one.left, two.left);
+    result.top = max(one.top, two.top);
+    result.right = min(one.right, two.right);
+    result.bottom = min(one.bottom, two.bottom);
+    const int width = result.right - result.left;
+    const int height = result.bottom - result.top;
+    const bool isEmpty = width <= 0 || height <= 0;
+    return !isEmpty;
+}
+
+/* Check if layers are disjoint */
+static bool isDisjoint(const hwc_layer_list_t* list) {
+    //Validate supported layer range
+    if(list->numHwLayers <= 0 || list->numHwLayers > MAX_BYPASS_LAYERS) {
+        return false;
+    }
+    for(int i = 0; i < (list->numHwLayers) - 1; i++) {
+        for(int j = i + 1; j < list->numHwLayers; j++) {
+            if(isIntersect(list->hwLayers[i].displayFrame,
+                list->hwLayers[j].displayFrame)) {
+                return false;
+            }
+        }
+    }
+    return true;
+}
+
+/*
+ * Checks if doing comp. bypass is possible. If video is not on and there
+ * are 2 layers then its doable.
+ */
+inline static bool isBypassDoable(hwc_composer_device_t *dev, const int yuvCount,
+        const hwc_layer_list_t* list) {
+    hwc_context_t* ctx = (hwc_context_t*)(dev);
+    private_hwc_module_t* hwcModule = reinterpret_cast<private_hwc_module_t*>(
+                                                           dev->common.module);
+    //Check if enabled in build.prop
+    if(hwcModule->isBypassEnabled == false) {
+        return false;
+    }
+    //Disable bypass during animation
+    if(UNLIKELY(ctx->animCount)) {
+        --(ctx->animCount);
+        return false;
+    }
+#if defined HDMI_DUAL_DISPLAY
+    //Disable bypass when HDMI is enabled
+    if(ctx->mHDMIEnabled || ctx->pendingHDMI) {
+        return false;
+    }
+#endif
+    return (yuvCount == 0) && isDisjoint(list);
+}
+
+/*
+ * Bypass is not efficient if area is greater than 1280x720
+ * AND rotation is necessary, since the rotator consumes
+ * time greater than 1 Vsync and is sequential.
+ */
+inline static bool isBypassEfficient(const framebuffer_device_t* fbDev,
+        const hwc_layer_list_t* list, hwc_context_t* ctx) {
+    bool rotationNeeded = false;
+    for(int i = 0; i < list->numHwLayers; ++i) {
+        if(list->hwLayers[i].transform) {
+            rotationNeeded = true;
+            break;
+        }
+    }
+    return !(rotationNeeded);
+}
+
+bool setupBypass(hwc_context_t* ctx, hwc_layer_list_t* list) {
+    for (int index = 0 ; index < list->numHwLayers; index++) {
+        if(prepareBypass(ctx, &(list->hwLayers[index]), index,
+                list->numHwLayers - 1) != 0) {
+            return false;
+        }
+    }
+    return true;
+}
+
+void setBypassLayerFlags(hwc_context_t* ctx, hwc_layer_list_t* list) {
+    for (int index = 0 ; index < list->numHwLayers; index++) {
+        list->hwLayers[index].flags = HWC_COMP_BYPASS;
+        list->hwLayers[index].compositionType = HWC_USE_OVERLAY;
+        #ifdef DEBUG
+            LOGE("%s: layer = %d", __FUNCTION__, index);
+        #endif
+    }
+}
+
+void unsetBypassLayerFlags(hwc_layer_list_t* list) {
+    for (int index = 0 ; index < list->numHwLayers; index++) {
+        if(list->hwLayers[index].flags == HWC_COMP_BYPASS) {
+            list->hwLayers[index].flags = 0;
+        }
+    }
+}
+
+void closeBypass(hwc_context_t* ctx) {
+    for (int index = 0 ; index < MAX_BYPASS_LAYERS; index++) {
+        ctx->mOvUI[index]->closeChannel();
+        #ifdef DEBUG
+            LOGE("%s", __FUNCTION__);
+        #endif
+    }
+}
+#endif  //COMPOSITION_BYPASS
+
+
+static void handleHDMIStateChange(hwc_composer_device_t *dev) {
+#if defined HDMI_DUAL_DISPLAY
+    hwc_context_t* ctx = (hwc_context_t*)(dev);
+    private_hwc_module_t* hwcModule = reinterpret_cast<private_hwc_module_t*>(
+                                                           dev->common.module);
+    framebuffer_device_t *fbDev = hwcModule->fbDevice;
+    if (fbDev) {
+        fbDev->enableHDMIOutput(fbDev, ctx->mHDMIEnabled);
+    }
+
+    if(ctx && ctx->mOverlayLibObject) {
+        overlay::Overlay *ovLibObject = ctx->mOverlayLibObject;
+        ovLibObject->setHDMIStatus(ctx->mHDMIEnabled);
+        if (!(ctx->mHDMIEnabled)) {
+            // Close the overlay channels if HDMI is disconnected
+            ovLibObject->closeChannel();
+        }
+    }
+#endif
+}
+
+
+/* Just mark flags and do stuff after eglSwapBuffers */
+static void hwc_enableHDMIOutput(hwc_composer_device_t *dev, bool enable) {
+#if defined HDMI_DUAL_DISPLAY
+    hwc_context_t* ctx = (hwc_context_t*)(dev);
+    ctx->mHDMIEnabled = enable;
+    if(enable) { //On connect, allow bypass to draw once to FB
+        ctx->pendingHDMI = true;
+    } else { //On disconnect, close immediately (there will be no bypass)
+        handleHDMIStateChange(dev);
+    }
+#endif
+}
+
+static bool isValidDestination(const framebuffer_device_t* fbDev, const hwc_rect_t& rect)
+{
+    if (!fbDev) {
+        LOGE("%s: fbDev is null", __FUNCTION__);
+        return false;
+    }
+
+    int dest_width = (rect.right - rect.left);
+    int dest_height = (rect.bottom - rect.top);
+
+    if (rect.left < 0 || rect.right < 0 || rect.top < 0 || rect.bottom < 0
+        || dest_width <= 0 || dest_height <= 0) {
+        LOGE("%s: destination: left=%d right=%d top=%d bottom=%d width=%d"
+             "height=%d", __FUNCTION__, rect.left, rect.right, rect.top,
+             rect.bottom, dest_width, dest_height);
+        return false;
+    }
+
+    if ((rect.left+dest_width) > fbDev->width || (rect.top+dest_height) > fbDev->height) {
+        LOGE("%s: destination out of bound params", __FUNCTION__);
+        return false;
+    }
+
+    return true;
+}
+
+static int getYUVBufferCount (const hwc_layer_list_t* list) {
+    int yuvBufferCount = 0;
+    if (list) {
+        for (size_t i=0 ; i<list->numHwLayers; i++) {
+            private_handle_t *hnd = (private_handle_t *)list->hwLayers[i].handle;
+            if (hnd && (hnd->bufferType == BUFFER_TYPE_VIDEO) &&
+               !(list->hwLayers[i].flags & HWC_DO_NOT_USE_OVERLAY)) {
+                yuvBufferCount++;
+                if (yuvBufferCount > 1) {
+                    break;
+                }
+            }
+        }
+    }
+    return yuvBufferCount;
+}
+
+static int getS3DVideoFormat (const hwc_layer_list_t* list) {
+    int s3dFormat = 0;
+    if (list) {
+        for (size_t i=0; i<list->numHwLayers; i++) {
+            private_handle_t *hnd = (private_handle_t *)list->hwLayers[i].handle;
+            if (hnd && (hnd->bufferType == BUFFER_TYPE_VIDEO))
+                s3dFormat = FORMAT_3D_INPUT(hnd->format);
+            if (s3dFormat)
+                break;
+        }
+    }
+    return s3dFormat;
+}
+
+static bool isS3DCompositionRequired() {
+#ifdef HDMI_AS_PRIMARY
+    return overlay::is3DTV();
+#endif
+    return false;
+}
+
+static void markUILayerForS3DComposition (hwc_layer_t &layer, int s3dVideoFormat) {
+#ifdef HDMI_AS_PRIMARY
+    layer.compositionType = HWC_FRAMEBUFFER;
+    switch(s3dVideoFormat) {
+        case HAL_3D_IN_SIDE_BY_SIDE_L_R:
+        case HAL_3D_IN_SIDE_BY_SIDE_R_L:
+            layer.hints |= HWC_HINT_DRAW_S3D_SIDE_BY_SIDE;
+            break;
+        case HAL_3D_IN_TOP_BOTTOM:
+            layer.hints |= HWC_HINT_DRAW_S3D_TOP_BOTTOM;
+            break;
+        default:
+            LOGE("%s: Unknown S3D input format 0x%x", __FUNCTION__, s3dVideoFormat);
+            break;
+    }
+#endif
+    return;
+}
+
+static int getLayersNotUpdatingCount(const hwc_layer_list_t* list) {
+    int numLayersNotUpdating = 0;
+    if (list) {
+        for (size_t i=0 ; i<list->numHwLayers; i++) {
+            private_handle_t *hnd = (private_handle_t *)list->hwLayers[i].handle;
+            if (hnd && (hnd->bufferType != BUFFER_TYPE_VIDEO) &&
+               list->hwLayers[i].flags & HWC_LAYER_NOT_UPDATING)
+               numLayersNotUpdating++;
+        }
+    }
+    return numLayersNotUpdating;
+}
+
+static int hwc_prepare(hwc_composer_device_t *dev, hwc_layer_list_t* list) {
+
+    hwc_context_t* ctx = (hwc_context_t*)(dev);
+
+    if(!ctx || !list) {
+         LOGE("hwc_prepare invalid context or list");
+         return -1;
+    }
+
+    private_hwc_module_t* hwcModule = reinterpret_cast<private_hwc_module_t*>(
+                                                           dev->common.module);
+    if(!hwcModule) {
+        LOGE("hwc_prepare null module ");
+        return -1;
+    }
+
+    int yuvBufferCount = 0;
+    int layerType = 0;
+    bool isS3DCompositionNeeded = false;
+    int s3dVideoFormat = 0;
+    int numLayersNotUpdating = 0;
+    bool fullscreen = false;
+
+    if (list) {
+        fullscreen = isFullScreenUpdate(hwcModule->fbDevice, list);
+        yuvBufferCount = getYUVBufferCount(list);
+
+        bool skipComposition = false;
+        if (yuvBufferCount == 1) {
+            numLayersNotUpdating = getLayersNotUpdatingCount(list);
+            skipComposition = canSkipComposition(ctx, yuvBufferCount,
+                                         list->numHwLayers, numLayersNotUpdating);
+            s3dVideoFormat = getS3DVideoFormat(list);
+            if (s3dVideoFormat)
+                isS3DCompositionNeeded = isS3DCompositionRequired();
+        }
+
+        if (list->flags & HWC_GEOMETRY_CHANGED) {
+            if (yuvBufferCount == 1) {
+                // Inform the gralloc of the current video overlay status
+                setVideoOverlayStatusInGralloc(ctx, true);
+            }
+        }
+
+        for (size_t i=0 ; i<list->numHwLayers ; i++) {
+            private_handle_t *hnd = (private_handle_t *)list->hwLayers[i].handle;
+            // If there is a single Fullscreen layer, we can bypass it - TBD
+            // If there is only one video/camera buffer, we can bypass itn
+            if (list->hwLayers[i].flags & HWC_SKIP_LAYER) {
+                // During the animaton UI layers are marked as SKIP
+                // need to still mark the layer for S3D composition
+                if (isS3DCompositionNeeded)
+                    markUILayerForS3DComposition(list->hwLayers[i], s3dVideoFormat);
+                continue;
+            }
+            if (hnd && (hnd->bufferType == BUFFER_TYPE_VIDEO) && (yuvBufferCount == 1)) {
+                bool waitForVsync = skipComposition ? true:false;
+                if (!isValidDestination(hwcModule->fbDevice, list->hwLayers[i].displayFrame)) {
+                    list->hwLayers[i].compositionType = HWC_FRAMEBUFFER;
+                    skipComposition = false;
+                } else if(prepareOverlay(ctx, &(list->hwLayers[i]), waitForVsync) == 0) {
+                    list->hwLayers[i].compositionType = HWC_USE_OVERLAY;
+                    list->hwLayers[i].hints |= HWC_HINT_CLEAR_FB;
+                    // We've opened the channel. Set the state to open.
+                    ctx->hwcOverlayStatus = HWC_OVERLAY_OPEN;
+                } else if (hwcModule->compositionType & (COMPOSITION_TYPE_C2D)) {
+                    //Fail safe path: If drawing with overlay fails,
+
+                    //Use C2D if available.
+                    list->hwLayers[i].compositionType = HWC_USE_COPYBIT;
+                    skipComposition = false;
+                } else {
+                    //If C2D is not enabled fall back to GPU.
+                    list->hwLayers[i].compositionType = HWC_FRAMEBUFFER;
+                    skipComposition = false;
+                }
+            } else if (isS3DCompositionNeeded) {
+                markUILayerForS3DComposition(list->hwLayers[i], s3dVideoFormat);
+            } else if (list->hwLayers[i].flags == HWC_USE_ORIGINAL_RESOLUTION) {
+                list->hwLayers[i].compositionType = HWC_USE_OVERLAY;
+                list->hwLayers[i].hints |= HWC_HINT_CLEAR_FB;
+                layerType |= HWC_ORIG_RESOLUTION;
+            } else if (hnd && (hwcModule->compositionType &
+                    (COMPOSITION_TYPE_C2D|COMPOSITION_TYPE_MDP))) {
+                list->hwLayers[i].compositionType = HWC_USE_COPYBIT;
+            } else if ((hwcModule->compositionType == COMPOSITION_TYPE_DYN)
+                    && fullscreen) {
+                list->hwLayers[i].compositionType = HWC_USE_COPYBIT;
+            } else {
+                list->hwLayers[i].compositionType = HWC_FRAMEBUFFER;
+            }
+        }
+
+        if (skipComposition) {
+            list->flags |= HWC_SKIP_COMPOSITION;
+        } else {
+            list->flags &= ~HWC_SKIP_COMPOSITION;
+        }
+
+#ifdef COMPOSITION_BYPASS
+        //Check if bypass is feasible
+        if(isBypassDoable(dev, yuvBufferCount, list) &&
+                isBypassEfficient(hwcModule->fbDevice, list, ctx)) {
+            //Setup bypass
+            if(setupBypass(ctx, list)) {
+                //Overwrite layer flags only if setup succeeds.
+                setBypassLayerFlags(ctx, list);
+                list->flags |= HWC_SKIP_COMPOSITION;
+                ctx->bypassState = BYPASS_ON;
+            }
+        } else {
+            unsetBypassLayerFlags(list);
+            if(ctx->bypassState == BYPASS_ON) {
+                ctx->bypassState = BYPASS_OFF_PENDING;
+            }
+        }
+#endif
+    }
+
+    return 0;
+}
+// ---------------------------------------------------------------------------
+struct range {
+    int current;
+    int end;
+};
+struct region_iterator : public copybit_region_t {
+    
+    region_iterator(hwc_region_t region) {
+        mRegion = region;
+        r.end = region.numRects;
+        r.current = 0;
+        this->next = iterate;
+    }
+
+private:
+    static int iterate(copybit_region_t const * self, copybit_rect_t* rect) {
+        if (!self || !rect) {
+            LOGE("iterate invalid parameters");
+            return 0;
+        }
+
+        region_iterator const* me = static_cast<region_iterator const*>(self);
+        if (me->r.current != me->r.end) {
+            rect->l = me->mRegion.rects[me->r.current].left;
+            rect->t = me->mRegion.rects[me->r.current].top;
+            rect->r = me->mRegion.rects[me->r.current].right;
+            rect->b = me->mRegion.rects[me->r.current].bottom;
+            me->r.current++;
+            return 1;
+        }
+        return 0;
+    }
+    
+    hwc_region_t mRegion;
+    mutable range r; 
+};
+
+
+static int drawLayerUsingCopybit(hwc_composer_device_t *dev, hwc_layer_t *layer, EGLDisplay dpy,
+                                 EGLSurface surface)
+{
+    hwc_context_t* ctx = (hwc_context_t*)(dev);
+    if(!ctx) {
+         LOGE("drawLayerUsingCopybit null context ");
+         return -1;
+    }
+
+    private_hwc_module_t* hwcModule = reinterpret_cast<private_hwc_module_t*>(dev->common.module);
+    if(!hwcModule) {
+        LOGE("drawLayerUsingCopybit null module ");
+        return -1;
+    }
+
+    private_handle_t *hnd = (private_handle_t *)layer->handle;
+    if(!hnd) {
+        LOGE("drawLayerUsingCopybit invalid handle");
+        return -1;
+    }
+
+    // Set the copybit source:
+    copybit_image_t src;
+    src.w = ALIGN(hnd->width, 32);
+    src.h = hnd->height;
+    src.format = hnd->format;
+    src.base = (void *)hnd->base;
+    src.handle = (native_handle_t *)layer->handle;
+
+    // Copybit source rect
+    hwc_rect_t sourceCrop = layer->sourceCrop;
+    copybit_rect_t srcRect = {sourceCrop.left, sourceCrop.top,
+                              sourceCrop.right,
+                              sourceCrop.bottom};
+
+    // Copybit destination rect
+    hwc_rect_t displayFrame = layer->displayFrame;
+    copybit_rect_t dstRect = {displayFrame.left, displayFrame.top,
+                              displayFrame.right,
+                              displayFrame.bottom};
+
+    // Copybit dst
+    copybit_image_t dst;
+    android_native_buffer_t *renderBuffer = (android_native_buffer_t *)eglGetRenderBufferANDROID(dpy, surface);
+    if (!renderBuffer) {
+        LOGE("eglGetRenderBufferANDROID returned NULL buffer");
+        return -1;
+    }
+    private_handle_t *fbHandle = (private_handle_t *)renderBuffer->handle;
+    if(!fbHandle) {
+        LOGE("Framebuffer handle is NULL");
+        return -1;
+    }
+    dst.w = ALIGN(fbHandle->width,32);
+    dst.h = fbHandle->height;
+    dst.format = fbHandle->format;
+    dst.base = (void *)fbHandle->base;
+    dst.handle = (native_handle_t *)renderBuffer->handle;
+
+    // Copybit region
+    hwc_region_t region = layer->visibleRegionScreen;
+    region_iterator copybitRegion(region);
+
+    copybit_device_t *copybit = hwcModule->copybitEngine;
+    copybit->set_parameter(copybit, COPYBIT_TRANSFORM, layer->transform);
+    copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA,
+                           (layer->blending == HWC_BLENDING_NONE) ? 0xFF : layer->alpha);
+    copybit->set_parameter(copybit, COPYBIT_PREMULTIPLIED_ALPHA,
+                           (layer->blending == HWC_BLENDING_PREMULT)? COPYBIT_ENABLE : COPYBIT_DISABLE);
+    int err = copybit->stretch(copybit, &dst, &src, &dstRect, &srcRect, &copybitRegion);
+
+    if(err < 0)
+        LOGE("copybit stretch failed");
+
+    return err;
+}
+
+static int drawLayerUsingOverlay(hwc_context_t *ctx, hwc_layer_t *layer)
+{
+    if (ctx && ctx->mOverlayLibObject) {
+        private_hwc_module_t* hwcModule = reinterpret_cast<private_hwc_module_t*>(ctx->device.common.module);
+        if (!hwcModule) {
+            LOGE("drawLayerUsingLayer null module ");
+            return -1;
+        }
+        private_handle_t *hnd = (private_handle_t *)layer->handle;
+        overlay::Overlay *ovLibObject = ctx->mOverlayLibObject;
+        int ret = 0;
+
+        ret = ovLibObject->queueBuffer(hnd);
+        if (!ret) {
+            LOGE("drawLayerUsingOverlay queueBuffer failed");
+            return -1;
+        }
+    }
+    return 0;
+}
+
+static int hwc_set(hwc_composer_device_t *dev,
+        hwc_display_t dpy,
+        hwc_surface_t sur,
+        hwc_layer_list_t* list)
+{
+    hwc_context_t* ctx = (hwc_context_t*)(dev);
+    if(!ctx || !list) {
+         LOGE("hwc_set invalid context or list");
+         return -1;
+    }
+
+    private_hwc_module_t* hwcModule = reinterpret_cast<private_hwc_module_t*>(
+                                                           dev->common.module);
+    if(!hwcModule) {
+        LOGE("hwc_set null module ");
+        return -1;
+    }
+
+    int ret = 0;
+    for (size_t i=0; i<list->numHwLayers; i++) {
+        if (list->hwLayers[i].flags == HWC_SKIP_LAYER) {
+            continue;
+#ifdef COMPOSITION_BYPASS
+        } else if (list->hwLayers[i].flags == HWC_COMP_BYPASS) {
+            drawLayerUsingBypass(ctx, &(list->hwLayers[i]), i);
+#endif
+        } else if (list->hwLayers[i].compositionType == HWC_USE_OVERLAY) {
+            drawLayerUsingOverlay(ctx, &(list->hwLayers[i]));
+        } else if (list->flags & HWC_SKIP_COMPOSITION) {
+            break;
+        } else if (list->hwLayers[i].compositionType == HWC_USE_COPYBIT) {
+            drawLayerUsingCopybit(dev, &(list->hwLayers[i]), (EGLDisplay)dpy, (EGLSurface)sur);
+        }
+    }
+
+    // Do not call eglSwapBuffers if we the skip composition flag is set on the list.
+    if (!(list->flags & HWC_SKIP_COMPOSITION)) {
+        EGLBoolean sucess = eglSwapBuffers((EGLDisplay)dpy, (EGLSurface)sur);
+        if (!sucess) {
+            ret = HWC_EGL_ERROR;
+        }
+    }
+#ifdef COMPOSITION_BYPASS
+    if(ctx->bypassState == BYPASS_OFF_PENDING) {
+        closeBypass(ctx);
+        ctx->bypassState = BYPASS_OFF;
+    }
+#endif
+#if defined HDMI_DUAL_DISPLAY
+    if(ctx->pendingHDMI) {
+        handleHDMIStateChange(dev);
+        ctx->pendingHDMI = false;
+    }
+#endif
+
+    hwc_closeOverlayChannels(ctx);
+    int yuvBufferCount = getYUVBufferCount(list);
+    setHWCOverlayStatus(ctx, yuvBufferCount);
+    return ret;
+}
+
+static int hwc_device_close(struct hw_device_t *dev)
+{
+    if(!dev) {
+        LOGE("hwc_device_close null device pointer");
+        return -1;
+    }
+
+    struct hwc_context_t* ctx = (struct hwc_context_t*)dev;
+
+    private_hwc_module_t* hwcModule = reinterpret_cast<private_hwc_module_t*>(
+            ctx->device.common.module);
+
+    // Close the overlay and copybit modules
+    if(hwcModule->copybitEngine) {
+        copybit_close(hwcModule->copybitEngine);
+        hwcModule->copybitEngine = NULL;
+    }
+    if(hwcModule->overlayEngine) {
+        overlay_control_close(hwcModule->overlayEngine);
+        hwcModule->overlayEngine = NULL;
+    }
+    if(hwcModule->fbDevice) {
+        framebuffer_close(hwcModule->fbDevice);
+        hwcModule->fbDevice = NULL;
+    }
+
+    if (ctx) {
+         delete ctx->mOverlayLibObject;
+         ctx->mOverlayLibObject = NULL;
+#ifdef COMPOSITION_BYPASS
+         for(int i = 0; i < MAX_BYPASS_LAYERS; i++) {
+            delete ctx->mOvUI[i];
+         }
+#endif
+        free(ctx);
+    }
+    return 0;
+}
+
+/*****************************************************************************/
+static int hwc_module_initialize(struct private_hwc_module_t* hwcModule)
+{
+
+    // Open the overlay and copybit modules
+    hw_module_t const *module;
+
+    if (hw_get_module(COPYBIT_HARDWARE_MODULE_ID, &module) == 0) {
+        copybit_open(module, &(hwcModule->copybitEngine));
+    }
+    if (hw_get_module(OVERLAY_HARDWARE_MODULE_ID, &module) == 0) {
+        overlay_control_open(module, &(hwcModule->overlayEngine));
+    }
+    if (hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module) == 0) {
+        framebuffer_open(module, &(hwcModule->fbDevice));
+    }
+
+    // get the current composition type
+    char property[PROPERTY_VALUE_MAX];
+    if (property_get("debug.sf.hw", property, NULL) > 0) {
+        if(atoi(property) == 0) {
+            //debug.sf.hw = 0
+            hwcModule->compositionType = COMPOSITION_TYPE_CPU;
+        } else { //debug.sf.hw = 1
+            // Get the composition type
+            property_get("debug.composition.type", property, NULL);
+            if (property == NULL) {
+                hwcModule->compositionType = COMPOSITION_TYPE_GPU;
+            } else if ((strncmp(property, "mdp", 3)) == 0) {
+                hwcModule->compositionType = COMPOSITION_TYPE_MDP;
+            } else if ((strncmp(property, "c2d", 3)) == 0) {
+                hwcModule->compositionType = COMPOSITION_TYPE_C2D;
+            } else if ((strncmp(property, "dyn", 3)) == 0) {
+                hwcModule->compositionType = COMPOSITION_TYPE_DYN;
+            } else {
+                hwcModule->compositionType = COMPOSITION_TYPE_GPU;
+            }
+
+            if(!hwcModule->copybitEngine)
+                hwcModule->compositionType = COMPOSITION_TYPE_GPU;
+            }
+    } else { //debug.sf.hw is not set. Use cpu composition
+        hwcModule->compositionType = COMPOSITION_TYPE_CPU;
+    }
+
+    //Check if composition bypass is enabled
+    if(property_get("debug.compbypass.enable", property, NULL) > 0) {
+        if(atoi(property) == 1) {
+            hwcModule->isBypassEnabled = true;
+        }
+    }
+
+    return 0;
+}
+
+
+static int hwc_device_open(const struct hw_module_t* module, const char* name,
+        struct hw_device_t** device)
+{
+    int status = -EINVAL;
+    if (!strcmp(name, HWC_HARDWARE_COMPOSER)) {
+	 private_hwc_module_t* hwcModule = reinterpret_cast<private_hwc_module_t*>
+                                        (const_cast<hw_module_t*>(module));
+        
+	hwc_module_initialize(hwcModule);
+        struct hwc_context_t *dev;
+        dev = (hwc_context_t*)malloc(sizeof(*dev));
+
+        /* initialize our state here */
+        memset(dev, 0, sizeof(*dev));
+        if(hwcModule->overlayEngine) {
+            dev->mOverlayLibObject = new overlay::Overlay();
+#ifdef COMPOSITION_BYPASS
+            for(int i = 0; i < MAX_BYPASS_LAYERS; i++) {
+                dev->mOvUI[i] = new overlay::OverlayUI();
+            }
+            dev->animCount = 0;
+            dev->bypassState = BYPASS_OFF;
+#endif
+        } else {
+            dev->mOverlayLibObject = NULL;
+#ifdef COMPOSITION_BYPASS
+            for(int i = 0; i < MAX_BYPASS_LAYERS; i++) {
+                dev->mOvUI[i] = NULL;
+            }
+#endif
+        }
+#if defined HDMI_DUAL_DISPLAY
+        dev->mHDMIEnabled = false;
+        dev->pendingHDMI = false;
+#endif
+        dev->hwcOverlayStatus = HWC_OVERLAY_CLOSED;
+        /* initialize the procs */
+        dev->device.common.tag = HARDWARE_DEVICE_TAG;
+        dev->device.common.version = 0;
+        dev->device.common.module = const_cast<hw_module_t*>(module);
+        dev->device.common.close = hwc_device_close;
+
+        dev->device.prepare = hwc_prepare;
+        dev->device.set = hwc_set;
+        dev->device.enableHDMIOutput = hwc_enableHDMIOutput;
+        *device = &dev->device.common;
+
+        status = 0;
+    }
+    return status;
+}
diff --git a/liboverlay/Android.mk b/liboverlay/Android.mk
new file mode 100644
index 0000000..0f3512c
--- /dev/null
+++ b/liboverlay/Android.mk
@@ -0,0 +1,53 @@
+# Copyright (C) 2008 The Android Open Source Project
+# Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+#
+#  Licensed under the Apache License, Version 2.0 (the "License");
+#  you may not use this file except in compliance with the License.
+#  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+#  Unless required by applicable law or agreed to in writing, software
+#  distributed under the License is distributed on an "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#  See the License for the specific language governing permissions and
+#  limitations under the License
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_PRELINK_MODULE := false
+LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)
+LOCAL_SHARED_LIBRARIES := liblog libcutils libutils
+LOCAL_C_INCLUDES += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr/include
+LOCAL_ADDITIONAL_DEPENDENCIES += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr
+LOCAL_C_INCLUDES += hardware/qcom/display/libgralloc
+LOCAL_SRC_FILES := \
+    overlayLib.cpp \
+    overlayLibUI.cpp \
+LOCAL_CFLAGS:= -DLOG_TAG=\"OverlayLib\"
+
+ifeq ($(TARGET_USES_ION),true)
+    LOCAL_CFLAGS += -DUSE_ION
+    LOCAL_SHARED_LIBRARIES += libmemalloc
+endif
+
+ifeq ($(TARGET_USE_HDMI_AS_PRIMARY),true)
+LOCAL_CFLAGS += -DHDMI_AS_PRIMARY
+endif
+LOCAL_MODULE := liboverlay
+include $(BUILD_SHARED_LIBRARY)
+
+# HAL module implemenation, not prelinked and stored in
+# hw/<OVERLAY_HARDWARE_MODULE_ID>.<ro.product.board>.so
+include $(CLEAR_VARS)
+LOCAL_PRELINK_MODULE := false
+LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw
+LOCAL_SHARED_LIBRARIES := liblog liboverlay libcutils
+LOCAL_C_INCLUDES += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr/include
+LOCAL_ADDITIONAL_DEPENDENCIES += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr
+LOCAL_C_INCLUDES += hardware/qcom/display/libgralloc
+LOCAL_SRC_FILES := overlay.cpp
+LOCAL_MODULE := overlay.default
+include $(BUILD_SHARED_LIBRARY)
diff --git a/liboverlay/overlay.cpp b/liboverlay/overlay.cpp
new file mode 100644
index 0000000..aa2828b
--- /dev/null
+++ b/liboverlay/overlay.cpp
@@ -0,0 +1,1197 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * Copyright (c) 2009, Code Aurora Forum. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "Overlay"
+
+#include <hardware/hardware.h>
+#include "overlayLib.h"
+#include <cutils/properties.h>
+#include <cutils/ashmem.h>
+#include <utils/threads.h>
+#include <linux/ashmem.h>
+#include <gralloc_priv.h>
+
+using android::Mutex;
+
+#define USE_MSM_ROTATOR
+#define EVEN_OUT(x) if (x & 0x0001) {x--;}
+
+#define SHARED_MEMORY_REGION_NAME "overlay_shared_memory"
+
+#define OVERLAY_HDMI_ENABLE 8
+
+/*****************************************************************************/
+
+
+using namespace overlay;
+
+struct overlay_control_context_t {
+    struct overlay_control_device_t device;
+    void *sharedMemBase;
+    unsigned int format3D; //input and output 3D format, zero means no 3D
+    unsigned int state;
+    unsigned int orientation;
+    overlay_rect posPanel;
+};
+
+struct overlay_data_context_t {
+    struct overlay_data_device_t device;
+    OverlayDataChannel* pobjDataChannel[2];
+    unsigned int format3D;
+    unsigned int state;
+    bool setCrop;
+    overlay_rect cropRect;
+    int srcFD; //store the FD as it will needed for fb1
+    int size;  //size of the overlay created
+    void *sharedMemBase;
+};
+
+///////////////////////////////////////////////////////////////////////////////////
+
+/* Overlay State func FIXME move to a separate module */
+class overlay_object;
+int setParameterHandleState(overlay_control_context_t *ctx,
+        overlay_object *obj,
+        int param, int value);
+int createOverlayHandleState(overlay_control_context_t *ctx, bool noRot,
+        overlay_object* overlay, int fd);
+int setPositionHandleState(overlay_control_context_t *ctx,
+        overlay_object *obj, overlay_rect& rect,
+        int x, int y, uint32_t w, uint32_t h);
+int configPipes_OV_2D_VIDEO_ON_PANEL(overlay_control_context_t *ctx,
+        overlay_object *obj,
+        unsigned int newState,
+        int enable, bool noRot,
+        overlay_rect& rect);
+
+int configPipes_OV_3D_VIDEO_2D_PANEL(overlay_control_context_t *ctx,
+        overlay_object *obj,
+        unsigned int newState,
+        int enable, bool noRot,
+        overlay_rect& rect);
+
+int configPipes_OV_3D_VIDEO_3D_PANEL(overlay_control_context_t *ctx,
+        overlay_object *obj,
+        unsigned int newState,
+        int enable, bool noRot,
+        overlay_rect& rect);
+
+int configPipes_OV_2D_VIDEO_ON_TV(overlay_control_context_t *ctx,
+        overlay_object *obj,
+        unsigned int newState,
+        int enable, bool noRot,
+        overlay_rect& rect);
+
+int configPipes_OV_3D_VIDEO_2D_TV(overlay_control_context_t *ctx,
+        overlay_object *obj,
+        unsigned int newState,
+        int enable, bool noRot,
+        overlay_rect& rect);
+
+int configPipes_OV_3D_VIDEO_3D_TV(overlay_control_context_t *ctx,
+        overlay_object *obj,
+        unsigned int newState,
+        int enable, bool noRot,
+        overlay_rect& rect);
+
+/* queue buffer */
+int queueBuffer_OV_2D_VIDEO_ON_PANEL(overlay_data_context_t *ctx,
+        overlay_shared_data* data,
+        unsigned int newState, bool noRot);
+
+int queueBuffer_OV_3D_VIDEO_2D_PANEL(overlay_data_context_t *ctx,
+        overlay_shared_data* data,
+        unsigned int newState, bool noRot);
+
+
+int queueBuffer_OV_3D_VIDEO_3D_PANEL(overlay_data_context_t *ctx,
+        overlay_shared_data* data,
+        unsigned int newState, bool noRot);
+
+int queueBuffer_OV_2D_VIDEO_ON_TV(overlay_data_context_t *ctx,
+        overlay_shared_data* data,
+        unsigned int newState, bool noRot);
+
+int queueBuffer_OV_3D_VIDEO_2D_TV(overlay_data_context_t *ctx,
+        overlay_shared_data* data,
+        unsigned int newState, bool noRot);
+
+int queueBuffer_OV_3D_VIDEO_3D_TV(overlay_data_context_t *ctx,
+        overlay_shared_data* data,
+        unsigned int newState, bool noRot);
+
+///////////////////////////////////////////////////////////////////////////////////
+
+
+static int overlay_device_open(const struct hw_module_t* module, const char* name,
+        struct hw_device_t** device);
+
+static struct hw_module_methods_t overlay_module_methods = {
+open: overlay_device_open
+};
+
+struct private_overlay_module_t {
+    overlay_module_t base;
+    Mutex *pobjMutex;
+};
+
+struct private_overlay_module_t HAL_MODULE_INFO_SYM = {
+base: {
+common: {
+tag: HARDWARE_MODULE_TAG,
+     version_major: 1,
+     version_minor: 0,
+     id: OVERLAY_HARDWARE_MODULE_ID,
+     name: "QCT MSM OVERLAY module",
+     author: "QuIC, Inc.",
+     methods: &overlay_module_methods,
+        }
+      },
+pobjMutex: NULL,
+};
+
+struct handle_t : public native_handle {
+    int sharedMemoryFd;
+    int ovid[2];
+    int rotid[2];
+    int size;
+    int w;
+    int h;
+    int format;
+    unsigned int format3D;
+    OverlayControlChannel *pobjControlChannel[2];
+};
+
+static int handle_get_ovId(const overlay_handle_t overlay, int index = 0) {
+    return static_cast<const struct handle_t *>(overlay)->ovid[index];
+}
+
+static int handle_get_rotId(const overlay_handle_t overlay, int index = 0) {
+    return static_cast<const struct handle_t *>(overlay)->rotid[index];
+}
+
+static int handle_get_size(const overlay_handle_t overlay) {
+    return static_cast<const struct handle_t *>(overlay)->size;
+}
+
+static int handle_get_width(const overlay_handle_t overlay) {
+    return static_cast<const struct handle_t *>(overlay)->w;
+}
+
+static int handle_get_height(const overlay_handle_t overlay) {
+    return static_cast<const struct handle_t *>(overlay)->h;
+}
+
+static int handle_get_shared_fd(const overlay_handle_t overlay) {
+    return static_cast<const struct handle_t *>(overlay)->sharedMemoryFd;
+}
+
+static int handle_get_format3D(const overlay_handle_t overlay) {
+    return static_cast<const struct handle_t *>(overlay)->format3D;
+}
+
+/*
+ * This is the overlay_t object, it is returned to the user and represents
+ * an overlay.
+ * This handles will be passed across processes and possibly given to other
+ * HAL modules (for instance video decode modules).
+ */
+class overlay_object : public overlay_t {
+    handle_t mHandle;
+
+    static overlay_handle_t getHandleRef(struct overlay_t* overlay) {
+        /* returns a reference to the handle, caller doesn't take ownership */
+        return &(static_cast<overlay_object *>(overlay)->mHandle);
+    }
+
+    public:
+        overlay_object(int w, int h, int format, int fd, unsigned int format3D = 0) {
+            this->overlay_t::getHandleRef = getHandleRef;
+            this->overlay_t::w = w;
+            this->overlay_t::h = h;
+            mHandle.version = sizeof(native_handle);
+            mHandle.sharedMemoryFd = fd;
+            mHandle.numFds = 1;
+            mHandle.numInts = (sizeof(mHandle) - sizeof(native_handle)) / 4;
+            mHandle.ovid[0] = -1;
+            mHandle.ovid[1] = -1;
+            mHandle.rotid[0] = -1;
+            mHandle.rotid[1] = -1;
+            mHandle.size = -1;
+            mHandle.w = w;
+            mHandle.h = h;
+            mHandle.format = format;
+            mHandle.format3D = format3D;
+            mHandle.pobjControlChannel[0] = 0;
+            mHandle.pobjControlChannel[1] = 0;
+        }
+
+    ~overlay_object() {
+        destroy_overlay();
+    }
+
+    int getHwOvId(int index = 0) { return mHandle.ovid[index]; }
+    int getRotSessionId(int index = 0) { return mHandle.rotid[index]; }
+    int getSharedMemoryFD() {return mHandle.sharedMemoryFd;}
+
+    bool startControlChannel(int fbnum, bool norot = false, int zorder = 0) {
+        int index = fbnum;
+        if (mHandle.format3D)
+            index = zorder;
+        if (!mHandle.pobjControlChannel[index])
+            mHandle.pobjControlChannel[index] = new OverlayControlChannel();
+        else {
+            mHandle.pobjControlChannel[index]->closeControlChannel();
+            mHandle.pobjControlChannel[index] = new OverlayControlChannel();
+        }
+        bool ret = mHandle.pobjControlChannel[index]->startControlChannel(
+                mHandle.w, mHandle.h, mHandle.format, fbnum, norot, false,
+                mHandle.format3D, zorder, true);
+        if (ret) {
+            if (!(mHandle.pobjControlChannel[index]->
+                        getOvSessionID(mHandle.ovid[index]) &&
+                        mHandle.pobjControlChannel[index]->
+                        getRotSessionID(mHandle.rotid[index]) &&
+                        mHandle.pobjControlChannel[index]->
+                        getSize(mHandle.size)))
+                ret = false;
+        }
+
+        if (!ret) {
+            closeControlChannel(index);
+        }
+
+        return ret;
+    }
+
+    bool setPosition(int x, int y, uint32_t w, uint32_t h, int channel) {
+        if (!mHandle.pobjControlChannel[channel])
+            return false;
+        return mHandle.pobjControlChannel[channel]->setPosition(
+                x, y, w, h);
+    }
+
+    bool getAspectRatioPosition(overlay_rect *rect, int channel) {
+        if (!mHandle.pobjControlChannel[channel])
+            return false;
+        return mHandle.pobjControlChannel[channel]->getAspectRatioPosition(mHandle.w,
+                mHandle.h, rect);
+    }
+
+    bool setParameter(int param, int value, int channel) {
+        if (!mHandle.pobjControlChannel[channel])
+            return false;
+        return mHandle.pobjControlChannel[channel]->setParameter(
+                param, value);
+    }
+
+    bool closeControlChannel(int channel) {
+        if (!mHandle.pobjControlChannel[channel])
+            return true;
+        bool ret = mHandle.pobjControlChannel[channel]->
+            closeControlChannel();
+        delete mHandle.pobjControlChannel[channel];
+        mHandle.pobjControlChannel[channel] = 0;
+        return ret;
+    }
+
+    bool getPositionS3D(overlay_rect *rect, int channel, bool useVFB = false) {
+        if (!mHandle.pobjControlChannel[channel]) {
+            LOGE("%s:Failed got channel %d", __func__, channel);
+            return false;
+        }
+        int format = useVFB ? HAL_3D_OUT_SIDE_BY_SIDE_MASK : mHandle.format3D;
+        return mHandle.pobjControlChannel[channel]->getPositionS3D(
+                channel, format, rect);
+    }
+
+    bool getPosition(int *x, int *y, uint32_t *w, uint32_t *h, int channel) {
+        if (!mHandle.pobjControlChannel[channel])
+            return false;
+        return mHandle.pobjControlChannel[channel]->getPosition(
+                *x, *y, *w, *h);
+    }
+
+    bool getOrientation(int *orientation, int channel) {
+        if (!mHandle.pobjControlChannel[channel])
+            return false;
+        return mHandle.pobjControlChannel[channel]->getOrientation(
+                *orientation);
+    }
+
+    void destroy_overlay() {
+        close(mHandle.sharedMemoryFd);
+        closeControlChannel(VG1_PIPE);
+        closeControlChannel(VG0_PIPE);
+        if(mHandle.format3D) {
+            send3DInfoPacket (0);
+            enableBarrier(0);
+        }
+    }
+
+    int getFBWidth(int channel) {
+        if (!mHandle.pobjControlChannel[channel])
+            return false;
+        return mHandle.pobjControlChannel[channel]->getFBWidth();
+    }
+
+    int getFBHeight(int channel) {
+        if (!mHandle.pobjControlChannel[channel])
+            return false;
+        return mHandle.pobjControlChannel[channel]->getFBHeight();
+    }
+
+    inline void setFormat3D(unsigned int format3D) {
+        mHandle.format3D = format3D;
+    }
+
+    inline bool useVirtualFB(int channel) {
+        if (!mHandle.pobjControlChannel[channel])
+            return false;
+        return mHandle.pobjControlChannel[channel]->useVirtualFB();
+    }
+};
+
+// ****************************************************************************
+// Control module
+// ****************************************************************************
+
+static int overlay_get(struct overlay_control_device_t *dev, int name) {
+    int result = -1;
+    switch (name) {
+        case OVERLAY_MINIFICATION_LIMIT:
+            result = HW_OVERLAY_MINIFICATION_LIMIT;
+            break;
+        case OVERLAY_MAGNIFICATION_LIMIT:
+            result = HW_OVERLAY_MAGNIFICATION_LIMIT;
+            break;
+        case OVERLAY_SCALING_FRAC_BITS:
+            result = 32;
+            break;
+        case OVERLAY_ROTATION_STEP_DEG:
+            result = 90; // 90 rotation steps (for instance)
+            break;
+        case OVERLAY_HORIZONTAL_ALIGNMENT:
+            result = 1;	// 1-pixel alignment
+            break;
+        case OVERLAY_VERTICAL_ALIGNMENT:
+            result = 1;	// 1-pixel alignment
+            break;
+        case OVERLAY_WIDTH_ALIGNMENT:
+            result = 1;	// 1-pixel alignment
+            break;
+        case OVERLAY_HEIGHT_ALIGNMENT:
+            result = 1;	// 1-pixel alignment
+            break;
+    }
+    return result;
+}
+
+static void error_cleanup_control(overlay_control_context_t *ctx, overlay_object *overlay, int fd, int index) {
+    LOGE("Failed to start control channel %d", index);
+    for (int i = 0; i < index; i++)
+        overlay->closeControlChannel(i);
+    if(ctx && (ctx->sharedMemBase != MAP_FAILED)) {
+        munmap(ctx->sharedMemBase, sizeof(overlay_shared_data));
+        ctx->sharedMemBase = MAP_FAILED;
+    }
+    if(fd > 0)
+        close(fd);
+    delete overlay;
+}
+
+static overlay_t* overlay_createOverlay(struct overlay_control_device_t *dev,
+        uint32_t w, uint32_t h, int32_t format) {
+    overlay_object            *overlay = NULL;
+    overlay_control_context_t *ctx = (overlay_control_context_t *)dev;
+    private_overlay_module_t* m = reinterpret_cast<private_overlay_module_t*>(
+            dev->common.module);
+    Mutex::Autolock objLock(m->pobjMutex);
+
+    // Open shared memory to store shared data
+    int size = sizeof(overlay_shared_data);
+    void *base;
+    int fd = ashmem_create_region(SHARED_MEMORY_REGION_NAME,
+            size);
+    if(fd < 0) {
+        LOGE("%s: create shared memory failed", __func__);
+        return NULL;
+    }
+    if (ashmem_set_prot_region(fd, PROT_READ | PROT_WRITE) < 0) {
+        LOGE("ashmem_set_prot_region(fd=%d, failed (%s)",
+                fd, strerror(-errno));
+        close(fd);
+        fd = -1;
+        return NULL;
+    } else {
+        base = mmap(0, size, PROT_READ | PROT_WRITE,
+                MAP_SHARED|MAP_POPULATE, fd, 0);
+        if (base == MAP_FAILED) {
+            LOGE("alloc mmap(fd=%d, size=%d) failed (%s)",
+                    fd, size, strerror(-errno));
+            close(fd);
+            fd = -1;
+            return NULL;
+        }
+    }
+
+    // Separate the color format from the 3D format.
+    // If there is 3D content; the effective format passed by the client is:
+    // effectiveFormat = 3D_IN | 3D_OUT | ColorFormat
+    unsigned int format3D = FORMAT_3D(format);
+    format = COLOR_FORMAT(format);
+    int fIn3D = FORMAT_3D_INPUT(format3D); // MSB 2 bytes are input format
+    int fOut3D = FORMAT_3D_OUTPUT(format3D); // LSB 2 bytes are output format
+    format3D = fIn3D | fOut3D;
+    // Use the same in/out format if not mentioned
+    if (!fIn3D) {
+        format3D |= fOut3D << SHIFT_3D; //Set the input format
+    }
+    if(!fOut3D) {
+        switch (fIn3D) {
+            case HAL_3D_IN_SIDE_BY_SIDE_L_R:
+            case HAL_3D_IN_SIDE_BY_SIDE_R_L:
+                // For all side by side formats, set the output
+                // format as Side-by-Side i.e 0x1
+                format3D |= HAL_3D_IN_SIDE_BY_SIDE_L_R >> SHIFT_3D;
+                break;
+            default:
+                format3D |= fIn3D >> SHIFT_3D; //Set the output format
+                break;
+        }
+    }
+    unsigned int curState = overlay::getOverlayConfig(format3D);
+    if (curState == OV_3D_VIDEO_2D_PANEL || curState == OV_3D_VIDEO_2D_TV) {
+        LOGI("3D content on 2D display: set the output format as monoscopic");
+        format3D = FORMAT_3D_INPUT(format3D) | HAL_3D_OUT_MONOSCOPIC_MASK;
+    }
+    LOGW("createOverlay: creating overlay with format3D: 0x%x, curState: %d", format3D, curState);
+    ctx->sharedMemBase = base;
+    ctx->format3D = format3D;
+    ctx->state = curState;
+    memset(ctx->sharedMemBase, 0, size);
+
+    /* number of buffer is not being used as overlay buffers are coming from client */
+    overlay = new overlay_object(w, h, format, fd, format3D);
+    if (overlay == NULL) {
+        LOGE("%s: can't create overlay object!", __FUNCTION__);
+        if(ctx && (ctx->sharedMemBase != MAP_FAILED)) {
+            munmap(ctx->sharedMemBase, size);
+            ctx->sharedMemBase = MAP_FAILED;
+        }
+        if(fd > 0)
+            close(fd);
+        return NULL;
+    }
+    bool noRot;
+#ifdef USE_MSM_ROTATOR
+    noRot = false;
+#else
+    noRot = true;
+#endif
+    if(-1 == createOverlayHandleState(ctx, noRot, overlay, fd))
+        return 0;// NULL
+    overlay_shared_data* data = static_cast<overlay_shared_data*>(ctx->sharedMemBase);
+    data->state = ctx->state;
+    for (int i=0; i<NUM_CHANNELS; i++) {
+        data->ovid[i]  = overlay->getHwOvId(i);
+        data->rotid[i] = overlay->getRotSessionId(i);
+    }
+    return overlay;
+}
+
+static void overlay_destroyOverlay(struct overlay_control_device_t *dev,
+        overlay_t* overlay)
+{
+    overlay_control_context_t *ctx = (overlay_control_context_t *)dev;
+    overlay_object * obj = static_cast<overlay_object *>(overlay);
+    private_overlay_module_t* m = reinterpret_cast<private_overlay_module_t*>(
+            dev->common.module);
+    Mutex::Autolock objLock(m->pobjMutex);
+    if(ctx && (ctx->sharedMemBase != MAP_FAILED)) {
+        munmap(ctx->sharedMemBase, sizeof(overlay_shared_data));
+        ctx->sharedMemBase = MAP_FAILED;
+    }
+    // ~overlay_object calls destroy_overlay
+    delete obj;
+}
+
+static int overlay_setPosition(struct overlay_control_device_t *dev,
+        overlay_t* overlay,
+        int x, int y, uint32_t w, uint32_t h) {
+    /* set this overlay's position (talk to the h/w) */
+    overlay_control_context_t *ctx = (overlay_control_context_t *)dev;
+    overlay_object * obj = static_cast<overlay_object *>(overlay);
+    private_overlay_module_t* m = reinterpret_cast<private_overlay_module_t*>(
+            dev->common.module);
+    Mutex::Autolock objLock(m->pobjMutex);
+    bool ret;
+    overlay_rect rect;
+    // saving the position for the disconnection event
+    ctx->posPanel.x = x;
+    ctx->posPanel.y = y;
+    ctx->posPanel.w = w;
+    ctx->posPanel.h = h;
+
+    if(-1 == setPositionHandleState(ctx, obj, rect, x, y, w, h))
+        return -1;
+
+    return 0;
+}
+
+static int overlay_commit(struct overlay_control_device_t *dev,
+        overlay_t* overlay)
+{
+    overlay_control_context_t *ctx = (overlay_control_context_t *)dev;
+    overlay_object *obj = static_cast<overlay_object *>(overlay);
+    private_overlay_module_t* m = reinterpret_cast<private_overlay_module_t*>(
+            dev->common.module);
+
+    Mutex::Autolock objLock(m->pobjMutex);
+    if (obj && (obj->getSharedMemoryFD() > 0) &&
+            (ctx->sharedMemBase != MAP_FAILED)) {
+        overlay_shared_data* data = static_cast<overlay_shared_data*>(ctx->sharedMemBase);
+        data->isControlSetup = true;
+    }
+    return 0;
+}
+
+static int overlay_getPosition(struct overlay_control_device_t *dev,
+        overlay_t* overlay,
+        int* x, int* y, uint32_t* w, uint32_t* h) {
+
+    /* get this overlay's position */
+    private_overlay_module_t* m = reinterpret_cast<private_overlay_module_t*>(
+            dev->common.module);
+    Mutex::Autolock objLock(m->pobjMutex);
+    overlay_object * obj = static_cast<overlay_object *>(overlay);
+    return obj->getPosition(x, y, w, h, 0) ? 0 : -1;
+}
+
+static bool overlay_configPipes(overlay_control_context_t *ctx,
+        overlay_object *obj, int enable,
+        unsigned int newState) {
+    bool noRot = true;
+    overlay_rect rect;
+#ifdef USE_MSM_ROTATOR
+    noRot = false;
+#else
+    noRot = true;
+#endif
+    switch (ctx->state)
+    {
+        case OV_2D_VIDEO_ON_PANEL:
+            if(-1 == configPipes_OV_2D_VIDEO_ON_PANEL(ctx,
+                        obj,
+                        newState,
+                        enable, noRot, rect))
+                return false;
+            break;
+        case OV_3D_VIDEO_2D_PANEL:
+            if(-1 == configPipes_OV_3D_VIDEO_2D_PANEL(ctx,
+                        obj,
+                        newState,
+                        enable, noRot, rect))
+                return false;
+            break;
+        case OV_3D_VIDEO_3D_PANEL:
+            if(-1 == configPipes_OV_3D_VIDEO_3D_PANEL(ctx,
+                        obj,
+                        newState,
+                        enable, noRot, rect))
+                return false;
+            break;
+        case OV_2D_VIDEO_ON_TV:
+            if(-1 == configPipes_OV_2D_VIDEO_ON_TV(ctx,
+                        obj,
+                        newState,
+                        enable, noRot, rect))
+                return false;
+            break;
+        case OV_3D_VIDEO_2D_TV:
+            if(-1 == configPipes_OV_3D_VIDEO_2D_TV(ctx,
+                        obj,
+                        newState,
+                        enable, noRot, rect))
+                return false;
+            break;
+        case OV_3D_VIDEO_3D_TV:
+            if(-1 == configPipes_OV_3D_VIDEO_3D_TV(ctx,
+                        obj,
+                        newState,
+                        enable, noRot, rect))
+                return false;
+            break;
+        default:
+            LOGE("Unknown state in configPipes");
+            abort();
+    }
+    //update the context's state
+    ctx->state = newState;
+    return true;
+}
+
+static int overlay_setParameter(struct overlay_control_device_t *dev,
+        overlay_t* overlay, int param, int value) {
+
+    overlay_control_context_t *ctx = (overlay_control_context_t *)dev;
+    overlay_object *obj = static_cast<overlay_object *>(overlay);
+    private_overlay_module_t* m = reinterpret_cast<private_overlay_module_t*>(
+            dev->common.module);
+    Mutex::Autolock objLock(m->pobjMutex);
+
+    if (obj && (obj->getSharedMemoryFD() > 0) &&
+            (ctx->sharedMemBase != MAP_FAILED)) {
+        overlay_shared_data* data = static_cast<overlay_shared_data*>(ctx->sharedMemBase);
+        data->isControlSetup = false;
+        /* SF will inform Overlay HAL the HDMI cable connection.
+           This avoids polling on the system property hw.hdmiON */
+        if(param == OVERLAY_HDMI_ENABLE) {
+            unsigned int curState = getOverlayConfig(ctx->format3D, false, value);
+            if(ctx->state != curState) {
+                LOGI("Overlay Configured for : %d Current state: %d", ctx->state, curState);
+                if(!overlay_configPipes(ctx, obj, value, curState)) {
+                    LOGE("In overlay_setParameter: reconfiguring of Overlay failed !!");
+                    return -1;
+                }
+                else {
+                    data->state = ctx->state;
+                    for (int i=0; i<NUM_CHANNELS; i++) {
+                        data->ovid[i]  = obj->getHwOvId(i);
+                        data->rotid[i] = obj->getRotSessionId(i);
+                    }
+                }
+            }
+        }
+    }
+    if(param != OVERLAY_HDMI_ENABLE) {
+        //Save the panel orientation
+        if (param == OVERLAY_TRANSFORM) {
+            ctx->orientation = value;
+            if(ctx->state == OV_3D_VIDEO_3D_PANEL) {
+                int barrier = 0;
+                switch(ctx->orientation) {
+                case HAL_TRANSFORM_ROT_90:
+                case HAL_TRANSFORM_ROT_270:
+                    barrier = BARRIER_LANDSCAPE;
+                    break;
+                default:
+                    barrier = BARRIER_PORTRAIT;
+                    break;
+                }
+                if(!enableBarrier(barrier))
+                    LOGE("%s:failed to enable barriers for 3D video", __func__);
+            }
+        }
+        if (-1 == setParameterHandleState(ctx, obj, param, value))
+            return -1;
+    }
+    return 0;
+}
+
+static int overlay_control_close(struct hw_device_t *dev)
+{
+    struct overlay_control_context_t* ctx = (struct overlay_control_context_t*)dev;
+    if (ctx) {
+        /* free all resources associated with this device here
+         * in particular the overlay_handle_t, outstanding overlay_t, etc...
+         */
+        free(ctx);
+    }
+    return 0;
+}
+
+// ****************************************************************************
+// Data module
+// ****************************************************************************
+
+static void error_cleanup_data(struct overlay_data_context_t* ctx, int index)
+{
+    LOGE("Couldn't start data channel %d", index);
+    for (int i = 0; i<index; i++) {
+        delete ctx->pobjDataChannel[i];
+        ctx->pobjDataChannel[i] = NULL;
+    }
+}
+
+int overlay_initialize(struct overlay_data_device_t *dev,
+        overlay_handle_t handle)
+{
+    /*
+     * overlay_handle_t should contain all the information to "inflate" this
+     * overlay. Typically it'll have a file descriptor, informations about
+     * how many buffers are there, etc...
+     * It is also the place to mmap all buffers associated with this overlay
+     * (see getBufferAddress).
+     *
+     * NOTE: this function doesn't take ownership of overlay_handle_t
+     *
+     */
+
+    struct overlay_data_context_t* ctx = (struct overlay_data_context_t*)dev;
+    int ovid = handle_get_ovId(handle);
+    int rotid = handle_get_rotId(handle);
+    int size = handle_get_size(handle);
+    int sharedFd = handle_get_shared_fd(handle);
+    unsigned int format3D = handle_get_format3D(handle);
+    private_overlay_module_t* m = reinterpret_cast<private_overlay_module_t*>(
+            dev->common.module);
+    Mutex::Autolock objLock(m->pobjMutex);
+    bool noRot = true;
+#ifdef USE_MSM_ROTATOR
+    noRot = false;
+#else
+    noRot = true;
+#endif
+    //default: set crop info to src size.
+    ctx->cropRect.x = 0;
+    ctx->cropRect.y = 0;
+    ctx->cropRect.w = handle_get_width(handle);
+    ctx->cropRect.h = handle_get_height(handle);
+
+    ctx->sharedMemBase = MAP_FAILED;
+    ctx->format3D = format3D;
+    //Store the size, needed for HDMI mirroring
+    ctx->size = size;
+
+    if(sharedFd > 0) {
+        void *base = mmap(0, sizeof(overlay_shared_data), PROT_READ,
+                MAP_SHARED|MAP_POPULATE, sharedFd, 0);
+        if(base == MAP_FAILED) {
+            LOGE("%s: map region failed %d", __func__, -errno);
+            return -1;
+        }
+        ctx->sharedMemBase = base;
+    } else {
+        LOGE("Received invalid shared memory fd");
+        return -1;
+    }
+    overlay_shared_data* data = static_cast<overlay_shared_data*>
+        (ctx->sharedMemBase);
+    if (data == NULL){
+        LOGE("%s:Shared data is NULL!!", __func__);
+        return -1;
+    }
+    ctx->state = data->state;
+    switch (ctx->state) {
+        case OV_2D_VIDEO_ON_PANEL:
+        case OV_3D_VIDEO_2D_PANEL:
+            ctx->pobjDataChannel[VG0_PIPE] = new OverlayDataChannel();
+            if (!ctx->pobjDataChannel[VG0_PIPE]->startDataChannel(ovid, rotid, size, FRAMEBUFFER_0, noRot)) {
+                error_cleanup_data(ctx, VG0_PIPE);
+                return -1;
+            }
+            break;
+        case OV_3D_VIDEO_3D_PANEL:
+            overlay_rect rect;
+            for (int i = 0; i < NUM_CHANNELS; i++) {
+                ovid = handle_get_ovId(handle, i);
+                rotid = handle_get_rotId(handle, i);
+                ctx->pobjDataChannel[i] = new OverlayDataChannel();
+                if (!ctx->pobjDataChannel[i]->startDataChannel(ovid, rotid, size, FRAMEBUFFER_0, noRot)) {
+                    error_cleanup_data(ctx, i);
+                    return -1;
+                }
+            }
+            break;
+        case OV_2D_VIDEO_ON_TV:
+        case OV_3D_VIDEO_2D_TV:
+            for (int i = 0; i < NUM_CHANNELS; i++) {
+                ovid = handle_get_ovId(handle, i);
+                rotid = handle_get_rotId(handle, i);
+                ctx->pobjDataChannel[i] = new OverlayDataChannel();
+                if (FRAMEBUFFER_1 == i)
+                    noRot = true;
+                if (!ctx->pobjDataChannel[i]->startDataChannel(ovid, rotid, size, i, noRot)) {
+                    error_cleanup_data(ctx, i);
+                    return -1;
+                }
+            }
+            break;
+        case OV_3D_VIDEO_3D_TV:
+            for (int i = 0; i < NUM_CHANNELS; i++) {
+                ovid = handle_get_ovId(handle, i);
+                rotid = handle_get_rotId(handle, i);
+                ctx->pobjDataChannel[i] = new OverlayDataChannel();
+                if (!ctx->pobjDataChannel[i]->startDataChannel(ovid, rotid, size, FRAMEBUFFER_1, true)) {
+                    error_cleanup_data(ctx, i);
+                    return -1;
+                }
+            }
+            if(!send3DInfoPacket(ctx->format3D & OUTPUT_MASK_3D))
+                LOGI("%s:Error setting the 3D mode for TV", __func__);
+            break;
+        default:
+            break;
+    }
+    return 0;
+}
+
+int overlay_dequeueBuffer(struct overlay_data_device_t *dev,
+        overlay_buffer_t* buf)
+{
+    /* blocks until a buffer is available and return an opaque structure
+     * representing this buffer.
+     */
+
+    /* no internal overlay buffer to dequeue */
+    LOGE("%s: no buffer to dequeue ...\n", __FUNCTION__);
+
+    return 0;
+}
+
+//Called with Mutex::Autolock objLock(m->pobjMutex); already held
+int overlay_queueBufferCheckStateChange(struct overlay_data_device_t *dev,
+        overlay_buffer_t buffer)
+{
+    /* Mark this buffer for posting and recycle or free overlay_buffer_t. */
+    struct overlay_data_context_t *ctx = (struct overlay_data_context_t*)dev;
+    overlay_shared_data* data = 0;
+    if(ctx->sharedMemBase != MAP_FAILED) {
+        data = static_cast<overlay_shared_data*>(ctx->sharedMemBase);
+        if(0 == data){
+            LOGE("ctx->sharedMemBase is NULL");
+            return false;
+        }
+    }
+    else{
+        LOGE("ctx->sharedMemBase == MAP_FAILED");
+        return false;
+    }
+
+    bool noRot = true;
+#ifdef USE_MSM_ROTATOR
+    noRot = false;
+#else
+    noRot = true;
+#endif
+
+    unsigned int newState = data->state;
+
+    switch (ctx->state)
+    {
+        case OV_2D_VIDEO_ON_PANEL:
+            if(-1 == queueBuffer_OV_2D_VIDEO_ON_PANEL(ctx, data,
+                        newState,
+                        noRot))
+                return -1;
+            break;
+        case OV_3D_VIDEO_2D_PANEL:
+            if(-1 == queueBuffer_OV_3D_VIDEO_2D_PANEL(ctx, data,
+                        newState,
+                        noRot))
+                return -1;
+            break;
+        case OV_3D_VIDEO_3D_PANEL:
+            if(-1 == queueBuffer_OV_3D_VIDEO_3D_PANEL(ctx, data,
+                        newState,
+                        noRot))
+                return -1;
+            break;
+        case OV_2D_VIDEO_ON_TV:
+            if(-1 == queueBuffer_OV_2D_VIDEO_ON_TV(ctx, data,
+                        newState,
+                        noRot))
+                return -1;
+            break;
+        case OV_3D_VIDEO_2D_TV:
+            if(-1 == queueBuffer_OV_3D_VIDEO_2D_TV(ctx, data,
+                        newState,
+                        noRot))
+                return -1;
+            break;
+        case OV_3D_VIDEO_3D_TV:
+            if(-1 == queueBuffer_OV_3D_VIDEO_3D_TV(ctx, data,
+                        newState,
+                        noRot))
+                return -1;
+            break;
+        default:
+            LOGE("Unknown state in configPipes");
+            abort();
+    }
+    //update the context's state
+    ctx->state = newState;
+    return 0;
+}
+
+int overlay_queueBuffer(struct overlay_data_device_t *dev,
+        overlay_buffer_t buffer)
+{
+    struct overlay_data_context_t *ctx = (struct overlay_data_context_t*)dev;
+    private_overlay_module_t* m = reinterpret_cast<private_overlay_module_t*>(
+            dev->common.module);
+    Mutex::Autolock objLock(m->pobjMutex);
+
+    // Check if control channel is setup.
+    overlay_shared_data* data = NULL;
+    if(ctx->sharedMemBase != MAP_FAILED) {
+        data = static_cast<overlay_shared_data*>(ctx->sharedMemBase);
+        if(data == NULL)
+            return false;
+    }
+    else
+        return false;
+
+    if(false == data->isControlSetup) {
+        LOGE("Overlay Control Channel is not fully setup yet");
+        return -1;
+    }
+
+    // check any state-changing related events
+    if(-1 == overlay_queueBufferCheckStateChange(dev, buffer)){
+        return -1;
+    }
+    switch (ctx->state) {
+        case OV_2D_VIDEO_ON_PANEL:
+            if (ctx->setCrop) {
+                if(!ctx->pobjDataChannel[VG0_PIPE]->setCrop(ctx->cropRect.x, ctx->cropRect.y, ctx->cropRect.w, ctx->cropRect.h)) {
+                    LOGE("%s: failed for pipe 0", __func__);
+                }
+                ctx->setCrop = false;
+            }
+            if(!ctx->pobjDataChannel[VG0_PIPE]->queueBuffer((uint32_t) buffer)) {
+                LOGE("%s: failed for VG pipe 0", __func__);
+                return -1;
+            }
+            break;
+        case OV_3D_VIDEO_2D_PANEL:
+            if (ctx->setCrop) {
+                overlay_rect rect;
+                ctx->pobjDataChannel[VG0_PIPE]->getCropS3D(&ctx->cropRect, VG0_PIPE, ctx->format3D, &rect);
+                if(!ctx->pobjDataChannel[VG0_PIPE]->setCrop(rect.x, rect.y, rect.w, rect.h)) {
+                    LOGE("%s: failed for pipe 0", __func__);
+                }
+                ctx->setCrop = false;
+            }
+            if(!ctx->pobjDataChannel[VG0_PIPE]->queueBuffer((uint32_t) buffer)) {
+                LOGE("%s: failed for VG pipe 0", __func__);
+                return -1;
+            }
+            break;
+        case OV_3D_VIDEO_3D_PANEL:
+        case OV_2D_VIDEO_ON_TV:
+        case OV_3D_VIDEO_2D_TV:
+        case OV_3D_VIDEO_3D_TV:
+            for (int i=0; i<NUM_CHANNELS; i++) {
+                if(!ctx->pobjDataChannel[i]->queueBuffer((uint32_t) buffer)) {
+                    LOGE("%s: failed for VG pipe %d", __func__, i);
+                    return -1;
+                }
+            }
+            break;
+        default:
+            break;
+    }
+    return 0;
+}
+
+int overlay_setFd(struct overlay_data_device_t *dev, int fd)
+{
+    private_overlay_module_t* m = reinterpret_cast<private_overlay_module_t*>(
+            dev->common.module);
+    struct overlay_data_context_t* ctx = (struct overlay_data_context_t*)dev;
+    Mutex::Autolock objLock(m->pobjMutex);
+    ctx->srcFD = fd;
+    switch (ctx->state) {
+        case OV_2D_VIDEO_ON_PANEL:
+        case OV_3D_VIDEO_2D_PANEL:
+            if(!ctx->pobjDataChannel[VG0_PIPE]->setFd(fd)) {
+                LOGE("%s: failed for VG pipe 0", __func__);
+                return -1;
+            }
+            break;
+        case OV_3D_VIDEO_3D_PANEL:
+        case OV_2D_VIDEO_ON_TV:
+        case OV_3D_VIDEO_2D_TV:
+        case OV_3D_VIDEO_3D_TV:
+            for (int i=0; i<NUM_CHANNELS; i++) {
+                if(!ctx->pobjDataChannel[i]->setFd(fd)) {
+                    LOGE("%s: failed for  pipe %d", __func__, i);
+                    return -1;
+                }
+            }
+            break;
+        default:
+            break;
+    }
+    return 0;
+}
+
+static int overlay_setCrop(struct overlay_data_device_t *dev, uint32_t x,
+        uint32_t y, uint32_t w, uint32_t h)
+{
+    private_overlay_module_t* m = reinterpret_cast<private_overlay_module_t*>(
+            dev->common.module);
+    struct overlay_data_context_t* ctx = (struct overlay_data_context_t*)dev;
+    overlay_shared_data* data = static_cast<overlay_shared_data*>(ctx->sharedMemBase);
+    //Yield processor until control channel is fully set up i.e commit happens.
+    while(false == data->isControlSetup) {
+        sched_yield();
+    }
+    Mutex::Autolock objLock(m->pobjMutex);
+    overlay_rect rect;
+    ctx->cropRect.x = x;
+    ctx->cropRect.y = y;
+    ctx->cropRect.w = w;
+    ctx->cropRect.h = h;
+    switch (ctx->state) {
+        case OV_2D_VIDEO_ON_PANEL:
+        case OV_3D_VIDEO_2D_PANEL:
+            ctx->setCrop = true;
+            break;
+        case OV_2D_VIDEO_ON_TV:
+            for (int i=0; i<NUM_CHANNELS; i++) {
+                if(!ctx->pobjDataChannel[i]->setCrop(x, y, w, h)) {
+                    LOGE("%s: failed for pipe %d", __func__, i);
+                    return -1;
+                }
+            }
+            break;
+        case OV_3D_VIDEO_3D_PANEL:
+        case OV_3D_VIDEO_2D_TV:
+        case OV_3D_VIDEO_3D_TV:
+            for (int i=0; i<NUM_CHANNELS; i++) {
+                ctx->pobjDataChannel[i]->getCropS3D(&ctx->cropRect, i, ctx->format3D, &rect);
+                if(!ctx->pobjDataChannel[i]->setCrop(rect.x, rect.y, rect.w, rect.h)) {
+                    LOGE("%s: failed for pipe %d", __func__, i);
+                    return -1;
+                }
+            }
+            break;
+        default:
+            break;
+    }
+    return 0;
+}
+
+void *overlay_getBufferAddress(struct overlay_data_device_t *dev,
+        overlay_buffer_t buffer)
+{
+    /* overlay buffers are coming from client */
+    return( NULL );
+}
+
+int overlay_getBufferCount(struct overlay_data_device_t *dev)
+{
+    return 0;
+}
+
+
+static int overlay_data_close(struct hw_device_t *dev)
+{
+    struct overlay_data_context_t* ctx = (struct overlay_data_context_t*)dev;
+    if (ctx) {
+        /* free all resources associated with this device here
+         * in particular all pending overlay_buffer_t if needed.
+         *
+         * NOTE: overlay_handle_t passed in initialize() is NOT freed and
+         * its file descriptors are not closed (this is the responsibility
+         * of the caller).
+         */
+
+        if (ctx->pobjDataChannel[0]) {
+            ctx->pobjDataChannel[0]->closeDataChannel();
+            delete ctx->pobjDataChannel[0];
+            ctx->pobjDataChannel[0] = 0;
+        }
+
+        if (ctx->pobjDataChannel[1]) {
+            ctx->pobjDataChannel[1]->closeDataChannel();
+            delete ctx->pobjDataChannel[1];
+            ctx->pobjDataChannel[1] = 0;
+        }
+
+        if(ctx->sharedMemBase != MAP_FAILED) {
+            munmap(ctx->sharedMemBase, sizeof(overlay_shared_data));
+            ctx->sharedMemBase = MAP_FAILED;
+        }
+
+        free(ctx);
+    }
+    return 0;
+}
+
+/*****************************************************************************/
+
+static int overlay_device_open(const struct hw_module_t* module, const char* name,
+        struct hw_device_t** device)
+{
+    int status = -EINVAL;
+
+    private_overlay_module_t* m = reinterpret_cast<private_overlay_module_t*>
+        (const_cast<hw_module_t*>(module));
+    if (!m->pobjMutex)
+        m->pobjMutex = new Mutex();
+
+    if (!strcmp(name, OVERLAY_HARDWARE_CONTROL)) {
+        struct overlay_control_context_t *dev;
+        dev = (overlay_control_context_t*)malloc(sizeof(*dev));
+
+        if (!dev)
+            return status;
+
+        /* initialize our state here */
+        memset(dev, 0, sizeof(*dev));
+
+        /* initialize the procs */
+        dev->device.common.tag = HARDWARE_DEVICE_TAG;
+        dev->device.common.version = 0;
+        dev->device.common.module = const_cast<hw_module_t*>(module);
+        dev->device.common.close = overlay_control_close;
+
+        dev->device.get = overlay_get;
+        dev->device.createOverlay = overlay_createOverlay;
+        dev->device.destroyOverlay = overlay_destroyOverlay;
+        dev->device.setPosition = overlay_setPosition;
+        dev->device.getPosition = overlay_getPosition;
+        dev->device.setParameter = overlay_setParameter;
+        dev->device.commit = overlay_commit;
+
+        *device = &dev->device.common;
+        status = 0;
+    } else if (!strcmp(name, OVERLAY_HARDWARE_DATA)) {
+        struct overlay_data_context_t *dev;
+        dev = (overlay_data_context_t*)malloc(sizeof(*dev));
+
+        if (!dev)
+            return status;
+
+        /* initialize our state here */
+        memset(dev, 0, sizeof(*dev));
+
+        /* initialize the procs */
+        dev->device.common.tag = HARDWARE_DEVICE_TAG;
+        dev->device.common.version = 0;
+        dev->device.common.module = const_cast<hw_module_t*>(module);
+        dev->device.common.close = overlay_data_close;
+
+        dev->device.initialize = overlay_initialize;
+        dev->device.setCrop = overlay_setCrop;
+        dev->device.dequeueBuffer = overlay_dequeueBuffer;
+        dev->device.queueBuffer = overlay_queueBuffer;
+        dev->device.setFd = overlay_setFd;
+        dev->device.getBufferAddress = overlay_getBufferAddress;
+        dev->device.getBufferCount = overlay_getBufferCount;
+
+        *device = &dev->device.common;
+        status = 0;
+    }
+    return status;
+}
+
+#include "overlayState.cpp"
diff --git a/liboverlay/overlayLib.cpp b/liboverlay/overlayLib.cpp
new file mode 100644
index 0000000..f0db551
--- /dev/null
+++ b/liboverlay/overlayLib.cpp
@@ -0,0 +1,1799 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "overlayLib.h"
+#include "gralloc_priv.h"
+
+#define INTERLACE_MASK 0x80
+#define DEBUG_OVERLAY true
+/* Helper functions */
+static inline size_t ALIGN(size_t x, size_t align) {
+    return (x + align-1) & ~(align-1);
+}
+
+using namespace overlay;
+using android::sp;
+using gralloc::IMemAlloc;
+using gralloc::IonController;
+using gralloc::alloc_data;
+
+#ifdef HDMI_AS_PRIMARY
+bool Overlay::sHDMIAsPrimary = true;
+#else
+bool Overlay::sHDMIAsPrimary = false;
+#endif
+
+int overlay::get_mdp_format(int format) {
+    switch (format) {
+    case HAL_PIXEL_FORMAT_RGBA_8888 :
+        return MDP_RGBA_8888;
+    case HAL_PIXEL_FORMAT_BGRA_8888:
+        return MDP_BGRA_8888;
+    case HAL_PIXEL_FORMAT_RGB_565:
+        return MDP_RGB_565;
+    case HAL_PIXEL_FORMAT_RGBX_8888:
+        return MDP_RGBX_8888;
+    case HAL_PIXEL_FORMAT_YCbCr_422_SP:
+        return MDP_Y_CBCR_H2V1;
+    case HAL_PIXEL_FORMAT_YCbCr_420_SP:
+        return MDP_Y_CRCB_H2V2;
+    case HAL_PIXEL_FORMAT_YCrCb_420_SP:
+        return MDP_Y_CBCR_H2V2;
+    case HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED:
+        return MDP_Y_CRCB_H2V2_TILE;
+    case HAL_PIXEL_FORMAT_YV12:
+        return MDP_Y_CR_CB_GH2V2;
+    default:
+        LOGE("%s: unknown color format [0x%x]", __FUNCTION__, format);
+        return -1;
+    }
+    return -1;
+}
+
+int overlay::get_mdp_orientation(int value) {
+    switch(value) {
+        case 0: return 0;
+        case HAL_TRANSFORM_FLIP_V:  return MDP_FLIP_UD;
+        case HAL_TRANSFORM_FLIP_H:  return MDP_FLIP_LR;
+        case HAL_TRANSFORM_ROT_90:  return MDP_ROT_90;
+        case HAL_TRANSFORM_ROT_90|HAL_TRANSFORM_FLIP_V:
+                                    return MDP_ROT_90|MDP_FLIP_LR;
+        case HAL_TRANSFORM_ROT_90|HAL_TRANSFORM_FLIP_H:
+                                    return MDP_ROT_90|MDP_FLIP_UD;
+        case HAL_TRANSFORM_ROT_180: return MDP_ROT_180;
+        case HAL_TRANSFORM_ROT_270: return MDP_ROT_270;
+        default:
+            LOGE("%s: invalid rotation value (value = 0x%x",
+                  __FUNCTION__, value);
+            return -1;
+    }
+    return -1;
+}
+
+// Rotator - input to output mapping
+int overlay::get_rot_output_format(int format) {
+    switch (format) {
+    case MDP_Y_CRCB_H2V2_TILE:
+        return MDP_Y_CRCB_H2V2;
+    case MDP_Y_CB_CR_H2V2:
+    case MDP_Y_CR_CB_GH2V2:
+        return MDP_Y_CBCR_H2V2;
+    default:
+        return format;
+    }
+    return -1;
+}
+
+// This function normalizes the crop values to be all even
+void overlay::normalize_crop(uint32_t& xy, uint32_t& wh) {
+
+    if (xy & 0x0001) {
+        // x or y is odd, increment it's value
+        xy += 1;
+        // Since we've incremented x(y), we need to decrement
+        // w(h) accordingly
+        if (wh & 0x0001) {
+            // w or h is odd, decrement it by 1, to make it even
+            EVEN_OUT(wh);
+        } else {
+            // w(h) is already even, hence we decrement by 2
+            wh -=2;
+        }
+    } else {
+        EVEN_OUT(wh);
+    }
+}
+
+#define LOG_TAG "OverlayLIB"
+static void reportError(const char* message) {
+    LOGE( "%s", message);
+}
+
+void overlay::dump(mdp_overlay& mOVInfo) {
+    if (!DEBUG_OVERLAY)
+        return;
+    LOGE("mOVInfo:");
+    LOGE("src: width %d height %d format %s user_data[0] %d", mOVInfo.src.width,
+        mOVInfo.src.height, getFormatString(mOVInfo.src.format),
+        mOVInfo.user_data[0]);
+    LOGE("src_rect: x %d y %d w %d h %d", mOVInfo.src_rect.x,
+        mOVInfo.src_rect.y, mOVInfo.src_rect.w, mOVInfo.src_rect.h);
+    LOGE("dst_rect: x %d y %d w %d h %d", mOVInfo.dst_rect.x,
+        mOVInfo.dst_rect.y, mOVInfo.dst_rect.w, mOVInfo.dst_rect.h);
+    LOGE("z_order %d is_fg %d alpha %d transp_mask %d flags %x id %d",
+        mOVInfo.z_order, mOVInfo.is_fg, mOVInfo.alpha, mOVInfo.transp_mask,
+        mOVInfo.flags, mOVInfo.id);
+}
+
+void overlay::dump(msm_rotator_img_info& mRotInfo) {
+    if (!DEBUG_OVERLAY)
+        return;
+    LOGE("mRotInfo:");
+    LOGE("session_id %d dst_x %d dst_y %d rotations %d enable %d",
+        mRotInfo.session_id, mRotInfo.dst_x, mRotInfo.dst_y,
+        mRotInfo.rotations, mRotInfo.enable);
+    LOGE("src: width %d height %d format %s", mRotInfo.src.width,
+        mRotInfo.src.height, getFormatString(mRotInfo.src.format));
+    LOGE("dst: width %d height %d format %s", mRotInfo.dst.width,
+        mRotInfo.dst.height, getFormatString(mRotInfo.src.format));
+    LOGE("src_rect: x %d y %d w %d h %d", mRotInfo.src_rect.x,
+        mRotInfo.src_rect.y, mRotInfo.src_rect.w, mRotInfo.src_rect.h);
+}
+
+const char* overlay::getFormatString(int format){
+    static const char* formats[] = {
+             "MDP_RGB_565",
+             "MDP_XRGB_8888",
+             "MDP_Y_CBCR_H2V2",
+             "MDP_ARGB_8888",
+             "MDP_RGB_888",
+             "MDP_Y_CRCB_H2V2",
+             "MDP_YCRYCB_H2V1",
+             "MDP_Y_CRCB_H2V1",
+             "MDP_Y_CBCR_H2V1",
+             "MDP_RGBA_8888",
+             "MDP_BGRA_8888",
+             "MDP_RGBX_8888",
+             "MDP_Y_CRCB_H2V2_TILE",
+             "MDP_Y_CBCR_H2V2_TILE",
+             "MDP_Y_CR_CB_H2V2",
+             "MDP_Y_CR_CB_GH2V2",
+             "MDP_Y_CB_CR_H2V2",
+             "MDP_Y_CRCB_H1V1",
+             "MDP_Y_CBCR_H1V1",
+             "MDP_IMGTYPE_LIMIT",
+             "MDP_BGR_565",
+             "MDP_FB_FORMAT",
+             "MDP_IMGTYPE_LIMIT2"
+        };
+    return formats[format];
+}
+
+bool overlay::isHDMIConnected () {
+    char value[PROPERTY_VALUE_MAX];
+    property_get("hw.hdmiON", value, "0");
+    int isHDMI = atoi(value);
+    return isHDMI ? true : false;
+}
+
+bool overlay::is3DTV() {
+    char is3DTV = '0';
+    FILE *fp = fopen(EDID_3D_INFO_FILE, "r");
+    if (fp) {
+        fread(&is3DTV, 1, 1, fp);
+        fclose(fp);
+    }
+    LOGI("3DTV EDID flag: %c", is3DTV);
+    return (is3DTV == '0') ? false : true;
+}
+
+bool overlay::isPanel3D() {
+    int fd = open("/dev/graphics/fb0", O_RDWR, 0);
+    if (fd < 0) {
+        reportError("Can't open framebuffer 0");
+        return false;
+    }
+    fb_fix_screeninfo finfo;
+    if (ioctl(fd, FBIOGET_FSCREENINFO, &finfo) == -1) {
+        reportError("FBIOGET_FSCREENINFO on fb0 failed");
+        close(fd);
+        fd = -1;
+        return false;
+    }
+    close(fd);
+    return (FB_TYPE_3D_PANEL == finfo.type) ? true : false;
+}
+
+bool overlay::usePanel3D() {
+    if (Overlay::sHDMIAsPrimary)
+        return is3DTV();
+
+    if(!isPanel3D())
+        return false;
+    char value[PROPERTY_VALUE_MAX];
+    property_get("persist.user.panel3D", value, "0");
+    int usePanel3D = atoi(value);
+    return usePanel3D ? true : false;
+}
+
+bool overlay::send3DInfoPacket (unsigned int format3D) {
+    FILE *fp = fopen(FORMAT_3D_FILE, "wb");
+    if (fp) {
+        fprintf(fp, "%d", format3D);
+        fclose(fp);
+        fp = NULL;
+        return true;
+    }
+    LOGE("%s:no sysfs entry for setting 3d mode!", __FUNCTION__);
+    return false;
+}
+
+bool overlay::enableBarrier (unsigned int orientation) {
+    FILE *fp = fopen(BARRIER_FILE, "wb");
+    if (fp) {
+        fprintf(fp, "%d", orientation);
+        fclose(fp);
+        fp = NULL;
+        return true;
+    }
+    LOGE("%s:no sysfs entry for enabling barriers on 3D panel!", __FUNCTION__);
+    return false;
+}
+
+int overlay::getColorFormat(int format)
+{
+    return (format == HAL_PIXEL_FORMAT_YV12) ?
+            format : COLOR_FORMAT(format);
+}
+
+unsigned int overlay::getOverlayConfig (unsigned int format3D, bool poll,
+        bool isHDMI) {
+    bool isTV3D = false;
+    unsigned int curState = 0;
+    if (poll)
+        isHDMI = isHDMIConnected();
+    if (isHDMI) {
+        LOGD("%s: HDMI connected... checking the TV type", __FUNCTION__);
+        if (format3D) {
+            if (is3DTV())
+                curState = OV_3D_VIDEO_3D_TV;
+            else
+                curState = OV_3D_VIDEO_2D_TV;
+        } else
+            curState = OV_2D_VIDEO_ON_TV;
+    } else {
+        LOGD("%s: HDMI not connected...", __FUNCTION__);
+        if(format3D) {
+            if (usePanel3D())
+                curState = OV_3D_VIDEO_3D_PANEL;
+            else
+                curState = OV_3D_VIDEO_2D_PANEL;
+        }
+        else
+            curState = OV_2D_VIDEO_ON_PANEL;
+    }
+    return curState;
+}
+
+Overlay::Overlay() : mChannelUP(false), mHDMIConnected(false),
+                     mS3DFormat(0), mCroppedSrcWidth(0),
+                     mCroppedSrcHeight(0), mState(-1) {
+    mOVBufferInfo.width = mOVBufferInfo.height = 0;
+    mOVBufferInfo.format = mOVBufferInfo.size = 0;
+}
+
+Overlay::~Overlay() {
+    closeChannel();
+}
+
+int Overlay::getFBWidth(int channel) const {
+    return objOvCtrlChannel[channel].getFBWidth();
+}
+
+int Overlay::getFBHeight(int channel) const {
+    return objOvCtrlChannel[channel].getFBHeight();
+}
+
+bool Overlay::startChannel(const overlay_buffer_info& info, int fbnum,
+                              bool norot, bool uichannel,
+                              unsigned int format3D, int channel,
+                              bool ignoreFB, int num_buffers) {
+    int zorder = 0;
+    int format = getColorFormat(info.format);
+    mCroppedSrcWidth = info.width;
+    mCroppedSrcHeight = info.height;
+    if (format3D)
+        zorder = channel;
+    if (mState == -1)
+        mState = OV_UI_MIRROR_TV;
+
+    mChannelUP = objOvCtrlChannel[channel].startControlChannel(info.width,
+                                                       info.height, format, fbnum,
+                                                       norot, uichannel,
+                                                       format3D, zorder, ignoreFB);
+    if (!mChannelUP) {
+        LOGE("startChannel for fb%d failed", fbnum);
+        return mChannelUP;
+    }
+    objOvCtrlChannel[channel].setSize(info.size);
+    return objOvDataChannel[channel].startDataChannel(objOvCtrlChannel[channel], fbnum,
+                                            norot, uichannel, num_buffers);
+}
+
+bool Overlay::closeChannel() {
+
+    if (!mChannelUP)
+        return true;
+
+    if(mS3DFormat) {
+        if (mHDMIConnected)
+            overlay::send3DInfoPacket(0);
+        else if (mState == OV_3D_VIDEO_3D_PANEL) {
+            if (sHDMIAsPrimary)
+                overlay::send3DInfoPacket(0);
+            else
+                enableBarrier(0);
+        }
+    }
+    for (int i = 0; i < NUM_CHANNELS; i++) {
+        objOvCtrlChannel[i].closeControlChannel();
+        objOvDataChannel[i].closeDataChannel();
+    }
+    mChannelUP = false;
+    mS3DFormat = 0;
+    mOVBufferInfo.width = 0;
+    mOVBufferInfo.height = 0;
+    mOVBufferInfo.format = 0;
+    mOVBufferInfo.size = 0;
+    mState = -1;
+    return true;
+}
+
+bool Overlay::getPosition(int& x, int& y, uint32_t& w, uint32_t& h, int channel) {
+    return objOvCtrlChannel[channel].getPosition(x, y, w, h);
+}
+
+bool Overlay::getOrientation(int& orientation, int channel) const {
+    return objOvCtrlChannel[channel].getOrientation(orientation);
+}
+
+bool Overlay::setPosition(int x, int y, uint32_t w, uint32_t h) {
+    bool ret = false;
+    overlay_rect rect;
+    switch (mState) {
+        case OV_UI_MIRROR_TV:
+        case OV_2D_VIDEO_ON_PANEL:
+        case OV_3D_VIDEO_2D_PANEL:
+            return setChannelPosition(x, y, w, h, VG0_PIPE);
+            break;
+        case OV_2D_VIDEO_ON_TV:
+            objOvCtrlChannel[VG1_PIPE].getAspectRatioPosition(mCroppedSrcWidth,
+                            mCroppedSrcHeight, &rect);
+            setChannelPosition(rect.x, rect.y, rect.w, rect.h, VG1_PIPE);
+            return setChannelPosition(x, y, w, h, VG0_PIPE);
+            break;
+        case OV_3D_VIDEO_3D_PANEL:
+            for (int i = 0; i < NUM_CHANNELS; i++) {
+                if (sHDMIAsPrimary)
+                    objOvCtrlChannel[i].getPositionS3D(i, mS3DFormat, &rect);
+                else {
+                    if (!objOvCtrlChannel[i].useVirtualFB()) {
+                        LOGE("%s: failed virtual fb for channel %d", __FUNCTION__, i);
+                        return false;
+                    }
+                    objOvCtrlChannel[i].getPositionS3D(i, 0x1, &rect);
+                }
+                if(!setChannelPosition(rect.x, rect.y, rect.w, rect.h, i)) {
+                    LOGE("%s: failed for channel %d", __FUNCTION__, i);
+                    return false;
+                }
+            }
+            break;
+        case OV_3D_VIDEO_2D_TV:
+        case OV_3D_VIDEO_3D_TV:
+            for (int i = 0; i < NUM_CHANNELS; i++) {
+                ret = objOvCtrlChannel[i].getPositionS3D(i, mS3DFormat, &rect);
+                if (!ret)
+                    ret = setChannelPosition(x, y, w, h, i);
+                else
+                    ret = setChannelPosition(rect.x, rect.y, rect.w, rect.h, i);
+                if (!ret) {
+                    LOGE("%s: failed for channel %d", __FUNCTION__, i);
+                    return ret;
+                }
+            }
+            break;
+        default:
+            LOGE("%s:Unknown state %d", __FUNCTION__, mState);
+            break;
+    }
+    return true;
+}
+
+bool Overlay::setChannelPosition(int x, int y, uint32_t w, uint32_t h, int channel) {
+    return objOvCtrlChannel[channel].setPosition(x, y, w, h);
+}
+
+bool Overlay::updateOverlaySource(const overlay_buffer_info& info, int orientation,
+                                  bool waitForVsync) {
+    bool ret = false;
+    int currentFlags = 0;
+    if (objOvCtrlChannel[0].isChannelUP()) {
+        currentFlags = objOvCtrlChannel[0].getOverlayFlags();
+    }
+
+    bool needUpdateFlags = false;
+    if (waitForVsync) {
+        if (currentFlags & MDP_OV_PLAY_NOWAIT) {
+            needUpdateFlags = true;
+        }
+    } else {
+        if (!(currentFlags & MDP_OV_PLAY_NOWAIT)) {
+            needUpdateFlags = true;
+        }
+    }
+
+    bool geometryChanged = true;
+    if (info.width == mOVBufferInfo.width &&
+        info.height == mOVBufferInfo.height &&
+        info.format == mOVBufferInfo.format) {
+        geometryChanged = false;
+    }
+
+    if (sHDMIAsPrimary)
+        needUpdateFlags = false;
+
+    if ((false == needUpdateFlags) && (false == geometryChanged)) {
+        objOvDataChannel[0].updateDataChannel(0, 0);
+        return true;
+    }
+
+    // Disable rotation for the HDMI channels
+    int orientHdmi = 0;
+    int orientPrimary = sHDMIAsPrimary ? 0 : orientation;
+    int orient[2] = {orientPrimary, orientHdmi};
+    // enable waitForVsync on HDMI
+    bool waitForHDMI = true;
+    bool waitForPrimary = sHDMIAsPrimary ? true : waitForVsync;
+    bool waitCond[2] = {waitForPrimary, waitForHDMI};
+
+    switch(mState) {
+        case OV_3D_VIDEO_3D_PANEL:
+            orient[1] = sHDMIAsPrimary ? 0 : orientation;
+            break;
+        case OV_3D_VIDEO_3D_TV:
+            orient[0] = 0;
+            break;
+        default:
+            break;
+    }
+
+    int numChannelsToUpdate = NUM_CHANNELS;
+    if (!geometryChanged) {
+        // Only update the primary channel - we only need to update the
+        // wait/no-wait flags
+        if (objOvCtrlChannel[0].isChannelUP()) {
+            return objOvCtrlChannel[0].updateWaitForVsyncFlags(waitForVsync);
+        }
+    }
+
+    // Set the overlay source info
+    for (int i = 0; i < NUM_CHANNELS; i++) {
+        if (objOvCtrlChannel[i].isChannelUP()) {
+            ret = objOvCtrlChannel[i].updateOverlaySource(info, orient[i], waitCond[i]);
+            if (!ret) {
+                LOGE("objOvCtrlChannel[%d].updateOverlaySource failed", i);
+                return false;
+            }
+            objOvCtrlChannel[i].setSize(info.size);
+            int updateDataChannel = orientation ? 1:0;
+            ret = objOvDataChannel[i].updateDataChannel(updateDataChannel, info.size);
+        }
+    }
+    if (ret) {
+        mOVBufferInfo = info;
+    } else
+        LOGE("update failed");
+    return ret;
+}
+
+int Overlay::getS3DFormat(int format) {
+    // The S3D is part of the HAL_PIXEL_FORMAT_YV12 value. Add
+    // an explicit check for the format
+    if (format == HAL_PIXEL_FORMAT_YV12) {
+        return 0;
+    }
+    int format3D = FORMAT_3D(format);
+    int fIn3D = FORMAT_3D_INPUT(format3D); // MSB 2 bytes are input format
+    int fOut3D = FORMAT_3D_OUTPUT(format3D); // LSB 2 bytes are output format
+    format3D = fIn3D | fOut3D;
+    if (!fIn3D) {
+        format3D |= fOut3D << SHIFT_3D; //Set the input format
+    }
+    if (!fOut3D) {
+        format3D |= fIn3D >> SHIFT_3D; //Set the output format
+    }
+    return format3D;
+}
+
+bool Overlay::setSource(const overlay_buffer_info& info, int orientation,
+                        bool hdmiConnected, bool waitForVsync, int num_buffers) {
+    // Separate the color format from the 3D format.
+    // If there is 3D content; the effective format passed by the client is:
+    // effectiveFormat = 3D_IN | 3D_OUT | ColorFormat
+    int newState = mState;
+    bool stateChange = false, ret = false;
+    unsigned int format3D = getS3DFormat(info.format);
+    int colorFormat = getColorFormat(info.format);
+    if (-1 == mState) {
+        newState = getOverlayConfig (format3D, false, hdmiConnected);
+        stateChange = (mState == newState) ? false : true;
+    }
+
+    if (stateChange) {
+        closeChannel();
+        mHDMIConnected = hdmiConnected;
+        mState = newState;
+        mS3DFormat = format3D;
+        if (mState == OV_3D_VIDEO_2D_PANEL || mState == OV_3D_VIDEO_2D_TV) {
+            LOGI("3D content on 2D display: set the output format as monoscopic");
+            mS3DFormat = FORMAT_3D_INPUT(format3D) | HAL_3D_OUT_MONOSCOPIC_MASK;
+        }
+        // We always enable the rotator for the primary.
+        bool noRot = false;
+        bool uiChannel = false;
+        switch(mState) {
+            case OV_2D_VIDEO_ON_PANEL:
+            case OV_3D_VIDEO_2D_PANEL:
+                return startChannel(info, FRAMEBUFFER_0, noRot, false,
+                        mS3DFormat, VG0_PIPE, waitForVsync, num_buffers);
+                break;
+            case OV_3D_VIDEO_3D_PANEL:
+                if (sHDMIAsPrimary) {
+                    noRot = true;
+                    waitForVsync = true;
+                    send3DInfoPacket(mS3DFormat & OUTPUT_MASK_3D);
+                }
+                for (int i=0; i<NUM_CHANNELS; i++) {
+                    if(!startChannel(info, FRAMEBUFFER_0, noRot, uiChannel,
+                                mS3DFormat, i, waitForVsync, num_buffers)) {
+                        LOGE("%s:failed to open channel %d", __FUNCTION__, i);
+                        return false;
+                    }
+                }
+                break;
+            case OV_2D_VIDEO_ON_TV:
+            case OV_3D_VIDEO_2D_TV:
+                for (int i=0; i<NUM_CHANNELS; i++) {
+                    if (FRAMEBUFFER_1 == i) {
+                        // Disable rotation for HDMI
+                        noRot = true;
+                        waitForVsync = true;
+                    }
+                    if(!startChannel(info, i, noRot, false, mS3DFormat,
+                                i, waitForVsync, num_buffers)) {
+                        LOGE("%s:failed to open channel %d", __FUNCTION__, i);
+                        return false;
+                    }
+                }
+                overlay_rect rect;
+                objOvCtrlChannel[VG1_PIPE].getAspectRatioPosition(info.width, info.height, &rect);
+                return setChannelPosition(rect.x, rect.y, rect.w, rect.h, VG1_PIPE);
+                break;
+            case OV_3D_VIDEO_3D_TV:
+                for (int i=0; i<NUM_CHANNELS; i++) {
+                    if(!startChannel(info, FRAMEBUFFER_1, true, false,
+                                mS3DFormat, i, waitForVsync, num_buffers)) {
+                        LOGE("%s:failed to open channel %d", __FUNCTION__, i);
+                        return false;
+                    }
+                    send3DInfoPacket(mS3DFormat & OUTPUT_MASK_3D);
+                }
+                break;
+            default:
+                LOGE("%s:Unknown state %d", __FUNCTION__, mState);
+                break;
+        }
+    } else {
+        ret = updateOverlaySource(info, orientation, waitForVsync);
+    }
+    return true;
+}
+
+bool Overlay::setCrop(uint32_t x, uint32_t y, uint32_t w, uint32_t h) {
+    if (!mChannelUP) {
+        LOGE("%s: channel not set", __FUNCTION__);
+        return false;
+    }
+    overlay_rect rect, inRect;
+    inRect.x = x; inRect.y = y; inRect.w = w; inRect.h = h;
+    mCroppedSrcWidth = w;
+    mCroppedSrcHeight = h;
+
+    switch (mState) {
+        case OV_UI_MIRROR_TV:
+        case OV_2D_VIDEO_ON_PANEL:
+            return setChannelCrop(x, y, w, h, VG0_PIPE);
+            break;
+        case OV_3D_VIDEO_2D_PANEL:
+            objOvDataChannel[VG0_PIPE].getCropS3D(&inRect, VG0_PIPE, mS3DFormat, &rect);
+            return setChannelCrop(rect.x, rect.y, rect.w, rect.h, VG0_PIPE);
+            break;
+        case OV_2D_VIDEO_ON_TV:
+            for (int i=0; i<NUM_CHANNELS; i++) {
+                if(!setChannelCrop(x, y, w, h, i)) {
+                    LOGE("%s: failed for pipe %d", __FUNCTION__, i);
+                    return false;
+                }
+            }
+            break;
+        case OV_3D_VIDEO_3D_PANEL:
+        case OV_3D_VIDEO_2D_TV:
+        case OV_3D_VIDEO_3D_TV:
+            for (int i=0; i<NUM_CHANNELS; i++) {
+                objOvDataChannel[i].getCropS3D(&inRect, i, mS3DFormat, &rect);
+                if(!setChannelCrop(rect.x, rect.y, rect.w, rect.h, i)) {
+                    LOGE("%s: failed for pipe %d", __FUNCTION__, i);
+                    return false;
+                }
+            }
+            break;
+        default:
+            LOGE("%s:Unknown state %d", __FUNCTION__, mState);
+            break;
+    }
+    return true;
+}
+
+bool Overlay::setChannelCrop(uint32_t x, uint32_t y, uint32_t w, uint32_t h, int channel) {
+    return objOvDataChannel[channel].setCrop(x, y, w, h);
+}
+
+bool Overlay::setParameter(int param, int value) {
+    int currentOrientation = -1;
+    getOrientation(currentOrientation);
+
+    switch (mState) {
+        case OV_UI_MIRROR_TV:
+        case OV_2D_VIDEO_ON_PANEL:
+        case OV_3D_VIDEO_2D_PANEL:
+            return objOvCtrlChannel[VG0_PIPE].setParameter(param, value);
+            break;
+        case OV_2D_VIDEO_ON_TV:
+        case OV_3D_VIDEO_2D_TV:
+        case OV_3D_VIDEO_3D_TV:
+            for (int i=0; i<NUM_CHANNELS; i++) {
+                if(!objOvCtrlChannel[i].setParameter(param, value)) {
+                    LOGE("%s:failed for channel %d", __FUNCTION__, i);
+                    return false;
+                }
+            }
+            break;
+        case OV_3D_VIDEO_3D_PANEL:
+            if (!sHDMIAsPrimary && param == OVERLAY_TRANSFORM) {
+                int barrier = 0;
+                switch (value) {
+                    case HAL_TRANSFORM_ROT_90:
+                    case HAL_TRANSFORM_ROT_270:
+                        barrier = BARRIER_LANDSCAPE;
+                        break;
+                    default:
+                        barrier = BARRIER_PORTRAIT;
+                        break;
+                }
+                if(!enableBarrier(barrier))
+                    LOGE("%s:failed to enable barriers for 3D video", __FUNCTION__);
+            }
+            for (int i=0; i<NUM_CHANNELS; i++) {
+                if(!objOvCtrlChannel[i].setParameter(param, value)) {
+                    LOGE("%s:failed for channel %d", __FUNCTION__, i);
+                    return false;
+               }
+            }
+            break;
+        default:
+            LOGE("%s:Unknown state %d", __FUNCTION__, mState);
+            break;
+    }
+    return true;
+}
+
+bool Overlay::setOrientation(int value, int channel) {
+    return objOvCtrlChannel[channel].setParameter(OVERLAY_TRANSFORM, value);
+}
+
+bool Overlay::setFd(int fd, int channel) {
+    return objOvDataChannel[channel].setFd(fd);
+}
+
+bool Overlay::queueBuffer(uint32_t offset, int channel) {
+    return objOvDataChannel[channel].queueBuffer(offset);
+}
+
+bool Overlay::queueBuffer(buffer_handle_t buffer) {
+    private_handle_t const* hnd = reinterpret_cast
+                                   <private_handle_t const*>(buffer);
+    if (!hnd) {
+        LOGE("Overlay::queueBuffer invalid handle");
+        return false;
+    }
+    const size_t offset = hnd->offset;
+    const int fd = hnd->fd;
+    switch (mState) {
+        case OV_UI_MIRROR_TV:
+        case OV_2D_VIDEO_ON_PANEL:
+        case OV_3D_VIDEO_2D_PANEL:
+            if(!queueBuffer(fd, offset, VG0_PIPE)) {
+                LOGE("%s:failed for channel 0", __FUNCTION__);
+                return false;
+            }
+            break;
+        case OV_2D_VIDEO_ON_TV:
+        case OV_3D_VIDEO_3D_PANEL:
+        case OV_3D_VIDEO_2D_TV:
+        case OV_3D_VIDEO_3D_TV:
+            for (int i=0; i<NUM_CHANNELS; i++) {
+                if(!queueBuffer(fd, offset, i)) {
+                    LOGE("%s:failed for channel %d", __FUNCTION__, i);
+                    return false;
+                }
+            }
+            break;
+        default:
+            LOGE("%s:Unknown state %d", __FUNCTION__, mState);
+            break;
+    }
+    return true;
+}
+
+bool Overlay::queueBuffer(int fd, uint32_t offset, int channel) {
+    bool ret = false;
+    ret = setFd(fd, channel);
+    if(!ret) {
+        LOGE("Overlay::queueBuffer channel %d setFd failed", channel);
+        return false;
+    }
+    ret = queueBuffer(offset, channel);
+    if(!ret) {
+        LOGE("Overlay::queueBuffer channel %d queueBuffer failed", channel);
+        return false;
+    }
+    return ret;
+}
+
+OverlayControlChannel::OverlayControlChannel() : mNoRot(false), mFD(-1), mRotFD(-1),
+                                                 mFormat3D(0), mIsChannelUpdated(true) {
+    memset(&mOVInfo, 0, sizeof(mOVInfo));
+    memset(&m3DOVInfo, 0, sizeof(m3DOVInfo));
+    memset(&mRotInfo, 0, sizeof(mRotInfo));
+}
+
+
+OverlayControlChannel::~OverlayControlChannel() {
+    closeControlChannel();
+}
+
+bool OverlayControlChannel::getAspectRatioPosition(int w, int h, overlay_rect *rect)
+{
+    int width = w, height = h, x, y;
+    int fbWidth  = getFBWidth();
+    int fbHeight = getFBHeight();
+    // width and height for YUV TILE format
+    int tempWidth = w, tempHeight = h;
+    /* Calculate the width and height if it is YUV TILE format*/
+    if(getFormat() == HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED) {
+        tempWidth = w - ( (((w-1)/64 +1)*64) - w);
+        tempHeight = h - ((((h-1)/32 +1)*32) - h);
+    }
+    if (width * fbHeight > fbWidth * height) {
+        height = fbWidth * height / width;
+        EVEN_OUT(height);
+        width = fbWidth;
+    } else if (width * fbHeight < fbWidth * height) {
+        width = fbHeight * width / height;
+        EVEN_OUT(width);
+        height = fbHeight;
+    } else {
+        width = fbWidth;
+        height = fbHeight;
+    }
+    /* Scaling of upto a max of 8 times supported */
+    if(width >(tempWidth * HW_OVERLAY_MAGNIFICATION_LIMIT)){
+        width = HW_OVERLAY_MAGNIFICATION_LIMIT * tempWidth;
+    }
+    if(height >(tempHeight*HW_OVERLAY_MAGNIFICATION_LIMIT)) {
+        height = HW_OVERLAY_MAGNIFICATION_LIMIT * tempHeight;
+    }
+    if (width > fbWidth) width = fbWidth;
+    if (height > fbHeight) height = fbHeight;
+    x = (fbWidth - width) / 2;
+    y = (fbHeight - height) / 2;
+    rect->x = x;
+    rect->y = y;
+    rect->w = width;
+    rect->h = height;
+    return true;
+}
+
+bool OverlayControlChannel::getPositionS3D(int channel, int format, overlay_rect *rect) {
+    int wDisp = getFBWidth();
+    int hDisp = getFBHeight();
+    switch (format & OUTPUT_MASK_3D) {
+    case HAL_3D_OUT_SIDE_BY_SIDE_MASK:
+        if (channel == VG0_PIPE) {
+            rect->x = 0;
+            rect->y = 0;
+            rect->w = wDisp/2;
+            rect->h = hDisp;
+        } else {
+            rect->x = wDisp/2;
+            rect->y = 0;
+            rect->w = wDisp/2;
+            rect->h = hDisp;
+        }
+        break;
+    case HAL_3D_OUT_TOP_BOTTOM_MASK:
+        if (channel == VG0_PIPE) {
+            rect->x = 0;
+            rect->y = 0;
+            rect->w = wDisp;
+            rect->h = hDisp/2;
+        } else {
+            rect->x = 0;
+            rect->y = hDisp/2;
+            rect->w = wDisp;
+            rect->h = hDisp/2;
+        }
+        break;
+    case HAL_3D_OUT_MONOSCOPIC_MASK:
+        if (channel == VG1_PIPE) {
+            rect->x = 0;
+            rect->y = 0;
+            rect->w = wDisp;
+            rect->h = hDisp;
+        }
+        else
+            return false;
+        break;
+    case HAL_3D_OUT_INTERLEAVE_MASK:
+        break;
+    default:
+        reportError("Unsupported 3D output format");
+        break;
+    }
+    return true;
+}
+
+bool OverlayControlChannel::openDevices(int fbnum) {
+    if (fbnum < 0)
+        return false;
+
+    char const * const device_template =
+                       "/dev/graphics/fb%u";
+    char dev_name[64];
+    snprintf(dev_name, 64, device_template, fbnum);
+
+    mFD = open(dev_name, O_RDWR, 0);
+    if (mFD < 0) {
+        reportError("Cant open framebuffer ");
+        return false;
+    }
+
+    fb_fix_screeninfo finfo;
+    if (ioctl(mFD, FBIOGET_FSCREENINFO, &finfo) == -1) {
+        reportError("FBIOGET_FSCREENINFO on fb1 failed");
+        close(mFD);
+        mFD = -1;
+        return false;
+    }
+
+    fb_var_screeninfo vinfo;
+    if (ioctl(mFD, FBIOGET_VSCREENINFO, &vinfo) == -1) {
+        reportError("FBIOGET_VSCREENINFO on fb1 failed");
+        close(mFD);
+        mFD = -1;
+        return false;
+    }
+    mFBWidth = vinfo.xres;
+    mFBHeight = vinfo.yres;
+    mFBbpp = vinfo.bits_per_pixel;
+    mFBystride = finfo.line_length;
+
+    if (!mNoRot) {
+        mRotFD = open("/dev/msm_rotator", O_RDWR, 0);
+        if (mRotFD < 0) {
+            reportError("Cant open rotator device");
+            close(mFD);
+            mFD = -1;
+            return false;
+        }
+    }
+
+    return true;
+}
+
+bool OverlayControlChannel::setOverlayInformation(const overlay_buffer_info& info,
+                                  int flags, int orientation, int zorder,
+                                  bool ignoreFB, int requestType) {
+    int w = info.width;
+    int h = info.height;
+    int format = info.format;
+
+    mOVInfo.src.width  = w;
+    mOVInfo.src.height = h;
+    mOVInfo.src_rect.x = 0;
+    mOVInfo.src_rect.y = 0;
+    mOVInfo.dst_rect.x = 0;
+    mOVInfo.dst_rect.y = 0;
+    mOVInfo.dst_rect.w = w;
+    mOVInfo.dst_rect.h = h;
+    if(format == MDP_Y_CRCB_H2V2_TILE) {
+        if (!orientation) {
+           mOVInfo.src_rect.w = w - ((((w-1)/64 +1)*64) - w);
+           mOVInfo.src_rect.h = h - ((((h-1)/32 +1)*32) - h);
+        } else {
+           mOVInfo.src_rect.w = w;
+           mOVInfo.src_rect.h = h;
+           mOVInfo.src.width  = (((w-1)/64 +1)*64);
+           mOVInfo.src.height = (((h-1)/32 +1)*32);
+           mOVInfo.src_rect.x = mOVInfo.src.width - w;
+           mOVInfo.src_rect.y = mOVInfo.src.height - h;
+        }
+    } else {
+        mOVInfo.src_rect.w = w;
+        mOVInfo.src_rect.h = h;
+    }
+
+    mOVInfo.src.format = format;
+    if (w > mFBWidth)
+        mOVInfo.dst_rect.w = mFBWidth;
+    if (h > mFBHeight)
+        mOVInfo.dst_rect.h = mFBHeight;
+
+    mOVInfo.user_data[0] = 0;
+    if (requestType == NEW_REQUEST) {
+        mOVInfo.id = MSMFB_NEW_REQUEST;
+        mOVInfo.z_order = zorder;
+        mOVInfo.alpha = 0xff;
+        mOVInfo.transp_mask = 0xffffffff;
+        mOVInfo.flags = flags;
+    }
+    if (!ignoreFB)
+        mOVInfo.flags |= MDP_OV_PLAY_NOWAIT;
+    else
+        mOVInfo.flags &= ~MDP_OV_PLAY_NOWAIT;
+
+    return true;
+}
+
+bool OverlayControlChannel::startOVRotatorSessions(
+                           const overlay_buffer_info& info,
+                           int orientation, int requestType) {
+    bool ret = true;
+    int w = info.width;
+    int h = info.height;
+    int format = info.format;
+
+    if (orientation) {
+        mRotInfo.src.format = format;
+        mRotInfo.src.width = w;
+        mRotInfo.src.height = h;
+        mRotInfo.src_rect.w = w;
+        mRotInfo.src_rect.h = h;
+        mRotInfo.dst.width = w;
+        mRotInfo.dst.height = h;
+        if(format == MDP_Y_CRCB_H2V2_TILE) {
+            mRotInfo.src.width =  (((w-1)/64 +1)*64);
+            mRotInfo.src.height = (((h-1)/32 +1)*32);
+            mRotInfo.src_rect.w = (((w-1)/64 +1)*64);
+            mRotInfo.src_rect.h = (((h-1)/32 +1)*32);
+            mRotInfo.dst.width = (((w-1)/64 +1)*64);
+            mRotInfo.dst.height = (((h-1)/32 +1)*32);
+            mRotInfo.dst.format = MDP_Y_CRCB_H2V2;
+        }
+        mRotInfo.dst.format = get_rot_output_format(format);
+        mRotInfo.dst_x = 0;
+        mRotInfo.dst_y = 0;
+        mRotInfo.src_rect.x = 0;
+        mRotInfo.src_rect.y = 0;
+        mRotInfo.rotations = 0;
+
+        if (requestType == NEW_REQUEST) {
+            mRotInfo.enable = 0;
+            if(mUIChannel)
+                mRotInfo.enable = 1;
+            mRotInfo.session_id = 0;
+        } else
+            mRotInfo.enable = 1;
+
+        int result = ioctl(mRotFD, MSM_ROTATOR_IOCTL_START, &mRotInfo);
+        if (result) {
+            reportError("Rotator session failed");
+            dump(mRotInfo);
+            ret = false;
+        }
+    }
+
+    if (ret && ioctl(mFD, MSMFB_OVERLAY_SET, &mOVInfo)) {
+        reportError("startOVRotatorSessions, Overlay set failed");
+        dump(mOVInfo);
+        ret = false;
+    }
+
+    if (!ret)
+        closeControlChannel();
+    else
+        mIsChannelUpdated = true;
+    return ret;
+}
+
+bool OverlayControlChannel::updateOverlaySource(const overlay_buffer_info& info,
+                                                int orientation, bool waitForVsync)
+{
+    int colorFormat = getColorFormat(info.format);
+    int hw_format = get_mdp_format(colorFormat);
+    overlay_buffer_info ovBufInfo;
+    ovBufInfo.width = info.width;
+    ovBufInfo.height = info.height;
+    ovBufInfo.format = hw_format;
+
+    if (!setOverlayInformation(ovBufInfo, 0, orientation, 0, waitForVsync, UPDATE_REQUEST))
+        return false;
+
+    return startOVRotatorSessions(ovBufInfo, orientation, UPDATE_REQUEST);
+}
+
+bool OverlayControlChannel::startControlChannel(int w, int h,
+                                           int format, int fbnum, bool norot,
+                                           bool uichannel,
+                                           unsigned int format3D, int zorder,
+                                           bool ignoreFB) {
+    mNoRot = norot;
+    mFormat = format;
+    mUIChannel = uichannel;
+    fb_fix_screeninfo finfo;
+    fb_var_screeninfo vinfo;
+    int hw_format;
+    int flags = 0;
+    int colorFormat = format;
+    // The interlace mask is part of the HAL_PIXEL_FORMAT_YV12 value. Add
+    // an explicit check for the format
+    if ((format != HAL_PIXEL_FORMAT_YV12) && (format & INTERLACE_MASK)) {
+        flags |= MDP_DEINTERLACE;
+
+        // Get the actual format
+        colorFormat = format ^ HAL_PIXEL_FORMAT_INTERLACE;
+    }
+    hw_format = get_mdp_format(colorFormat);
+    if (hw_format < 0) {
+        reportError("Unsupported format");
+        return false;
+    }
+
+    mFormat3D = format3D;
+    if ( !mFormat3D || (mFormat3D & HAL_3D_OUT_MONOSCOPIC_MASK) ) {
+        // Set the share bit for sharing the VG pipe
+        flags |= MDP_OV_PIPE_SHARE;
+    }
+    if (!openDevices(fbnum))
+        return false;
+
+    int orientation = mNoRot ? 0: 1;
+    overlay_buffer_info ovBufInfo;
+    ovBufInfo.width = w;
+    ovBufInfo.height = h;
+    ovBufInfo.format = hw_format;
+    if (!setOverlayInformation(ovBufInfo, flags, orientation, zorder, ignoreFB, NEW_REQUEST))
+        return false;
+
+    return startOVRotatorSessions(ovBufInfo, orientation, NEW_REQUEST);
+}
+
+bool OverlayControlChannel::closeControlChannel() {
+    if (!isChannelUP())
+        return true;
+
+    if (!mNoRot && mRotFD > 0) {
+        ioctl(mRotFD, MSM_ROTATOR_IOCTL_FINISH, &(mRotInfo.session_id));
+        close(mRotFD);
+        mRotFD = -1;
+    }
+
+    int ovid = mOVInfo.id;
+    ioctl(mFD, MSMFB_OVERLAY_UNSET, &ovid);
+    if (m3DOVInfo.is_3d) {
+        m3DOVInfo.is_3d = 0;
+        ioctl(mFD, MSMFB_OVERLAY_3D, &m3DOVInfo);
+    }
+
+    close(mFD);
+    memset(&mOVInfo, 0, sizeof(mOVInfo));
+    memset(&mRotInfo, 0, sizeof(mRotInfo));
+    memset(&m3DOVInfo, 0, sizeof(m3DOVInfo));
+    mFD = -1;
+
+    return true;
+}
+
+bool OverlayControlChannel::updateWaitForVsyncFlags(bool waitForVsync) {
+    if (!waitForVsync)
+        mOVInfo.flags |= MDP_OV_PLAY_NOWAIT;
+    else
+        mOVInfo.flags &= ~MDP_OV_PLAY_NOWAIT;
+
+    if (ioctl(mFD, MSMFB_OVERLAY_SET, &mOVInfo)) {
+        LOGE("%s: OVERLAY_SET failed", __FUNCTION__);
+        dump(mOVInfo);
+        return false;
+    }
+    return true;
+}
+
+bool OverlayControlChannel::setPosition(int x, int y, uint32_t w, uint32_t h) {
+
+    if (!isChannelUP() ||
+           (x < 0) || (y < 0) || ((x + w) > mFBWidth) ||
+           ((y + h) > mFBHeight)) {
+        reportError("setPosition failed");
+        LOGW("x %d y %d (x+w) %d (y+h) %d FBWidth %d FBHeight %d", x, y, x+w, y+h,
+                                                        mFBWidth,mFBHeight);
+        return false;
+    }
+    if( x != mOVInfo.dst_rect.x || y != mOVInfo.dst_rect.y ||
+        w != mOVInfo.dst_rect.w || h !=  mOVInfo.dst_rect.h ) {
+        mdp_overlay ov;
+        ov.id = mOVInfo.id;
+        if (ioctl(mFD, MSMFB_OVERLAY_GET, &ov)) {
+            reportError("setPosition, overlay GET failed");
+            return false;
+        }
+
+        /* Scaling of upto a max of 8 times supported */
+        if(w >(ov.src_rect.w * HW_OVERLAY_MAGNIFICATION_LIMIT)){
+            w = HW_OVERLAY_MAGNIFICATION_LIMIT * ov.src_rect.w;
+            x = (mFBWidth - w) / 2;
+        }
+        if(h >(ov.src_rect.h * HW_OVERLAY_MAGNIFICATION_LIMIT)) {
+            h = HW_OVERLAY_MAGNIFICATION_LIMIT * ov.src_rect.h;
+            y = (mFBHeight - h) / 2;
+        }
+        ov.dst_rect.x = x;
+        ov.dst_rect.y = y;
+        ov.dst_rect.w = w;
+        ov.dst_rect.h = h;
+        if (ioctl(mFD, MSMFB_OVERLAY_SET, &ov)) {
+            reportError("setPosition, Overlay SET failed");
+            dump(ov);
+            return false;
+        }
+        mOVInfo = ov;
+    }
+    return true;
+}
+
+void OverlayControlChannel::swapOVRotWidthHeight() {
+    int tmp = mOVInfo.src.width;
+    mOVInfo.src.width = mOVInfo.src.height;
+    mOVInfo.src.height = tmp;
+
+    tmp = mOVInfo.src_rect.h;
+    mOVInfo.src_rect.h = mOVInfo.src_rect.w;
+    mOVInfo.src_rect.w = tmp;
+
+    tmp = mRotInfo.dst.width;
+    mRotInfo.dst.width = mRotInfo.dst.height;
+    mRotInfo.dst.height = tmp;
+}
+
+bool OverlayControlChannel::useVirtualFB() {
+    if(!m3DOVInfo.is_3d) {
+        m3DOVInfo.is_3d = 1;
+        mFBWidth *= 2;
+        mFBHeight /= 2;
+        m3DOVInfo.width = mFBWidth;
+        m3DOVInfo.height = mFBHeight;
+        return ioctl(mFD, MSMFB_OVERLAY_3D, &m3DOVInfo) ? false : true;
+    }
+    return true;
+}
+
+bool OverlayControlChannel::setParameter(int param, int value, bool fetch) {
+    if (!isChannelUP()) {
+        LOGE("%s: channel is not up", __FUNCTION__);
+        return false;
+    }
+
+    mdp_overlay ov = mOVInfo;
+    if (fetch && ioctl(mFD, MSMFB_OVERLAY_GET, &ov)) {
+        reportError("setParameter, overlay GET failed");
+        return false;
+    }
+    mOVInfo = ov;
+    if (!mIsChannelUpdated && (OVERLAY_TRANSFORM == param)) {
+        int orientation = get_mdp_orientation(value);
+        if (orientation == mOVInfo.user_data[0]) {
+            return true;
+        }
+    }
+    mIsChannelUpdated = false;
+
+    switch (param) {
+    case OVERLAY_DITHER:
+        break;
+    case OVERLAY_TRANSFORM:
+    {
+        int val = mOVInfo.user_data[0];
+        if (mNoRot)
+            return true;
+
+        int rot = value;
+
+        switch(rot) {
+        case 0:
+        case HAL_TRANSFORM_FLIP_H:
+        case HAL_TRANSFORM_FLIP_V:
+        {
+            if (val == MDP_ROT_90) {
+                    int tmp = mOVInfo.src_rect.y;
+                    mOVInfo.src_rect.y = mOVInfo.src.width -
+                            (mOVInfo.src_rect.x + mOVInfo.src_rect.w);
+                    mOVInfo.src_rect.x = tmp;
+                    swapOVRotWidthHeight();
+            }
+            else if (val == MDP_ROT_270) {
+                    int tmp = mOVInfo.src_rect.x;
+                    mOVInfo.src_rect.x = mOVInfo.src.height - (
+                            mOVInfo.src_rect.y + mOVInfo.src_rect.h);
+                    mOVInfo.src_rect.y = tmp;
+                    swapOVRotWidthHeight();
+            }
+            break;
+        }
+        case HAL_TRANSFORM_ROT_90:
+        case (HAL_TRANSFORM_ROT_90|HAL_TRANSFORM_FLIP_H):
+        case (HAL_TRANSFORM_ROT_90|HAL_TRANSFORM_FLIP_V):
+        {
+            if (val == MDP_ROT_270) {
+                    mOVInfo.src_rect.x = mOVInfo.src.width - (
+                            mOVInfo.src_rect.x + mOVInfo.src_rect.w);
+                    mOVInfo.src_rect.y = mOVInfo.src.height - (
+                    mOVInfo.src_rect.y + mOVInfo.src_rect.h);
+            }
+            else if (val == MDP_ROT_NOP || val == MDP_ROT_180) {
+                    int tmp = mOVInfo.src_rect.x;
+                    mOVInfo.src_rect.x = mOVInfo.src.height -
+                               (mOVInfo.src_rect.y + mOVInfo.src_rect.h);
+                    mOVInfo.src_rect.y = tmp;
+                    swapOVRotWidthHeight();
+            }
+            break;
+        }
+        case HAL_TRANSFORM_ROT_180:
+        {
+            if (val == MDP_ROT_270) {
+                    int tmp = mOVInfo.src_rect.y;
+                    mOVInfo.src_rect.y = mOVInfo.src.width -
+                               (mOVInfo.src_rect.x + mOVInfo.src_rect.w);
+                    mOVInfo.src_rect.x = tmp;
+                    swapOVRotWidthHeight();
+            }
+            else if (val == MDP_ROT_90) {
+                    int tmp = mOVInfo.src_rect.x;
+                    mOVInfo.src_rect.x = mOVInfo.src.height - (
+                             mOVInfo.src_rect.y + mOVInfo.src_rect.h);
+                    mOVInfo.src_rect.y = tmp;
+                    swapOVRotWidthHeight();
+            }
+            break;
+        }
+        case HAL_TRANSFORM_ROT_270:
+        {
+            if (val == MDP_ROT_90) {
+                    mOVInfo.src_rect.y = mOVInfo.src.height -
+                               (mOVInfo.src_rect.y + mOVInfo.src_rect.h);
+                    mOVInfo.src_rect.x = mOVInfo.src.width -
+                               (mOVInfo.src_rect.x + mOVInfo.src_rect.w);
+            }
+            else if (val == MDP_ROT_NOP || val == MDP_ROT_180) {
+                    int tmp = mOVInfo.src_rect.y;
+                    mOVInfo.src_rect.y = mOVInfo.src.width - (
+                        mOVInfo.src_rect.x + mOVInfo.src_rect.w);
+                    mOVInfo.src_rect.x = tmp;
+                    swapOVRotWidthHeight();
+            }
+            break;
+        }
+        default: return false;
+    }
+    int mdp_rotation = get_mdp_orientation(rot);
+    if (mdp_rotation == -1)
+        return false;
+
+    mOVInfo.user_data[0] = mdp_rotation;
+    mRotInfo.rotations = mOVInfo.user_data[0];
+
+    /* Rotator always outputs non-tiled formats.
+    If rotator is used, set Overlay input to non-tiled
+    Else, overlay input remains tiled */
+
+    if (mOVInfo.user_data[0]) {
+        if (mRotInfo.src.format == MDP_Y_CRCB_H2V2_TILE)
+            mOVInfo.src.format = MDP_Y_CRCB_H2V2;
+        mRotInfo.enable = 1;
+    }
+    else {
+        if(mRotInfo.src.format == MDP_Y_CRCB_H2V2_TILE)
+            mOVInfo.src.format = MDP_Y_CRCB_H2V2_TILE;
+        mRotInfo.enable = 0;
+        if(mUIChannel)
+            mRotInfo.enable = 1;
+    }
+    if (ioctl(mRotFD, MSM_ROTATOR_IOCTL_START, &mRotInfo)) {
+        reportError("setParameter, rotator start failed");
+        return false;
+    }
+
+    if ((mOVInfo.user_data[0] == MDP_ROT_90) ||
+        (mOVInfo.user_data[0] == MDP_ROT_270))
+        mOVInfo.flags |= MDP_SOURCE_ROTATED_90;
+    else
+        mOVInfo.flags &= ~MDP_SOURCE_ROTATED_90;
+
+    if (ioctl(mFD, MSMFB_OVERLAY_SET, &mOVInfo)) {
+        reportError("setParameter, overlay set failed");
+        dump(mOVInfo);
+        return false;
+    }
+        break;
+    }
+    default:
+        reportError("Unsupproted param");
+    return false;
+    }
+
+    return true;
+}
+
+bool OverlayControlChannel::getPosition(int& x, int& y,
+                                  uint32_t& w, uint32_t& h) {
+    if (!isChannelUP())
+        return false;
+    //mOVInfo has the current Overlay Position
+    x = mOVInfo.dst_rect.x;
+    y = mOVInfo.dst_rect.y;
+    w = mOVInfo.dst_rect.w;
+    h = mOVInfo.dst_rect.h;
+
+    return true;
+}
+
+bool OverlayControlChannel::getOrientation(int& orientation) const {
+    if (!isChannelUP())
+        return false;
+    // mOVInfo has the current orientation
+    orientation = mOVInfo.user_data[0];
+    return true;
+}
+bool OverlayControlChannel::getOvSessionID(int& sessionID) const {
+    if (!isChannelUP())
+        return false;
+    sessionID = mOVInfo.id;
+    return true;
+}
+
+bool OverlayControlChannel::getRotSessionID(int& sessionID) const {
+    if (!isChannelUP())
+        return false;
+    sessionID = mRotInfo.session_id;
+    return true;
+}
+
+bool OverlayControlChannel::getSize(int& size) const {
+    if (!isChannelUP())
+        return false;
+    size = mSize;
+    return true;
+}
+
+OverlayDataChannel::OverlayDataChannel() : mNoRot(false), mFD(-1), mRotFD(-1),
+                                  mPmemFD(-1), mPmemAddr(0), mUpdateDataChannel(0)
+{
+#ifdef USE_ION
+    mAlloc = gralloc::IAllocController::getInstance();
+#endif
+}
+
+OverlayDataChannel::~OverlayDataChannel() {
+    closeDataChannel();
+}
+
+bool OverlayDataChannel::startDataChannel(
+               const OverlayControlChannel& objOvCtrlChannel,
+               int fbnum, bool norot, bool uichannel, int num_buffers) {
+    int ovid, rotid, size;
+    mNoRot = norot;
+    memset(&mOvData, 0, sizeof(mOvData));
+    memset(&mOvDataRot, 0, sizeof(mOvDataRot));
+    memset(&mRotData, 0, sizeof(mRotData));
+    if (objOvCtrlChannel.getOvSessionID(ovid) &&
+            objOvCtrlChannel.getRotSessionID(rotid) &&
+            objOvCtrlChannel.getSize(size)) {
+        return startDataChannel(ovid, rotid, size, fbnum,
+                      norot, uichannel, num_buffers);
+    }
+    else
+        return false;
+}
+
+bool OverlayDataChannel::openDevices(int fbnum, bool uichannel, int num_buffers) {
+    if (fbnum < 0)
+        return false;
+    char const * const device_template =
+                      "/dev/graphics/fb%u";
+    char dev_name[64];
+    snprintf(dev_name, 64, device_template, fbnum);
+
+    mFD = open(dev_name, O_RDWR, 0);
+    if (mFD < 0) {
+        reportError("Cant open framebuffer ");
+        return false;
+    }
+    if (!mNoRot) {
+        mRotFD = open("/dev/msm_rotator", O_RDWR, 0);
+        if (mRotFD < 0) {
+            reportError("Cant open rotator device");
+            close(mFD);
+            mFD = -1;
+            return false;
+        }
+
+        return mapRotatorMemory(num_buffers, uichannel, NEW_REQUEST);
+    }
+    return true;
+}
+
+bool OverlayDataChannel::mapRotatorMemory(int num_buffers, bool uiChannel, int requestType)
+{
+    mPmemAddr = MAP_FAILED;
+
+#ifdef USE_ION
+    alloc_data data;
+    data.base = 0;
+    data.fd = -1;
+    data.offset = 0;
+    data.size = mPmemOffset * num_buffers;
+    data.align = getpagesize();
+    data.uncached = true;
+
+    int err = mAlloc->allocate(data, GRALLOC_USAGE_PRIVATE_ADSP_HEAP|
+                                     GRALLOC_USAGE_PRIVATE_SMI_HEAP, 0);
+    if(err) {
+        reportError("Cant allocate from ION");
+        close(mFD);
+        mFD = -1;
+        close(mRotFD);
+        mRotFD = -1;
+        return false;
+    }
+    mPmemFD = data.fd;
+    mPmemAddr = data.base;
+    mBufferType = data.allocType;
+#else
+
+    if((requestType == NEW_REQUEST) && !uiChannel) {
+        mPmemFD = open("/dev/pmem_smipool", O_RDWR | O_SYNC);
+        if(mPmemFD >= 0)
+            mPmemAddr = (void *) mmap(NULL, mPmemOffset * num_buffers, PROT_READ | PROT_WRITE,
+                                      MAP_SHARED, mPmemFD, 0);
+    }
+
+    if (mPmemAddr == MAP_FAILED) {
+        mPmemFD = open("/dev/pmem_adsp", O_RDWR | O_SYNC);
+        if (mPmemFD < 0) {
+            reportError("Cant open pmem_adsp ");
+            close(mFD);
+            mFD = -1;
+            close(mRotFD);
+            mRotFD = -1;
+            return false;
+        } else {
+            mPmemAddr = (void *) mmap(NULL, mPmemOffset * num_buffers, PROT_READ | PROT_WRITE,
+                                      MAP_SHARED, mPmemFD, 0);
+            if (mPmemAddr == MAP_FAILED) {
+                reportError("Cant map pmem_adsp ");
+                close(mFD);
+                mFD = -1;
+                close(mPmemFD);
+                mPmemFD = -1;
+                close(mRotFD);
+                mRotFD = -1;
+                return false;
+            }
+        }
+    }
+#endif
+    // Set this flag if source memory is fb
+    if(uiChannel)
+        mRotData.src.flags |= MDP_MEMORY_ID_TYPE_FB;
+
+    mOvDataRot.data.memory_id = mPmemFD;
+    mRotData.dst.memory_id = mPmemFD;
+    mRotData.dst.offset = 0;
+    mNumBuffers = num_buffers;
+    mCurrentItem = 0;
+    for (int i = 0; i < num_buffers; i++)
+        mRotOffset[i] = i * mPmemOffset;
+
+    return true;
+}
+
+bool OverlayDataChannel::updateDataChannel(int updateStatus, int size) {
+    mUpdateDataChannel = updateStatus;
+    mNewPmemOffset = size;
+    return true;
+}
+
+bool OverlayDataChannel::startDataChannel(int ovid, int rotid, int size,
+                                   int fbnum, bool norot,
+                                   bool uichannel, int num_buffers) {
+    memset(&mOvData, 0, sizeof(mOvData));
+    memset(&mOvDataRot, 0, sizeof(mOvDataRot));
+    memset(&mRotData, 0, sizeof(mRotData));
+    mNoRot = norot;
+    mOvData.data.memory_id = -1;
+    mOvData.id = ovid;
+    mOvDataRot = mOvData;
+    mPmemOffset = size;
+    mRotData.session_id = rotid;
+    mNumBuffers = 0;
+    mCurrentItem = 0;
+
+    return openDevices(fbnum, uichannel, num_buffers);
+}
+
+bool OverlayDataChannel::closeDataChannel() {
+    if (!isChannelUP())
+        return true;
+
+    if (!mNoRot && mRotFD > 0) {
+#ifdef USE_ION
+        sp<IMemAlloc> memalloc = mAlloc->getAllocator(mBufferType);
+        memalloc->free_buffer(mPmemAddr, mPmemOffset * mNumBuffers, 0, mPmemFD);
+#else
+        munmap(mPmemAddr, mPmemOffset * mNumBuffers);
+        close(mPmemFD);
+#endif
+        close(mPmemFD);
+        mPmemFD = -1;
+        close(mRotFD);
+        mRotFD = -1;
+    }
+    close(mFD);
+    mFD = -1;
+    memset(&mOvData, 0, sizeof(mOvData));
+    memset(&mOvDataRot, 0, sizeof(mOvDataRot));
+    memset(&mRotData, 0, sizeof(mRotData));
+
+    mNumBuffers = 0;
+    mCurrentItem = 0;
+
+    return true;
+}
+
+bool OverlayDataChannel::setFd(int fd) {
+    mOvData.data.memory_id = fd;
+    return true;
+}
+
+bool OverlayDataChannel::queueBuffer(uint32_t offset) {
+    if ((!isChannelUP()) || mOvData.data.memory_id < 0) {
+        reportError("QueueBuffer failed, either channel is not set or no file descriptor to read from");
+        return false;
+    }
+
+    int oldPmemFD = -1;
+    void* oldPmemAddr = MAP_FAILED;
+    uint32_t oldPmemOffset = -1;
+    bool result;
+    if (!mNoRot) {
+        if (mUpdateDataChannel) {
+            oldPmemFD = mPmemFD;
+            oldPmemAddr = mPmemAddr;
+            oldPmemOffset = mPmemOffset;
+            mPmemOffset = mNewPmemOffset;
+            mNewPmemOffset = -1;
+            // Map the new PMEM memory
+            result = mapRotatorMemory(mNumBuffers, 0, UPDATE_REQUEST);
+            if (!result) {
+                LOGE("queueBuffer: mapRotatorMemory failed");
+                return false;
+            }
+        }
+    }
+
+    result = queue(offset);
+
+    // Unmap the old PMEM memory after the queueBuffer has returned
+    if (oldPmemFD != -1 && oldPmemAddr != MAP_FAILED) {
+#ifdef USE_ION
+        sp<IMemAlloc> memalloc = mAlloc->getAllocator(mBufferType);
+        memalloc->free_buffer(oldPmemAddr, oldPmemOffset * mNumBuffers, 0, oldPmemFD);
+#else
+        munmap(oldPmemAddr, oldPmemOffset * mNumBuffers);
+        close(oldPmemFD);
+#endif
+
+        oldPmemFD = -1;
+    }
+    return result;
+}
+
+bool OverlayDataChannel::queue(uint32_t offset) {
+    msmfb_overlay_data *odPtr;
+    mOvData.data.offset = offset;
+    odPtr = &mOvData;
+    if (!mNoRot) {
+        mRotData.src.memory_id = mOvData.data.memory_id;
+        mRotData.src.offset = offset;
+        mRotData.dst.offset = (mRotData.dst.offset) ? 0 : mPmemOffset;
+        mRotData.dst.offset = mRotOffset[mCurrentItem];
+        mCurrentItem = (mCurrentItem + 1) % mNumBuffers;
+
+        int result = ioctl(mRotFD,
+                       MSM_ROTATOR_IOCTL_ROTATE, &mRotData);
+
+        if (!result) {
+            mOvDataRot.data.offset = (uint32_t) mRotData.dst.offset;
+            odPtr = &mOvDataRot;
+        }
+    }
+
+    if (ioctl(mFD, MSMFB_OVERLAY_PLAY, odPtr)) {
+        reportError("overlay play failed.");
+        return false;
+    }
+    return true;
+}
+
+bool OverlayDataChannel::getCropS3D(overlay_rect *inRect, int channel, int format,
+                                    overlay_rect *rect) {
+    // for the 3D usecase extract channels from a frame
+    switch (format & INPUT_MASK_3D) {
+    case HAL_3D_IN_SIDE_BY_SIDE_L_R:
+        if(channel == 0) {
+            rect->x = 0;
+            rect->y = 0;
+            rect->w = inRect->w/2;
+            rect->h = inRect->h;
+        } else {
+            rect->x = inRect->w/2;
+            rect->y = 0;
+            rect->w = inRect->w/2;
+            rect->h = inRect->h;
+        }
+        break;
+    case HAL_3D_IN_SIDE_BY_SIDE_R_L:
+         if(channel == 1) {
+            rect->x = 0;
+            rect->y = 0;
+            rect->w = inRect->w/2;
+            rect->h = inRect->h;
+        } else {
+            rect->x = inRect->w/2;
+            rect->y = 0;
+            rect->w = inRect->w/2;
+            rect->h = inRect->h;
+        }
+         break;
+    case HAL_3D_IN_TOP_BOTTOM:
+        if(channel == 0) {
+            rect->x = 0;
+            rect->y = 0;
+            rect->w = inRect->w;
+            rect->h = inRect->h/2;
+        } else {
+            rect->x = 0;
+            rect->y = inRect->h/2;
+            rect->w = inRect->w;
+            rect->h = inRect->h/2;
+        }
+        break;
+    case HAL_3D_IN_INTERLEAVE:
+      break;
+    default:
+        reportError("Unsupported 3D format...");
+        break;
+   }
+   return true;
+}
+
+bool OverlayDataChannel::setCrop(uint32_t x, uint32_t y, uint32_t w, uint32_t h) {
+    if (!isChannelUP()) {
+        reportError("Channel not set");
+        return false;
+    }
+
+    mdp_overlay ov;
+    ov.id = mOvData.id;
+    if (ioctl(mFD, MSMFB_OVERLAY_GET, &ov)) {
+        reportError("setCrop, overlay GET failed");
+        return false;
+    }
+
+    if ((ov.user_data[0] == MDP_ROT_90) ||
+        (ov.user_data[0] == (MDP_ROT_90 | MDP_FLIP_UD)) ||
+        (ov.user_data[0] == (MDP_ROT_90 | MDP_FLIP_LR))){
+        if (ov.src.width < (y + h))
+            return false;
+
+        uint32_t tmp = x;
+        x = ov.src.width - (y + h);
+        y = tmp;
+
+        tmp = w;
+        w = h;
+        h = tmp;
+    }
+    else if (ov.user_data[0] == MDP_ROT_270) {
+        if (ov.src.height < (x + w))
+            return false;
+
+        uint32_t tmp = y;
+        y = ov.src.height - (x + w);
+        x = tmp;
+
+        tmp = w;
+        w = h;
+        h = tmp;
+    }
+    else if(ov.user_data[0] == MDP_ROT_180) {
+        if ((ov.src.height < (y + h)) || (ov.src.width < ( x + w)))
+            return false;
+
+        x = ov.src.width - (x + w);
+        y = ov.src.height - (y + h);
+    }
+
+
+    if ((ov.src_rect.x == x) &&
+           (ov.src_rect.y == y) &&
+           (ov.src_rect.w == w) &&
+           (ov.src_rect.h == h))
+        return true;
+
+    normalize_crop(x, w);
+    normalize_crop(y, h);
+
+    ov.src_rect.x = x;
+    ov.src_rect.y = y;
+    ov.src_rect.w = w;
+    ov.src_rect.h = h;
+
+    /* Scaling of upto a max of 8 times supported */
+    if(ov.dst_rect.w >(ov.src_rect.w * HW_OVERLAY_MAGNIFICATION_LIMIT)){
+        ov.dst_rect.w = HW_OVERLAY_MAGNIFICATION_LIMIT * ov.src_rect.w;
+    }
+    if(ov.dst_rect.h >(ov.src_rect.h * HW_OVERLAY_MAGNIFICATION_LIMIT)) {
+        ov.dst_rect.h = HW_OVERLAY_MAGNIFICATION_LIMIT * ov.src_rect.h;
+    }
+    if (ioctl(mFD, MSMFB_OVERLAY_SET, &ov)) {
+        reportError("setCrop, overlay set error");
+        return false;
+    }
+
+    return true;
+}
diff --git a/liboverlay/overlayLib.h b/liboverlay/overlayLib.h
new file mode 100644
index 0000000..0ad92ce
--- /dev/null
+++ b/liboverlay/overlayLib.h
@@ -0,0 +1,306 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef INCLUDE_OVERLAY_LIB
+#define INCLUDE_OVERLAY_LIB
+
+#include <cutils/log.h>
+#include <cutils/properties.h>
+#include <cutils/atomic.h>
+
+#include <hardware/hardware.h>
+#include <hardware/gralloc.h>
+
+#include <dlfcn.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <string.h>
+#include <stdlib.h>
+#include <pthread.h>
+
+#include <linux/fb.h>
+#include <linux/msm_mdp.h>
+#include <linux/msm_rotator.h>
+#include <linux/android_pmem.h>
+
+#include <sys/mman.h>
+#include <sys/ioctl.h>
+#include <hardware/overlay.h>
+#include <utils/RefBase.h>
+#include <alloc_controller.h>
+#include <memalloc.h>
+
+#define HW_OVERLAY_MAGNIFICATION_LIMIT 8
+#define HW_OVERLAY_MINIFICATION_LIMIT HW_OVERLAY_MAGNIFICATION_LIMIT
+
+#define EVEN_OUT(x) if (x & 0x0001) {x--;}
+#define VG0_PIPE 0
+#define VG1_PIPE 1
+#define NUM_CHANNELS 2
+#define FRAMEBUFFER_0 0
+#define FRAMEBUFFER_1 1
+
+enum {
+    HDMI_OFF,
+    HDMI_ON
+};
+
+enum {
+    OVERLAY_CHANNEL_DOWN,
+    OVERLAY_CHANNEL_UP
+};
+
+enum {
+    NEW_REQUEST,
+    UPDATE_REQUEST
+};
+/* ------------------------------- 3D defines ---------------------------------------*/
+// The compound format passed to the overlay is
+// ABCCC where A is the input 3D format,
+// B is the output 3D format
+// CCC is the color format e.g YCbCr420SP YCrCb420SP etc.
+#define FORMAT_3D(x) (x & 0xFF000)
+#define COLOR_FORMAT(x) (x & 0xFFF)
+// in the final 3D format, the MSB 2Bytes are the input format and the
+// LSB 2bytes are the output format. Shift the output byte 12 bits.
+#define SHIFT_OUTPUT_3D 12
+#define FORMAT_3D_OUTPUT(x) ((x & 0xF000) >> SHIFT_OUTPUT_3D)
+#define FORMAT_3D_INPUT(x)  (x & 0xF0000)
+#define INPUT_MASK_3D  0xFFFF0000
+#define OUTPUT_MASK_3D 0x0000FFFF
+#define SHIFT_3D       16
+// The output format is the 2MSB bytes. Shift the format by 12 to reflect this
+#define HAL_3D_OUT_SIDE_BY_SIDE_MASK (HAL_3D_OUT_SIDE_BY_SIDE >> SHIFT_OUTPUT_3D)
+#define HAL_3D_OUT_TOP_BOTTOM_MASK   (HAL_3D_OUT_TOP_BOTTOM   >> SHIFT_OUTPUT_3D)
+#define HAL_3D_OUT_INTERLEAVE_MASK   (HAL_3D_OUT_INTERLEAVE   >> SHIFT_OUTPUT_3D)
+#define HAL_3D_OUT_MONOSCOPIC_MASK   (HAL_3D_OUT_MONOSCOPIC   >> SHIFT_OUTPUT_3D)
+
+// 3D panel barrier orientation
+#define BARRIER_LANDSCAPE 1
+#define BARRIER_PORTRAIT  2
+
+#ifdef HDMI_AS_PRIMARY
+#define FORMAT_3D_FILE        "/sys/class/graphics/fb0/format_3d"
+#define EDID_3D_INFO_FILE     "/sys/class/graphics/fb0/3d_present"
+#else
+#define FORMAT_3D_FILE        "/sys/class/graphics/fb1/format_3d"
+#define EDID_3D_INFO_FILE     "/sys/class/graphics/fb1/3d_present"
+#endif
+#define BARRIER_FILE          "/sys/devices/platform/mipi_novatek.0/enable_3d_barrier"
+/* -------------------------- end 3D defines ----------------------------------------*/
+
+// Struct to hold the buffer info: geometry and size
+struct overlay_buffer_info {
+    int width;
+    int height;
+    int format;
+    int size;
+};
+
+namespace overlay {
+
+enum {
+    OV_UI_MIRROR_TV = 0,
+    OV_2D_VIDEO_ON_PANEL,
+    OV_2D_VIDEO_ON_TV,
+    OV_3D_VIDEO_2D_PANEL,
+    OV_3D_VIDEO_2D_TV,
+    OV_3D_VIDEO_3D_PANEL,
+    OV_3D_VIDEO_3D_TV
+};
+bool isHDMIConnected();
+bool is3DTV();
+bool isPanel3D();
+bool usePanel3D();
+bool send3DInfoPacket(unsigned int format3D);
+bool enableBarrier(unsigned int orientation);
+unsigned int  getOverlayConfig (unsigned int format3D, bool poll = true,
+                                bool isHDMI = false);
+int getColorFormat(int format);
+int get_mdp_format(int format);
+int get_size(int format, int w, int h);
+int get_rot_output_format(int format);
+int get_mdp_orientation(int value);
+void normalize_crop(uint32_t& xy, uint32_t& wh);
+
+/* Print values being sent to driver in case of ioctl failures
+   These logs are enabled only if DEBUG_OVERLAY is true       */
+void dump(msm_rotator_img_info& mRotInfo);
+void dump(mdp_overlay& mOvInfo);
+const char* getFormatString(int format);
+
+const int max_num_buffers = 3;
+typedef struct mdp_rect overlay_rect;
+
+class OverlayControlChannel {
+
+    bool mNoRot;
+
+    int mFBWidth;
+    int mFBHeight;
+    int mFBbpp;
+    int mFBystride;
+    int mFormat;
+    int mFD;
+    int mRotFD;
+    int mSize;
+    int mOrientation;
+    unsigned int mFormat3D;
+    bool mUIChannel;
+    mdp_overlay mOVInfo;
+    msm_rotator_img_info mRotInfo;
+    msmfb_overlay_3d m3DOVInfo;
+    bool mIsChannelUpdated;
+    bool openDevices(int fbnum = -1);
+    bool setOverlayInformation(const overlay_buffer_info& info,
+                               int flags, int orientation, int zorder = 0, bool ignoreFB = false,
+                               int requestType = NEW_REQUEST);
+    bool startOVRotatorSessions(const overlay_buffer_info& info, int orientation, int requestType);
+    void swapOVRotWidthHeight();
+
+public:
+    OverlayControlChannel();
+    ~OverlayControlChannel();
+    bool startControlChannel(int w, int h, int format,
+                               int fbnum, bool norot = false,
+                               bool uichannel = false,
+                               unsigned int format3D = 0, int zorder = 0,
+                               bool ignoreFB = false);
+    bool closeControlChannel();
+    bool setPosition(int x, int y, uint32_t w, uint32_t h);
+    bool setParameter(int param, int value, bool fetch = true);
+    void setSize (int size) { mSize = size; }
+    bool getPosition(int& x, int& y, uint32_t& w, uint32_t& h);
+    bool getOvSessionID(int& sessionID) const;
+    bool getRotSessionID(int& sessionID) const;
+    bool getSize(int& size) const;
+    bool isChannelUP() const { return (mFD > 0); }
+    int getFBWidth() const { return mFBWidth; }
+    int getFBHeight() const { return mFBHeight; }
+    int getFormat3D() const { return mFormat3D; }
+    bool getOrientation(int& orientation) const;
+    bool updateWaitForVsyncFlags(bool waitForVsync);
+    bool getAspectRatioPosition(int w, int h, overlay_rect *rect);
+    bool getPositionS3D(int channel, int format, overlay_rect *rect);
+    bool updateOverlaySource(const overlay_buffer_info& info, int orientation, bool waitForVsync);
+    bool getFormat() const { return mFormat; }
+    bool useVirtualFB ();
+    int getOverlayFlags() const { return mOVInfo.flags; }
+};
+
+class OverlayDataChannel {
+
+    bool mNoRot;
+    int mFD;
+    int mRotFD;
+    int mPmemFD;
+    void* mPmemAddr;
+    uint32_t mPmemOffset;
+    uint32_t mNewPmemOffset;
+    msmfb_overlay_data mOvData;
+    msmfb_overlay_data mOvDataRot;
+    msm_rotator_data_info mRotData;
+    int mRotOffset[max_num_buffers];
+    int mCurrentItem;
+    int mNumBuffers;
+    int mUpdateDataChannel;
+    android::sp<gralloc::IAllocController> mAlloc;
+    int mBufferType;
+
+    bool openDevices(int fbnum = -1, bool uichannel = false, int num_buffers = 2);
+    bool mapRotatorMemory(int num_buffers, bool uiChannel, int requestType);
+    bool queue(uint32_t offset);
+
+public:
+    OverlayDataChannel();
+    ~OverlayDataChannel();
+    bool startDataChannel(const OverlayControlChannel& objOvCtrlChannel,
+                                int fbnum, bool norot = false,
+                                bool uichannel = false, int num_buffers = 2);
+    bool startDataChannel(int ovid, int rotid, int size,
+                       int fbnum, bool norot = false, bool uichannel = false,
+                       int num_buffers = 2);
+    bool closeDataChannel();
+    bool setFd(int fd);
+    bool queueBuffer(uint32_t offset);
+    bool setCrop(uint32_t x, uint32_t y, uint32_t w, uint32_t h);
+    bool getCropS3D(overlay_rect *inRect, int channel, int format, overlay_rect *rect);
+    bool isChannelUP() const { return (mFD > 0); }
+    bool updateDataChannel(int updateStatus, int size);
+};
+
+/*
+ * Overlay class for single thread application
+ * A multiple thread/process application need to use Overlay HAL
+ */
+class Overlay {
+
+    bool mChannelUP;
+    bool mHDMIConnected;
+    unsigned int mS3DFormat;
+    //Actual cropped source width and height of overlay
+    int mCroppedSrcWidth;
+    int mCroppedSrcHeight;
+    overlay_buffer_info mOVBufferInfo;
+    int mState;
+    OverlayControlChannel objOvCtrlChannel[2];
+    OverlayDataChannel    objOvDataChannel[2];
+
+public:
+    Overlay();
+    ~Overlay();
+
+    static bool sHDMIAsPrimary;
+    bool startChannel(const overlay_buffer_info& info, int fbnum, bool norot = false,
+                          bool uichannel = false, unsigned int format3D = 0,
+                          int channel = 0, bool ignoreFB = false,
+                          int num_buffers = 2);
+    bool closeChannel();
+    bool setPosition(int x, int y, uint32_t w, uint32_t h);
+    bool setParameter(int param, int value);
+    bool setOrientation(int value, int channel = 0);
+    bool setFd(int fd, int channel = 0);
+    bool queueBuffer(uint32_t offset, int channel = 0);
+    bool getPosition(int& x, int& y, uint32_t& w, uint32_t& h, int channel = 0);
+    bool isChannelUP() const { return mChannelUP; }
+    int getFBWidth(int channel = 0) const;
+    int getFBHeight(int channel = 0) const;
+    bool getOrientation(int& orientation, int channel = 0) const;
+    bool queueBuffer(buffer_handle_t buffer);
+    bool setSource(const overlay_buffer_info& info, int orientation, bool hdmiConnected,
+                    bool ignoreFB = false, int numBuffers = 2);
+    bool setCrop(uint32_t x, uint32_t y, uint32_t w, uint32_t h);
+    int  getChannelStatus() const { return (mChannelUP ? OVERLAY_CHANNEL_UP: OVERLAY_CHANNEL_DOWN); }
+    void setHDMIStatus (bool isHDMIConnected) { mHDMIConnected = isHDMIConnected; mState = -1; }
+    int getHDMIStatus() const {return (mHDMIConnected ? HDMI_ON : HDMI_OFF); }
+
+private:
+    bool setChannelPosition(int x, int y, uint32_t w, uint32_t h, int channel = 0);
+    bool setChannelCrop(uint32_t x, uint32_t y, uint32_t w, uint32_t h, int channel);
+    bool queueBuffer(int fd, uint32_t offset, int channel);
+    bool updateOverlaySource(const overlay_buffer_info& info, int orientation, bool waitForVsync);
+    int getS3DFormat(int format);
+};
+
+struct overlay_shared_data {
+    volatile bool isControlSetup;
+    unsigned int state;
+    int rotid[2];
+    int ovid[2];
+};
+};
+#endif
diff --git a/liboverlay/overlayLibUI.cpp b/liboverlay/overlayLibUI.cpp
new file mode 100644
index 0000000..dd19cd9
--- /dev/null
+++ b/liboverlay/overlayLibUI.cpp
@@ -0,0 +1,524 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "overlayLibUI.h"
+#include "gralloc_priv.h"
+#define LOG_TAG "OverlayUI"
+
+using android::sp;
+using gralloc::IMemAlloc;
+using gralloc::alloc_data;
+
+namespace {
+/* helper functions */
+bool checkOVState(int w, int h, int format, int orientation,
+                            int zorder, const mdp_overlay& ov) {
+    switch(orientation) {
+        case OVERLAY_TRANSFORM_ROT_90:
+        case OVERLAY_TRANSFORM_ROT_270: {
+            int tmp = w;
+            w = h;
+            h = tmp;
+            break;
+        }
+        default:
+            break;
+    }
+
+    int srcw = (w + 31) & ~31;
+    int srch = (h + 31) & ~31;
+    bool displayAttrsCheck = ((srcw == ov.src.width) && (srch == ov.src.height) &&
+                                 (format == ov.src.format));
+    bool zOrderCheck = (ov.z_order == zorder);
+
+    if (displayAttrsCheck && zorder == overlay::NO_INIT)
+        return true;
+
+    if (displayAttrsCheck && zorder != overlay::NO_INIT
+                            && ov.z_order == zorder)
+        return true;
+    return false;
+}
+
+void swapOVRotWidthHeight(msm_rotator_img_info& rotInfo,
+                                 mdp_overlay& ovInfo) {
+    int srcWidth = ovInfo.src.width;
+    ovInfo.src.width = ovInfo.src.height;
+    ovInfo.src.height = srcWidth;
+
+    int srcRectWidth = ovInfo.src_rect.w;
+    ovInfo.src_rect.w = ovInfo.src_rect.h;
+    ovInfo.src_rect.h = srcRectWidth;
+
+    int dstWidth = rotInfo.dst.width;
+    rotInfo.dst.width = rotInfo.dst.height;
+    rotInfo.dst.height = dstWidth;
+}
+
+void setupOvRotInfo(int w, int h, int format, int orientation,
+                             mdp_overlay& ovInfo, msm_rotator_img_info& rotInfo) {
+    memset(&ovInfo, 0, sizeof(ovInfo));
+    memset(&rotInfo, 0, sizeof(rotInfo));
+    ovInfo.id = MSMFB_NEW_REQUEST;
+    int srcw = (w + 31) & ~31;
+    int srch = (h + 31) & ~31;
+    ovInfo.src.width = srcw;
+    ovInfo.src.height = srch;
+    ovInfo.src.format = format;
+    ovInfo.src_rect.w = w;
+    ovInfo.src_rect.h = h;
+    ovInfo.alpha = 0xff;
+    ovInfo.transp_mask = 0xffffffff;
+    rotInfo.src.format = format;
+    rotInfo.dst.format = format;
+    rotInfo.src.width = srcw;
+    rotInfo.src.height = srch;
+    rotInfo.src_rect.w = srcw;
+    rotInfo.src_rect.h = srch;
+    rotInfo.dst.width = srcw;
+    rotInfo.dst.height = srch;
+
+    int rot = orientation;
+    switch(rot) {
+        case 0:
+        case HAL_TRANSFORM_FLIP_H:
+        case HAL_TRANSFORM_FLIP_V:
+            rot = 0;
+            break;
+        case HAL_TRANSFORM_ROT_90:
+        case (HAL_TRANSFORM_ROT_90|HAL_TRANSFORM_FLIP_H):
+        case (HAL_TRANSFORM_ROT_90|HAL_TRANSFORM_FLIP_V): {
+            int tmp = ovInfo.src_rect.x;
+            ovInfo.src_rect.x = ovInfo.src.height -
+                                 (ovInfo.src_rect.y + ovInfo.src_rect.h);
+            ovInfo.src_rect.y = tmp;
+            swapOVRotWidthHeight(rotInfo, ovInfo);
+            rot = HAL_TRANSFORM_ROT_90;
+            break;
+        }
+        case HAL_TRANSFORM_ROT_180:
+            break;
+        case HAL_TRANSFORM_ROT_270: {
+            int tmp = ovInfo.src_rect.y;
+            ovInfo.src_rect.y = ovInfo.src.width -
+                                   (ovInfo.src_rect.x + ovInfo.src_rect.w);
+            ovInfo.src_rect.x = tmp;
+            swapOVRotWidthHeight(rotInfo, ovInfo);
+            break;
+        }
+        default:
+            break;
+    }
+
+    int mdp_rotation = overlay::get_mdp_orientation(rot);
+    if (mdp_rotation < 0)
+        mdp_rotation = 0;
+    ovInfo.user_data[0] = mdp_rotation;
+    rotInfo.rotations = ovInfo.user_data[0];
+    if (mdp_rotation)
+        rotInfo.enable = 1;
+    ovInfo.dst_rect.w = ovInfo.src_rect.w;
+    ovInfo.dst_rect.h = ovInfo.src_rect.h;
+}
+
+bool isRGBType(int format) {
+    bool ret = false;
+    switch(format) {
+        case MDP_RGBA_8888:
+        case MDP_BGRA_8888:
+        case MDP_RGBX_8888:
+        case MDP_RGB_565:
+            ret = true;
+            break;
+        default:
+            ret = false;
+            break;
+    }
+    return ret;
+}
+
+int getRGBBpp(int format) {
+    int ret = -1;
+    switch(format) {
+        case MDP_RGBA_8888:
+        case MDP_BGRA_8888:
+        case MDP_RGBX_8888:
+            ret = 4;
+            break;
+        case MDP_RGB_565:
+            ret = 2;
+            break;
+        default:
+            ret = -1;
+            break;
+    }
+
+    return ret;
+}
+
+bool turnOFFVSync() {
+    static int swapIntervalPropVal = -1;
+    if (swapIntervalPropVal == -1) {
+        char pval[PROPERTY_VALUE_MAX];
+        property_get("debug.gr.swapinterval", pval, "1");
+        swapIntervalPropVal = atoi(pval);
+    }
+    return (swapIntervalPropVal == 0);
+}
+
+};
+
+namespace overlay {
+
+status_t Display::openDisplay(int fbnum) {
+    if (mFD != NO_INIT)
+        return ALREADY_EXISTS;
+
+    status_t ret = NO_INIT;
+    char const * const device_template =
+                        "/dev/graphics/fb%u";
+    char dev_name[64];
+    snprintf(dev_name, 64, device_template, fbnum);
+
+    mFD = open(dev_name, O_RDWR, 0);
+    if (mFD < 0) {
+        LOGE("Failed to open FB %d", fbnum);
+        return ret;
+    }
+
+    fb_var_screeninfo vinfo;
+    if (ioctl(mFD, FBIOGET_VSCREENINFO, &vinfo)) {
+        LOGE("FBIOGET_VSCREENINFO on failed on FB %d", fbnum);
+        close(mFD);
+        mFD = NO_INIT;
+        return ret;
+    }
+
+    mFBWidth = vinfo.xres;
+    mFBHeight = vinfo.yres;
+    mFBBpp = vinfo.bits_per_pixel;
+    ret = NO_ERROR;
+
+    return ret;
+}
+
+status_t OVHelper::startOVSession(mdp_overlay& ovInfo, int fbnum) {
+    status_t ret = NO_INIT;
+
+    if (mSessionID == NO_INIT) {
+        ret = mobjDisplay.openDisplay(fbnum);
+        if (ret != NO_ERROR)
+            return ret;
+
+        if (ioctl(mobjDisplay.getFD(), MSMFB_OVERLAY_SET, &ovInfo)) {
+            LOGE("OVerlay set failed..");
+            mobjDisplay.closeDisplay();
+            ret = BAD_VALUE;
+        }
+        else {
+            mSessionID = ovInfo.id;
+            mOVInfo = ovInfo;
+            ret  = NO_ERROR;
+        }
+    }
+    else
+        ret = ALREADY_EXISTS;
+
+    return ret;
+}
+
+status_t OVHelper::queueBuffer(msmfb_overlay_data ovData) {
+    if (mSessionID == NO_INIT)
+        return NO_INIT;
+
+    ovData.id = mSessionID;
+    if (ioctl(mobjDisplay.getFD(), MSMFB_OVERLAY_PLAY, &ovData))
+        return BAD_VALUE;
+
+    return NO_ERROR;
+}
+
+status_t OVHelper::closeOVSession() {
+    if (mSessionID != NO_INIT) {
+        ioctl(mobjDisplay.getFD(), MSMFB_OVERLAY_UNSET, &mSessionID);
+        mobjDisplay.closeDisplay();
+    }
+
+    mSessionID = NO_INIT;
+
+    return NO_ERROR;
+}
+
+status_t OVHelper::setPosition(int x, int y, int w, int h) {
+    status_t ret = BAD_VALUE;
+    if (mSessionID != NO_INIT) {
+        int fd = mobjDisplay.getFD();
+        if (x < 0 || y < 0 || ((x + w) > getFBWidth())) {
+            LOGE("set position failed, invalid argument");
+            return ret;
+        }
+
+        mdp_overlay ov;
+        ov.id = mSessionID;
+        if (!ioctl(fd, MSMFB_OVERLAY_GET, &ov)) {
+            if (x != ov.dst_rect.x || y != ov.dst_rect.y ||
+                      w != ov.dst_rect.w || h != ov.dst_rect.h) {
+                ov.dst_rect.x = x;
+                ov.dst_rect.y = y;
+                ov.dst_rect.w = w;
+                ov.dst_rect.h = h;
+                if (ioctl(fd, MSMFB_OVERLAY_SET, &ov)) {
+                    LOGE("set position failed");
+                    return ret;
+                }
+            }
+            mOVInfo = ov;
+            return NO_ERROR;
+        }
+        return ret;
+    }
+
+    return NO_INIT;
+}
+
+status_t OVHelper::getOVInfo(mdp_overlay& ovInfo) {
+    if (mSessionID == NO_INIT)
+        return NO_INIT;
+    ovInfo = mOVInfo;
+    return NO_ERROR;
+}
+
+status_t Rotator::startRotSession(msm_rotator_img_info& rotInfo,
+                                   int size, int numBuffers) {
+    status_t ret = ALREADY_EXISTS;
+    if (mSessionID == NO_INIT && mFD == NO_INIT) {
+        mNumBuffers = numBuffers;
+        mFD = open("/dev/msm_rotator", O_RDWR, 0);
+        if (mFD < 0) {
+            LOGE("Couldnt open rotator device");
+            return NO_INIT;
+        }
+
+        if (int check = ioctl(mFD, MSM_ROTATOR_IOCTL_START, &rotInfo)) {
+            close(mFD);
+            mFD = NO_INIT;
+            return NO_INIT;
+        }
+
+#ifdef USE_ION
+        alloc_data data;
+        data.base = 0;
+        data.fd = -1;
+        data.offset = 0;
+        data.size = mSize * mNumBuffers;
+        data.align = getpagesize();
+        data.uncached = true;
+
+        int err = mAlloc->allocate(data, GRALLOC_USAGE_PRIVATE_ADSP_HEAP|
+                                         GRALLOC_USAGE_PRIVATE_SMI_HEAP, 0);
+
+        if(err) {
+            LOGE("Cant allocate from ION");
+            closeRotSession();
+            return NO_INIT;
+        }
+        mPmemFD = data.fd;
+        mPmemAddr = data.base;
+        mBufferType = data.allocType;
+#else
+        mSessionID = rotInfo.session_id;
+        mPmemFD = open("/dev/pmem_adsp", O_RDWR | O_SYNC);
+        if (mPmemFD < 0) {
+            closeRotSession();
+            return NO_INIT;
+        }
+
+        mSize = size;
+        mPmemAddr = (void *) mmap(NULL, mSize* mNumBuffers, PROT_READ | PROT_WRITE,
+                                                     MAP_SHARED, mPmemFD, 0);
+        if (mPmemAddr == MAP_FAILED) {
+            closeRotSession();
+            return NO_INIT;
+        }
+#endif
+
+        mCurrentItem = 0;
+        for (int i = 0; i < mNumBuffers; i++)
+            mRotOffset[i] = i * mSize;
+        ret = NO_ERROR;
+    }
+
+    return ret;
+}
+
+status_t Rotator::closeRotSession() {
+    if (mSessionID != NO_INIT && mFD != NO_INIT) {
+        ioctl(mFD, MSM_ROTATOR_IOCTL_FINISH, &mSessionID);
+        close(mFD);
+#ifdef USE_ION
+        sp<IMemAlloc> memalloc = mAlloc->getAllocator(mBufferType);
+        memalloc->free_buffer(mPmemAddr, mSize * mNumBuffers, 0, mPmemFD);
+#else
+        munmap(mPmemAddr, mSize * mNumBuffers);
+        close(mPmemFD);
+#endif
+        close(mPmemFD);
+    }
+
+    mFD = NO_INIT;
+    mSessionID = NO_INIT;
+    mPmemFD = NO_INIT;
+    mPmemAddr = MAP_FAILED;
+
+    return NO_ERROR;
+}
+
+status_t Rotator::rotateBuffer(msm_rotator_data_info& rotData) {
+    status_t ret = NO_INIT;
+    if (mSessionID != NO_INIT) {
+        rotData.dst.memory_id = mPmemFD;
+        rotData.dst.offset = mRotOffset[mCurrentItem];
+        rotData.session_id = mSessionID;
+        mCurrentItem = (mCurrentItem + 1) % mNumBuffers;
+        if (ioctl(mFD, MSM_ROTATOR_IOCTL_ROTATE, &rotData)) {
+            LOGE("Rotator failed to rotate");
+            return BAD_VALUE;
+        }
+        return NO_ERROR;
+    }
+
+    return ret;
+}
+
+status_t OverlayUI::closeChannel() {
+    mobjOVHelper.closeOVSession();
+    mobjRotator.closeRotSession();
+    mChannelState = CLOSED;
+    return NO_ERROR;
+}
+
+status_t OverlayUI::setSource(const overlay_buffer_info& info, int orientation,
+                                             bool useVGPipe, bool ignoreFB,
+                                             int fbnum, int zorder) {
+    status_t ret = NO_INIT;
+
+    int format3D = FORMAT_3D(info.format);
+    int colorFormat = COLOR_FORMAT(info.format);
+    int format = get_mdp_format(colorFormat);
+
+    if (format3D || !isRGBType(format))
+        return ret;
+
+    if (mChannelState == PENDING_CLOSE)
+        closeChannel();
+
+    if (mChannelState == UP) {
+        mdp_overlay ov;
+        if (mobjOVHelper.getOVInfo(ov) == NO_ERROR) {
+            if (mOrientation == orientation &&
+                   mFBNum == fbnum &&
+                   checkOVState(info.width, info.height, format, orientation, zorder, ov))
+                return NO_ERROR;
+            else
+                mChannelState = PENDING_CLOSE;
+        }
+        else
+            mChannelState = PENDING_CLOSE;
+        return ret;
+    }
+
+    mOrientation = orientation;
+    mdp_overlay ovInfo;
+    msm_rotator_img_info rotInfo;
+    setupOvRotInfo(info.width, info.height, format, orientation, ovInfo, rotInfo);
+
+    int flags = 0;
+    if (ignoreFB)
+        ovInfo.is_fg = 1;
+    else
+        flags |= MDP_OV_PLAY_NOWAIT;
+
+    if (turnOFFVSync())
+        flags |= MDP_OV_PLAY_NOWAIT;
+
+    if (useVGPipe ||
+          (fbnum == FB0 && getRGBBpp(format) != mobjOVHelper.getFBBpp()))
+        flags |= MDP_OV_PIPE_SHARE;
+
+    ovInfo.flags = flags;
+    if (zorder != NO_INIT)
+        ovInfo.z_order = zorder;
+
+    ret = startChannel(fbnum, ovInfo, rotInfo, info.size);
+    return ret;
+}
+
+status_t OverlayUI::startChannel(int fbnum, mdp_overlay& ovInfo,
+                                 msm_rotator_img_info& rotInfo, int size) {
+    status_t ret = BAD_VALUE;
+    if (mChannelState == UP)
+        return ret;
+
+    ret = mobjOVHelper.startOVSession(ovInfo, fbnum);
+    if (ret == NO_ERROR && mOrientation) {
+        ret = mobjRotator.startRotSession(rotInfo, size);
+    }
+
+    if (ret == NO_ERROR) {
+        mChannelState = UP;
+        mFBNum = fbnum;
+    }
+    else
+        LOGE("start channel failed.");
+
+    return ret;
+}
+
+status_t OverlayUI::queueBuffer(buffer_handle_t buffer) {
+    status_t ret = NO_INIT;
+
+    if (mChannelState != UP)
+        return ret;
+
+    msmfb_overlay_data ovData;
+    memset(&ovData, 0, sizeof(ovData));
+
+    private_handle_t const* hnd = reinterpret_cast
+                                        <private_handle_t const*>(buffer);
+    ovData.data.memory_id = hnd->fd;
+    ovData.data.offset = hnd->offset;
+    if (mOrientation) {
+        msm_rotator_data_info rotData;
+        memset(&rotData, 0, sizeof(rotData));
+        rotData.src.memory_id = hnd->fd;
+        rotData.src.offset = hnd->offset;
+        if (mobjRotator.rotateBuffer(rotData) != NO_ERROR) {
+            LOGE("Rotator failed.. ");
+            return BAD_VALUE;
+        }
+        ovData.data.memory_id = rotData.dst.memory_id;
+        ovData.data.offset = rotData.dst.offset;
+    }
+
+    ret = mobjOVHelper.queueBuffer(ovData);
+    if (ret != NO_ERROR)
+        LOGE("Queuebuffer failed ");
+
+    return ret;
+}
+
+};
diff --git a/liboverlay/overlayLibUI.h b/liboverlay/overlayLibUI.h
new file mode 100644
index 0000000..2cb1ffe
--- /dev/null
+++ b/liboverlay/overlayLibUI.h
@@ -0,0 +1,160 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef INCLUDE_OVERLAY_LIB_UI
+#define INCLUDE_OVERLAY_LIB_UI
+
+#include <errno.h>
+
+#include "overlayLib.h"
+
+namespace overlay {
+
+enum channel_state_t { UP, CLOSED, PENDING_CLOSE };
+enum status_t {
+                  NO_ERROR,
+                  INVALID_OPERATION = -ENOSYS,
+                  BAD_VALUE = -EINVAL,
+                  NO_INIT = -ENODEV,
+                  ALREADY_EXISTS = -EEXIST
+              };
+
+/*
+ * Display class provides following services
+ * Open FB
+ * FB information (Width, Height and Bpp)
+ */
+
+class Display {
+    int mFD;
+    int mFBWidth;
+    int mFBHeight;
+    int mFBBpp;
+    Display(const Display& objDisplay);
+    Display& operator=(const Display& objDisplay);
+
+public:
+    explicit Display() : mFD(NO_INIT) { };
+    ~Display() { close(mFD); };
+    int getFD() const { return mFD; };
+    int getFBWidth() const { return mFBWidth; };
+    int getFBHeight() const { return mFBHeight; };
+    int getFBBpp() const { return mFBBpp; };
+    status_t openDisplay(int fbnum);
+    void closeDisplay() { close(mFD); mFD = NO_INIT; };
+};
+
+/*
+ * OVHelper class, provides apis related to Overlay
+ * It communicates with MDP driver, provides following services
+ * Start overlay session
+ * Set position of the destination on to display
+ */
+
+class OVHelper {
+    int mSessionID;
+    Display mobjDisplay;
+    mdp_overlay mOVInfo;
+    OVHelper(const OVHelper& objOVHelper);
+    OVHelper& operator=(const OVHelper& objOVHelper);
+
+public:
+    explicit OVHelper() : mSessionID(NO_INIT) { };
+    ~OVHelper() { closeOVSession(); };
+    status_t startOVSession(mdp_overlay& ovInfo, int fbnum);
+    status_t closeOVSession();
+    status_t queueBuffer(msmfb_overlay_data ovData);
+    int getFBWidth() const { return mobjDisplay.getFBWidth(); };
+    int getFBHeight() const { return mobjDisplay.getFBHeight(); };
+    int getFBBpp() const { return mobjDisplay.getFBBpp(); };
+    status_t setPosition(int x, int y, int w, int h);
+    status_t getOVInfo(mdp_overlay& ovInfo);
+};
+
+/*
+ * Rotator class, manages rotation of the buffers
+ * It communicates with Rotator driver, provides following services
+ * Start rotator session
+ * Rotate buffer
+ */
+
+class Rotator {
+    int mFD;
+    int mSessionID;
+    int mPmemFD;
+    void* mPmemAddr;
+    int mRotOffset[max_num_buffers];
+    int mCurrentItem;
+    int mNumBuffers;
+    int mSize;
+    android::sp<gralloc::IAllocController> mAlloc;
+    int mBufferType;
+    Rotator(const Rotator& objROtator);
+    Rotator& operator=(const Rotator& objRotator);
+
+public:
+    explicit Rotator() : mFD(NO_INIT), mSessionID(NO_INIT), mPmemFD(-1)
+    {
+#ifdef USE_ION
+        mAlloc = gralloc::IAllocController::getInstance();
+#endif
+    }
+    ~Rotator() { closeRotSession(); }
+    status_t startRotSession(msm_rotator_img_info& rotInfo, int size,
+                             int numBuffers = max_num_buffers);
+    status_t closeRotSession();
+    status_t rotateBuffer(msm_rotator_data_info& rotData);
+};
+
+/*
+ * Overlay class for Comp. Bypass
+ * We merge control and data channel classes.
+ */
+
+class OverlayUI {
+    channel_state_t mChannelState;
+    int mOrientation;
+    int mFBNum;
+    OVHelper mobjOVHelper;
+    Rotator mobjRotator;
+
+    OverlayUI(const OverlayUI& objOverlay);
+    OverlayUI& operator=(const OverlayUI& objOverlay);
+
+    status_t startChannel(int fbnum, mdp_overlay& ovInfo,
+                               msm_rotator_img_info& rotInfo, int size);
+public:
+
+    enum fbnum_t { FB0, FB1 };
+
+    explicit OverlayUI() : mChannelState(CLOSED), mOrientation(NO_INIT), mFBNum(NO_INIT) { };
+    ~OverlayUI() { closeChannel(); };
+    status_t setSource(const overlay_buffer_info& info, int orientation,
+                          bool useVGPipe = false, bool ignoreFB = true,
+                          int fbnum = FB0, int zorder = NO_INIT);
+    status_t setPosition(int x, int y, int w, int h) {
+        return mobjOVHelper.setPosition(x, y, w, h);
+    };
+    status_t closeChannel();
+    channel_state_t isChannelUP() const { return mChannelState; };
+    int getFBWidth() const { return mobjOVHelper.getFBWidth(); };
+    int getFBHeight() const { return mobjOVHelper.getFBHeight(); };
+    status_t queueBuffer(buffer_handle_t buffer);
+};
+
+};
+#endif
diff --git a/liboverlay/overlayState.cpp b/liboverlay/overlayState.cpp
new file mode 100644
index 0000000..f4398d4
--- /dev/null
+++ b/liboverlay/overlayState.cpp
@@ -0,0 +1,1109 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * Copyright (c) 2009 - 2011, Code Aurora Forum. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+int setParameterHandleState(overlay_control_context_t *ctx,
+        overlay_object *obj,
+        int param, int value)
+{
+    switch (ctx->state) {
+        case OV_2D_VIDEO_ON_PANEL:
+        case OV_3D_VIDEO_2D_PANEL:
+            if(!obj->setParameter(param, value, VG0_PIPE)) {
+                LOGE("%s: Failed for channel 0", __func__);
+                return -1;
+            }
+            break;
+        case OV_2D_VIDEO_ON_TV:
+        case OV_3D_VIDEO_2D_TV:
+        case OV_3D_VIDEO_3D_TV:
+        case OV_3D_VIDEO_3D_PANEL:
+            for (int i=0; i<NUM_CHANNELS; i++) {
+                if(!obj->setParameter(param, value, i)) {
+                    LOGE("%s: Failed for channel %d", __func__, i);
+                    return -1;
+                }
+            }
+            break;
+        default:
+            LOGE("Unknown state in setParameter");
+            abort();
+            break;
+    }
+    return 0;
+}
+
+int createOverlayHandleState(overlay_control_context_t *ctx, bool noRot,
+        overlay_object* overlay, int fd)
+{
+    switch (ctx->state) {
+        case OV_2D_VIDEO_ON_PANEL:
+        case OV_3D_VIDEO_2D_PANEL:
+            if (!overlay->startControlChannel(FRAMEBUFFER_0, noRot)) {
+                error_cleanup_control(ctx, overlay, fd, FRAMEBUFFER_0);
+                return -1;
+            }
+            break;
+        case OV_3D_VIDEO_3D_PANEL:
+            for (int i=0; i<NUM_CHANNELS; i++) {
+                if (!overlay->startControlChannel(FRAMEBUFFER_0, noRot, i)) {
+                    error_cleanup_control(ctx, overlay, fd, i);
+                    return -1;
+                }
+            }
+            break;
+        case OV_2D_VIDEO_ON_TV:
+        case OV_3D_VIDEO_2D_TV:
+            if (!overlay->startControlChannel(FRAMEBUFFER_0, noRot, VG0_PIPE)) {
+                error_cleanup_control(ctx, overlay, fd, VG0_PIPE);
+                return -1;
+            }
+            if (!overlay->startControlChannel(FRAMEBUFFER_1, true, VG1_PIPE)) {
+                error_cleanup_control(ctx, overlay, fd, VG1_PIPE);
+                return -1;
+            }
+            break;
+        case OV_3D_VIDEO_3D_TV:
+            for (int i=0; i<NUM_CHANNELS; i++) {
+                if (!overlay->startControlChannel(FRAMEBUFFER_1, true, i)) {
+                    error_cleanup_control(ctx, overlay, fd, i);
+                    return -1;
+                }
+            }
+            break;
+        default:
+            break;
+    }
+    return 0;
+}
+
+int setPositionHandleState(overlay_control_context_t *ctx,
+        overlay_object *obj, overlay_rect& rect,
+        int x, int y, uint32_t w, uint32_t h)
+{
+    int ret = 0;
+    switch (ctx->state) {
+        case OV_2D_VIDEO_ON_PANEL:
+        case OV_3D_VIDEO_2D_PANEL:
+            if(!obj->setPosition(x, y, w, h, VG0_PIPE)) {
+                LOGE("%s:Failed for channel 0", __func__);
+                return -1;
+            }
+            break;
+        case OV_3D_VIDEO_3D_PANEL:
+            for (int i = 0; i < NUM_CHANNELS; i++) {
+                if (!obj->useVirtualFB(i)) {
+                    LOGE("can't use the virtual fb for line interleaving!");
+                }
+                obj->getPositionS3D(&rect, i, true);
+                if(!obj->setPosition(rect.x, rect.y, rect.w, rect.h, i)) {
+                    LOGE("%s:Failed for channel %d", __func__, i);
+                    return -1;
+                }
+            }
+            break;
+        case OV_2D_VIDEO_ON_TV:
+            obj->getAspectRatioPosition(&rect, VG1_PIPE);
+            if(!obj->setPosition(rect.x, rect.y, rect.w, rect.h, VG1_PIPE)) {
+                LOGE("%s:Failed for channel 1", __func__);
+            }
+            if(!obj->setPosition(x, y, w, h, VG0_PIPE)) {
+                LOGE("%s:Failed for channel 0", __func__);
+                return -1;
+            }
+            break;
+        case OV_3D_VIDEO_2D_TV:
+        case OV_3D_VIDEO_3D_TV:
+            for (int i = 0; i < NUM_CHANNELS; i++) {
+                if (!obj->getPositionS3D(&rect, i))
+                    ret = obj->setPosition(x, y, w, h, i);
+                else
+                    ret = obj->setPosition(rect.x, rect.y, rect.w, rect.h, i);
+                if (!ret) {
+                    LOGE("%s:Failed for channel %d", __func__, i);
+                    return -1;
+                }
+            }
+            break;
+        default:
+            break;
+    }
+    return ret;
+}
+
+////////////////////////  configPipes ///////////////////////////////////
+
+/////////////////////////////////////////////////////////////////////////////////////
+
+bool TV2Dconn(overlay_control_context_t *ctx,
+        overlay_object *obj, bool noRot,
+        overlay_rect& rect)
+{
+    LOGI("2D TV connected, Open a new control channel for TV.");
+    //Start a new channel for mirroring on HDMI
+    if (!obj->startControlChannel(FRAMEBUFFER_1, true, VG1_PIPE)) {
+        obj->closeControlChannel(VG1_PIPE);
+        return false;
+    }
+    if (ctx->format3D)
+        obj->getPositionS3D(&rect, FRAMEBUFFER_1);
+    else
+        obj->getAspectRatioPosition(&rect, FRAMEBUFFER_1);
+    if(!obj->setPosition(rect.x, rect.y, rect.w, rect.h, FRAMEBUFFER_1)) {
+        LOGE("%s:Failed to set position for framebuffer 1", __func__);
+        return false;
+    }
+    return true;
+}
+
+bool TV3Dconn(overlay_control_context_t *ctx,
+        overlay_object *obj, bool noRot,
+        overlay_rect& rect)
+{
+    LOGI("3D TV connected, close old ctl channel and open two ctl channels for 3DTV.");
+    //close the channel 0 as it is configured for panel
+    obj->closeControlChannel(VG0_PIPE);
+    //update the output from monoscopic to stereoscopic
+    ctx->format3D = FORMAT_3D_INPUT(ctx->format3D) | ctx->format3D >> SHIFT_3D;
+    obj->setFormat3D(ctx->format3D);
+    LOGI("Control: new S3D format : 0x%x", ctx->format3D);
+    //now open both the channels
+    for (int i = 0; i < NUM_CHANNELS; i++) {
+        if (!obj->startControlChannel(FRAMEBUFFER_1, true, i)) {
+            LOGE("%s:Failed to open control channel for pipe %d", __func__, i);
+            return false;
+        }
+        obj->getPositionS3D(&rect, i);
+        if(!obj->setPosition(rect.x, rect.y, rect.w, rect.h, i)) {
+            LOGE("%s: failed for channel %d", __func__, i);
+            return false;
+        }
+    }
+    return true;
+}
+
+bool TV3DSetup(overlay_control_context_t *ctx, overlay_object *obj, int i,
+        int fbnum, overlay_rect& rect)
+{
+    bool noRot = fbnum ? true : false;
+    if (!obj->startControlChannel(fbnum, noRot, i)) {
+        LOGE("%s:Failed to open control channel for pipe %d", __func__, i);
+        return false;
+    }
+    bool ret=true;
+    if (!obj->getPositionS3D(&rect, i))
+        ret = obj->setPosition(ctx->posPanel.x, ctx->posPanel.y,
+                ctx->posPanel.w, ctx->posPanel.h, i);
+    else
+        ret = obj->setPosition(rect.x, rect.y, rect.w, rect.h, i);
+    if(!ret) {
+        LOGE("%s: failed for channel %d", __func__, i);
+        return false;
+    }
+    return true;
+}
+
+int configPipes_OV_2D_VIDEO_ON_PANEL_to_OV_2D_VIDEO_ON_TV (overlay_control_context_t *ctx,
+        overlay_object *obj,
+        unsigned int newState,
+        int enable, bool noRot,
+        overlay_rect& rect)
+{
+    if(enable) // HDMI connected
+    {
+        if(!TV2Dconn(ctx, obj, noRot, rect))
+            return -1;
+        return 0;
+    }
+    LOGE("%s Error cannot disconnect HDMI in that state", __func__);
+    abort();
+    return -1;
+}
+
+int configPipes_OV_3D_VIDEO_2D_PANEL_to_OV_3D_VIDEO_2D_TV (overlay_control_context_t *ctx,
+        overlay_object *obj,
+        unsigned int newState,
+        int enable, bool noRot,
+        overlay_rect& rect)
+{
+    // same as OV_2D_VIDEO_ON_PANEL_to_OV_2D_VIDEO_ON_TV
+    return configPipes_OV_2D_VIDEO_ON_PANEL_to_OV_2D_VIDEO_ON_TV(ctx,
+            obj,
+            newState,
+            enable, noRot, rect);
+}
+
+int configPipes_OV_3D_VIDEO_2D_PANEL_to_OV_3D_VIDEO_3D_TV (overlay_control_context_t *ctx,
+        overlay_object *obj,
+        unsigned int newState,
+        int enable, bool noRot,
+        overlay_rect& rect)
+{
+    if(enable) // HDMI connected
+    {
+        if(!TV3Dconn(ctx, obj, noRot, rect))
+            return -1;
+        return 0;
+    }
+    // HDMI disconnected
+    LOGE("%s Error cannot disconnect HDMI in that state", __func__);
+    abort();
+    return -1;
+}
+
+int configPipes_OV_3D_VIDEO_3D_PANEL_to_OV_3D_VIDEO_2D_TV (overlay_control_context_t *ctx,
+        overlay_object *obj,
+        unsigned int newState,
+        int enable, bool noRot,
+        overlay_rect& rect)
+{
+    if(!enable){ // HDMI disconnect
+        LOGE("%s Error cannot disconnect HDMI in that state", __func__);
+        abort();
+        return -1;
+    }
+    obj->closeControlChannel(VG1_PIPE);
+    obj->closeControlChannel(VG0_PIPE);
+    //disable the panel barriers
+    enableBarrier(0);
+    //now open both the channels
+    //update the output from stereoscopic to monoscopic
+    ctx->format3D = FORMAT_3D_INPUT(ctx->format3D) | HAL_3D_OUT_MONOSCOPIC_MASK;
+    obj->setFormat3D(ctx->format3D);
+    LOGI("Control: new S3D format : 0x%x", ctx->format3D);
+    int fbnum = 0;
+    bool ret = true;
+    //now open both the channels
+    for (int i = 0; i < NUM_CHANNELS; i++) {
+        fbnum = i;
+        if(!TV3DSetup(ctx, obj, i, fbnum, rect))
+            return -1;
+    }
+    return 0;
+}
+
+int configPipes_OV_3D_VIDEO_3D_PANEL_to_OV_3D_VIDEO_3D_TV (overlay_control_context_t *ctx,
+        overlay_object *obj,
+        unsigned int newState,
+        int enable, bool noRot,
+        overlay_rect& rect)
+{
+    if(!enable){ // HDMI disconnect
+        LOGE("%s Error cannot disconnect HDMI in that state", __func__);
+        abort();
+        return -1;
+    }
+    obj->closeControlChannel(VG1_PIPE);
+    obj->closeControlChannel(VG0_PIPE);
+    //disable the panel barrier
+    enableBarrier(0);
+    //now open both the channels
+    for (int i = 0; i < NUM_CHANNELS; i++) {
+        if(!TV3DSetup(ctx, obj, i, FRAMEBUFFER_1, rect))
+            return -1;
+    }
+    return 0;
+}
+
+
+///// HDMI Disconnect ////
+int configPipes_OV_2D_VIDEO_ON_TV_to_OV_2D_VIDEO_ON_PANEL (overlay_control_context_t *ctx,
+        overlay_object *obj,
+        unsigned int newState,
+        int enable, bool noRot,
+        overlay_rect& rect)
+{
+    if(enable) // HDMI connected
+    {
+        LOGE("%s Error cannot connect HDMI in that state", __func__);
+        abort();
+        return -1;
+    }
+    LOGI("2D TV disconnected, close the control channel.");
+    obj->closeControlChannel(VG1_PIPE);
+    return 0;
+}
+
+int configPipes_OV_3D_VIDEO_2D_TV_to_OV_3D_VIDEO_2D_PANEL (overlay_control_context_t *ctx,
+        overlay_object *obj,
+        unsigned int newState,
+        int enable, bool noRot,
+        overlay_rect& rect)
+{
+    // same as OV_2D_VIDEO_ON_TV_to_OV_2D_VIDEO_ON_PANEL
+    return configPipes_OV_2D_VIDEO_ON_TV_to_OV_2D_VIDEO_ON_PANEL(ctx,
+            obj,
+            newState,
+            enable, noRot, rect);
+}
+
+int configPipes_OV_3D_VIDEO_3D_TV_to_OV_3D_VIDEO_2D_PANEL(overlay_control_context_t *ctx,
+        overlay_object *obj,
+        unsigned int newState,
+        int enable, bool noRot,
+        overlay_rect& rect)
+{
+    if(enable) // HDMI connected
+    {
+        LOGE("%s Error cannot connect HDMI in that state", __func__);
+        abort();
+        return -1;
+    }
+    LOGI("3D TV disconnected, close the control channels & open one for panel.");
+    // Close both the pipes' control channel
+    obj->closeControlChannel(VG1_PIPE);
+    obj->closeControlChannel(VG0_PIPE);
+    //update the format3D as monoscopic
+    ctx->format3D = FORMAT_3D_INPUT(ctx->format3D) | HAL_3D_OUT_MONOSCOPIC_MASK;
+    obj->setFormat3D(ctx->format3D);
+    LOGI("Control: New format3D: 0x%x", ctx->format3D);
+    //now open the channel 0
+    if (!obj->startControlChannel(FRAMEBUFFER_0, noRot)) {
+        LOGE("%s:Failed to open control channel for pipe 0", __func__);
+        return false;
+    }
+    if(!obj->setPosition(ctx->posPanel.x, ctx->posPanel.y,
+                ctx->posPanel.w, ctx->posPanel.h, FRAMEBUFFER_0)) {
+        LOGE("%s:Failed to set position for framebuffer 0", __func__);
+        return false;
+    }
+    if (!obj->setParameter(OVERLAY_TRANSFORM, ctx->orientation, VG0_PIPE)) {
+        LOGE("%s: Failed to set orientation for channel 0", __func__);
+        return -1;
+    }
+    return 0;
+}
+
+int TVto3DPanel(overlay_control_context_t *ctx, overlay_object *obj,
+        bool noRot, overlay_rect& rect)
+{
+    for (int i = 0; i < NUM_CHANNELS; i++) {
+        if (!obj->startControlChannel(FRAMEBUFFER_0, noRot, i)) {
+            LOGE("%s:Failed to open control channel for pipe %d", __func__, i);
+            return false;
+        }
+        if (!obj->useVirtualFB(i)) {
+            LOGE("can't use the virtual fb for line interleaving!");
+        }
+        obj->getPositionS3D(&rect, i);
+        if(!obj->setPosition(rect.x, rect.y, rect.w, rect.h, i)) {
+            LOGE("%s:Failed for channel %d", __func__, i);
+            return -1;
+        }
+        if (!obj->setParameter(OVERLAY_TRANSFORM, ctx->orientation, i)) {
+            LOGE("%s: Failed to set orientation for channel 0", __func__);
+            return -1;
+        }
+    }
+    return 0;
+}
+
+int configPipes_OV_3D_VIDEO_2D_TV_to_OV_3D_VIDEO_3D_PANEL(overlay_control_context_t *ctx,
+        overlay_object *obj,
+        unsigned int newState,
+        int enable, bool noRot,
+        overlay_rect& rect)
+{
+    if(enable) { // HDMI connect
+        LOGE("%s Error cannot connect HDMI in that state", __func__);
+        abort();
+        return -1;
+    }
+    // disconnect TV
+    // Close both the pipes' control channel
+    obj->closeControlChannel(VG0_PIPE);
+    obj->closeControlChannel(VG1_PIPE);
+    //update the output from monoscopic to stereoscopic
+    ctx->format3D = FORMAT_3D_INPUT(ctx->format3D) | ctx->format3D >> SHIFT_3D;
+    obj->setFormat3D(ctx->format3D);
+    LOGI("Control: new S3D format : 0x%x", ctx->format3D);
+    return TVto3DPanel(ctx, obj, noRot, rect);
+}
+
+int configPipes_OV_3D_VIDEO_3D_TV_to_OV_3D_VIDEO_3D_PANEL(overlay_control_context_t *ctx,
+        overlay_object *obj,
+        unsigned int newState,
+        int enable, bool noRot,
+        overlay_rect& rect)
+{
+    if(enable) { // HDMI connect
+        LOGE("%s Error cannot connect HDMI in that state", __func__);
+        abort();
+        return -1;
+    }
+
+    // disconnect TV
+    // Close both the pipes' control channel
+    obj->closeControlChannel(VG0_PIPE);
+    obj->closeControlChannel(VG1_PIPE);
+    return TVto3DPanel(ctx, obj, noRot, rect);
+}
+
+
+//// On Panel ////
+
+int configPipes_OV_2D_VIDEO_ON_PANEL(overlay_control_context_t *ctx,
+        overlay_object *obj,
+        unsigned int newState,
+        int enable, bool noRot,
+        overlay_rect& rect)
+{
+    switch(newState){
+        case OV_2D_VIDEO_ON_PANEL:
+        case OV_3D_VIDEO_2D_PANEL:
+        case OV_3D_VIDEO_3D_PANEL:
+        case OV_3D_VIDEO_3D_TV:
+        case OV_3D_VIDEO_2D_TV:
+            LOGE("ctl: Error in handling OV_2D_VIDEO_ON_PANEL newstate=%d", newState);
+            abort();
+            return -1;
+            break;
+        case OV_2D_VIDEO_ON_TV:
+            LOGI("TV connected: open a new VG control channel");
+            if(-1 == configPipes_OV_2D_VIDEO_ON_PANEL_to_OV_2D_VIDEO_ON_TV(ctx,
+                        obj,
+                        newState,
+                        enable, noRot, rect))
+                return -1;
+            break;
+        default:
+            LOGE("%s Unknown state in configPipes %d", __func__, newState);
+            abort();
+            break;
+    }
+    return 0;
+}
+
+int configPipes_OV_3D_VIDEO_2D_PANEL(overlay_control_context_t *ctx,
+        overlay_object *obj,
+        unsigned int newState,
+        int enable, bool noRot,
+        overlay_rect& rect)
+{
+    switch(newState){
+        case OV_2D_VIDEO_ON_PANEL:
+        case OV_3D_VIDEO_2D_PANEL:
+        case OV_3D_VIDEO_3D_PANEL:
+        case OV_2D_VIDEO_ON_TV:
+            LOGE("Error in handling OV_3D_VIDEO_2D_PANEL newstate=%d", newState);
+            abort();
+            return -1;
+        case OV_3D_VIDEO_2D_TV:
+            if(-1 == configPipes_OV_3D_VIDEO_2D_PANEL_to_OV_3D_VIDEO_2D_TV(ctx,
+                        obj,
+                        newState,
+                        enable, noRot, rect))
+                return -1;
+            break;
+        case OV_3D_VIDEO_3D_TV:
+            if(-1 == configPipes_OV_3D_VIDEO_2D_PANEL_to_OV_3D_VIDEO_3D_TV(ctx,
+                        obj,
+                        newState,
+                        enable, noRot, rect))
+                return -1;
+            break;
+        default:
+            LOGE("%s Unknown state in configPipes %d", __func__, newState);
+            abort();
+    }
+    return 0;
+}
+
+int configPipes_OV_3D_VIDEO_3D_PANEL(overlay_control_context_t *ctx,
+        overlay_object *obj,
+        unsigned int newState,
+        int enable, bool noRot,
+        overlay_rect& rect)
+{
+    switch(newState){
+        case OV_2D_VIDEO_ON_PANEL:
+        case OV_3D_VIDEO_2D_PANEL:
+        case OV_3D_VIDEO_3D_PANEL:
+        case OV_2D_VIDEO_ON_TV:
+            LOGE("Error in handling OV_3D_VIDEO_3D_PANEL newstate=%d", newState);
+            abort();
+            return -1;
+        case OV_3D_VIDEO_2D_TV:
+            if(-1 == configPipes_OV_3D_VIDEO_3D_PANEL_to_OV_3D_VIDEO_2D_TV(ctx,
+                        obj,
+                        newState,
+                        enable, noRot, rect))
+                return -1;
+            break;
+        case OV_3D_VIDEO_3D_TV:
+            if(-1 == configPipes_OV_3D_VIDEO_3D_PANEL_to_OV_3D_VIDEO_3D_TV(ctx,
+                        obj,
+                        newState,
+                        enable, noRot, rect))
+                return -1;
+            break;
+        default:
+            LOGE("%s Unknown state in configPipes %d", __func__, newState);
+            abort();
+    }
+    return 0;
+}
+
+/// OV on TV ////
+
+int configPipes_OV_2D_VIDEO_ON_TV(overlay_control_context_t *ctx,
+        overlay_object *obj,
+        unsigned int newState,
+        int enable, bool noRot,
+        overlay_rect& rect)
+{
+    switch(newState){
+        case OV_2D_VIDEO_ON_PANEL:
+            if(-1 == configPipes_OV_2D_VIDEO_ON_TV_to_OV_2D_VIDEO_ON_PANEL(ctx,
+                        obj,
+                        newState,
+                        enable, noRot, rect))
+                return -1;
+            break;
+        case OV_3D_VIDEO_3D_PANEL:
+        case OV_3D_VIDEO_2D_PANEL:
+        case OV_3D_VIDEO_3D_TV:
+        case OV_3D_VIDEO_2D_TV:
+        case OV_2D_VIDEO_ON_TV:
+            LOGE("Error in handling OV_2D_VIDEO_ON_TV newstate=%d", newState);
+            abort();
+            return -1;
+        default:
+            LOGE("%s Unknown state in configPipes %d", __func__, newState);
+            abort();
+    }
+    return 0;
+}
+
+int configPipes_OV_3D_VIDEO_2D_TV(overlay_control_context_t *ctx,
+        overlay_object *obj,
+        unsigned int newState,
+        int enable, bool noRot,
+        overlay_rect& rect)
+{
+    switch(newState){
+        case OV_2D_VIDEO_ON_PANEL:
+        case OV_3D_VIDEO_3D_TV:
+        case OV_2D_VIDEO_ON_TV:
+        case OV_3D_VIDEO_2D_TV:
+            LOGE("Error in handling OV_3D_VIDEO_2D_TV newstate=%d", newState);
+            abort();
+            return -1;
+        case OV_3D_VIDEO_3D_PANEL:
+            if(-1 == configPipes_OV_3D_VIDEO_2D_TV_to_OV_3D_VIDEO_3D_PANEL(ctx,
+                        obj,
+                        newState,
+                        enable, noRot, rect))
+                break;
+        case OV_3D_VIDEO_2D_PANEL:
+            if(-1 == configPipes_OV_3D_VIDEO_2D_TV_to_OV_3D_VIDEO_2D_PANEL(ctx,
+                        obj,
+                        newState,
+                        enable, noRot, rect))
+                return -1;
+            break;
+        default:
+            LOGE("%s Unknown state in configPipes %d", __func__, newState);
+            abort();
+    }
+    return 0;
+}
+
+int configPipes_OV_3D_VIDEO_3D_TV(overlay_control_context_t *ctx,
+        overlay_object *obj,
+        unsigned int newState,
+        int enable, bool noRot,
+        overlay_rect& rect)
+{
+    switch(newState){
+        case OV_3D_VIDEO_2D_PANEL:
+            if(-1 == configPipes_OV_3D_VIDEO_3D_TV_to_OV_3D_VIDEO_2D_PANEL(ctx,
+                        obj,
+                        newState,
+                        enable, noRot, rect))
+                return -1;
+            break;
+        case OV_2D_VIDEO_ON_PANEL:
+        case OV_3D_VIDEO_3D_TV:
+        case OV_2D_VIDEO_ON_TV:
+        case OV_3D_VIDEO_2D_TV:
+            LOGE("Error in handling OV_3D_VIDEO_2D_TV newstate=%d", newState);
+            abort();
+            return -1;
+        case OV_3D_VIDEO_3D_PANEL:
+            if(-1 == configPipes_OV_3D_VIDEO_3D_TV_to_OV_3D_VIDEO_3D_PANEL(ctx,
+                        obj,
+                        newState,
+                        enable, noRot, rect))
+                return -1;
+            break;
+        default:
+            LOGE("%s Unknown state in configPipes %d", __func__, newState);
+            abort();
+    }
+    return 0;
+}
+
+
+//////////////////////////////////// Queue Buffer ///////////////////////////////////
+
+///////////////////////// Helper func ///////////////////////////////
+
+int queueBuffer_OV_2D_VIDEO_ON_PANEL_to_OV_2D_VIDEO_ON_TV(overlay_data_context_t *ctx,
+        overlay_shared_data* data)
+{
+    LOGI("2D TV connected, Open a new data channel for TV.");
+    //Start a new channel for mirroring on HDMI
+    ctx->pobjDataChannel[VG1_PIPE] = new OverlayDataChannel();
+    if (!ctx->pobjDataChannel[VG1_PIPE]->startDataChannel(
+                data->ovid[VG1_PIPE], data->rotid[VG1_PIPE], ctx->size,
+                FRAMEBUFFER_1, true)) {
+        delete ctx->pobjDataChannel[VG1_PIPE];
+        ctx->pobjDataChannel[VG1_PIPE] = NULL;
+        return -1;
+    }
+    if(!ctx->pobjDataChannel[VG1_PIPE]->setCrop(
+                ctx->cropRect.x,ctx->cropRect.y,
+                ctx->cropRect.w,ctx->cropRect.h)) {
+        LOGE("%s:failed to crop pipe 1", __func__);
+    }
+    //setting the srcFD
+    if (!ctx->pobjDataChannel[VG1_PIPE]->setFd(ctx->srcFD)) {
+        LOGE("%s: Failed to set fd for pipe 1", __func__);
+        return -1;
+    }
+    return 0;
+}
+
+int queueBuffer_OV_3D_VIDEO_2D_PANEL_to_OV_3D_VIDEO_2D_TV(overlay_data_context_t *ctx,
+        overlay_shared_data* data)
+{
+    LOGI("2D TV connected, Open a new data channel for TV.");
+    //Start a new channel for mirroring on HDMI
+    ctx->pobjDataChannel[VG1_PIPE] = new OverlayDataChannel();
+    if (!ctx->pobjDataChannel[VG1_PIPE]->startDataChannel(
+                data->ovid[VG1_PIPE], data->rotid[VG1_PIPE], ctx->size,
+                FRAMEBUFFER_1, true)) {
+        delete ctx->pobjDataChannel[VG1_PIPE];
+        ctx->pobjDataChannel[VG1_PIPE] = NULL;
+        return -1;
+    }
+    overlay_rect rect;
+    ctx->pobjDataChannel[VG1_PIPE]->getCropS3D(&ctx->cropRect, VG1_PIPE, ctx->format3D, &rect);
+    if (!ctx->pobjDataChannel[VG1_PIPE]->setCrop(rect.x, rect.y, rect.w, rect.h)) {
+        LOGE("%s: Failed to crop pipe 1", __func__);
+        return -1;
+    }
+    //setting the srcFD
+    if (!ctx->pobjDataChannel[VG1_PIPE]->setFd(ctx->srcFD)) {
+        LOGE("%s: Failed to set fd for pipe 1", __func__);
+        return -1;
+    }
+    return 0;
+}
+
+int queueBuffer_OV_3D_VIDEO_2D_PANEL_to_OV_3D_VIDEO_3D_TV(overlay_data_context_t *ctx,
+        overlay_shared_data* data)
+{
+    //close the channel 0 as it is configured for panel
+    ctx->pobjDataChannel[VG0_PIPE]->closeDataChannel();
+    delete ctx->pobjDataChannel[VG0_PIPE];
+    ctx->pobjDataChannel[VG0_PIPE] = NULL;
+    //update the output from monoscopic to stereoscopic
+    ctx->format3D = FORMAT_3D_INPUT(ctx->format3D) | ctx->format3D >> SHIFT_3D;
+    LOGI("Data: New S3D format : 0x%x", ctx->format3D);
+    //now open both the channels
+    overlay_rect rect;
+    for (int i = 0; i < NUM_CHANNELS; i++) {
+        ctx->pobjDataChannel[i] = new OverlayDataChannel();
+        if (!ctx->pobjDataChannel[i]->startDataChannel(
+                    data->ovid[i], data->rotid[i], ctx->size,
+                    FRAMEBUFFER_1, true)) {
+            error_cleanup_data(ctx, i);
+            return -1;
+        }
+        ctx->pobjDataChannel[i]->getCropS3D(&ctx->cropRect, i, ctx->format3D, &rect);
+        if (!ctx->pobjDataChannel[i]->setCrop(rect.x, rect.y, rect.w, rect.h)) {
+            LOGE("%s: Failed to crop pipe %d", __func__, i);
+            return -1;
+        }
+        if (!ctx->pobjDataChannel[i]->setFd(ctx->srcFD)) {
+            LOGE("%s: Failed to set fd for pipe %d", __func__, i);
+            return -1;
+        }
+    }
+    send3DInfoPacket(ctx->format3D & OUTPUT_MASK_3D);
+    return 0;
+}
+int queueBuffer_3D_to_2D_TV_common(overlay_data_context_t *ctx,
+        overlay_shared_data* data,
+        overlay_rect& rect,
+        int i, int fbnum)
+{
+    bool noRot = fbnum ? true : false;
+    ctx->pobjDataChannel[i] = new OverlayDataChannel();
+    if (!ctx->pobjDataChannel[i]->startDataChannel(
+            data->ovid[i], data->rotid[i], ctx->size, fbnum, noRot)) {
+        error_cleanup_data(ctx, i);
+        return -1;
+    }
+    ctx->pobjDataChannel[i]->getCropS3D(&ctx->cropRect, i, ctx->format3D, &rect);
+    if (!ctx->pobjDataChannel[i]->setCrop(rect.x, rect.y, rect.w, rect.h)) {
+        LOGE("%s: Failed to crop pipe %d", __func__, i);
+        return -1;
+    }
+    if (!ctx->pobjDataChannel[i]->setFd(ctx->srcFD)) {
+        LOGE("%s: Failed to set fd for pipe %d", __func__, i);
+        return -1;
+    }
+    return 0;
+}
+
+int queueBuffer_OV_3D_VIDEO_3D_PANEL_to_OV_3D_VIDEO_2D_TV(overlay_data_context_t *ctx,
+        overlay_shared_data* data)
+{
+    // Close both the pipes' data channel
+    for (int i = 0; i < NUM_CHANNELS; i++) {
+        ctx->pobjDataChannel[i]->closeDataChannel();
+        delete ctx->pobjDataChannel[i];
+        ctx->pobjDataChannel[i] = NULL;
+    }
+    //now open both the channels
+    overlay_rect rect;
+    for (int i = 0; i < NUM_CHANNELS; i++) {
+        int fbnum = i;
+        //update the output from stereoscopic to monoscopic
+       ctx->format3D = FORMAT_3D_INPUT(ctx->format3D) | HAL_3D_OUT_MONOSCOPIC_MASK;
+        LOGI("Data: New S3D format : 0x%x", ctx->format3D);
+        if(-1 == queueBuffer_3D_to_2D_TV_common(ctx, data, rect, i, fbnum))
+            return -1;
+    }
+    return 0;
+}
+
+int queueBuffer_OV_3D_VIDEO_3D_PANEL_to_OV_3D_VIDEO_3D_TV(overlay_data_context_t *ctx,
+        overlay_shared_data* data)
+{
+    // Close both the pipes' data channel
+    for (int i = 0; i < NUM_CHANNELS; i++) {
+        ctx->pobjDataChannel[i]->closeDataChannel();
+        delete ctx->pobjDataChannel[i];
+        ctx->pobjDataChannel[i] = NULL;
+    }
+    //now open both the channels
+    overlay_rect rect;
+    int fbnum = 1;
+    for (int i = 0; i < NUM_CHANNELS; i++) {
+        if(-1 == queueBuffer_3D_to_2D_TV_common(ctx, data, rect, i, fbnum))
+            return -1;
+    }
+    send3DInfoPacket(ctx->format3D & OUTPUT_MASK_3D);
+    return 0;
+}
+
+void queueBuffer_OV_2D_VIDEO_ON_TV_to_OV_2D_VIDEO_ON_PANEL(overlay_data_context_t *ctx)
+{
+    LOGI("2D TV disconnected, close the data channel for TV.");
+    ctx->pobjDataChannel[VG1_PIPE]->closeDataChannel();
+    delete ctx->pobjDataChannel[VG1_PIPE];
+    ctx->pobjDataChannel[VG1_PIPE] = NULL;
+}
+
+void queueBuffer_OV_3D_VIDEO_2D_TV_to_OV_3D_VIDEO_2D_PANEL(overlay_data_context_t *ctx)
+{
+    // same as queueBuffer_OV_2D_VIDEO_ON_TV_to_OV_2D_VIDEO_ON_PANEL
+    queueBuffer_OV_2D_VIDEO_ON_TV_to_OV_2D_VIDEO_ON_PANEL(ctx);
+}
+
+int queueBuffer_OV_3D_VIDEO_3D_TV_to_OV_3D_VIDEO_2D_PANEL(overlay_data_context_t *ctx,
+        overlay_shared_data* data, bool noRot)
+{
+    LOGI("3D TV disconnected, close the data channels for 3DTV and open one for panel.");
+    // Close both the pipes' data channel
+    for (int i = 0; i < NUM_CHANNELS; i++) {
+        ctx->pobjDataChannel[i]->closeDataChannel();
+        delete ctx->pobjDataChannel[i];
+        ctx->pobjDataChannel[i] = NULL;
+    }
+    send3DInfoPacket(0);
+    //update the format3D as monoscopic
+    ctx->format3D = FORMAT_3D_INPUT(ctx->format3D) | HAL_3D_OUT_MONOSCOPIC_MASK;
+    //now open the channel 0
+    ctx->pobjDataChannel[VG0_PIPE] = new OverlayDataChannel();
+    if (!ctx->pobjDataChannel[VG0_PIPE]->startDataChannel(
+                data->ovid[VG0_PIPE], data->rotid[VG0_PIPE], ctx->size,
+                FRAMEBUFFER_0, noRot)) {
+        error_cleanup_data(ctx, VG0_PIPE);
+        return -1;
+    }
+    overlay_rect rect;
+    ctx->pobjDataChannel[VG0_PIPE]->getCropS3D(&ctx->cropRect, VG0_PIPE,
+            ctx->format3D, &rect);
+    //setting the crop value
+    if(!ctx->pobjDataChannel[VG0_PIPE]->setCrop( rect.x, rect.y,rect.w, rect.h)) {
+        LOGE("%s:failed to crop pipe 0", __func__);
+    }
+    //setting the srcFD
+    if (!ctx->pobjDataChannel[VG0_PIPE]->setFd(ctx->srcFD)) {
+        LOGE("%s: Failed set fd for pipe 0", __func__);
+        return -1;
+    }
+    return 0;
+}
+
+void queueBuffer_3D_Panel_common_pre(overlay_data_context_t *ctx)
+{
+    // Close both the pipes' data channel
+    for (int i = 0; i < NUM_CHANNELS; i++) {
+        ctx->pobjDataChannel[i]->closeDataChannel();
+        delete ctx->pobjDataChannel[i];
+        ctx->pobjDataChannel[i] = NULL;
+    }
+    send3DInfoPacket(0);
+}
+
+
+int queueBuffer_3D_Panel_common_post(overlay_data_context_t *ctx,
+        overlay_shared_data* data,
+        bool noRot)
+{
+    overlay_rect rect;
+    for (int i = 0; i < NUM_CHANNELS; i++) {
+        ctx->pobjDataChannel[i] = new OverlayDataChannel();
+        if (!ctx->pobjDataChannel[i]->startDataChannel(
+                    data->ovid[i], data->rotid[i], ctx->size, FRAMEBUFFER_0, noRot)) {
+            error_cleanup_data(ctx, i);
+            return -1;
+        }
+        ctx->pobjDataChannel[i]->getCropS3D(&ctx->cropRect, i,
+                ctx->format3D, &rect);
+        if (!ctx->pobjDataChannel[i]->setCrop(rect.x, rect.y, rect.w, rect.h)) {
+            LOGE("%s: Failed to crop pipe %d", __func__, i);
+            return -1;
+        }
+        if (!ctx->pobjDataChannel[i]->setFd(ctx->srcFD)) {
+            LOGE("%s: Failed to set fd for pipe %d", __func__, i);
+            return -1;
+        }
+    }
+    return 0;
+}
+
+int queueBuffer_OV_3D_VIDEO_3D_TV_to_OV_3D_VIDEO_3D_PANEL(overlay_data_context_t *ctx,
+        overlay_shared_data* data,
+        bool noRot)
+{
+    queueBuffer_3D_Panel_common_pre(ctx);
+
+    if(-1 == queueBuffer_3D_Panel_common_post(ctx, data, noRot))
+        return -1;
+
+    return 0;
+}
+
+int queueBuffer_OV_3D_VIDEO_2D_TV_to_OV_3D_VIDEO_3D_PANEL(overlay_data_context_t *ctx,
+        overlay_shared_data* data,
+        bool noRot)
+{
+    queueBuffer_3D_Panel_common_pre(ctx);
+    ctx->format3D = FORMAT_3D_INPUT(ctx->format3D) |
+        ctx->format3D >> SHIFT_3D;
+    if(-1 == queueBuffer_3D_Panel_common_post(ctx, data, noRot))
+        return -1;
+
+    return 0;
+}
+
+////////////////// Queue buffer state machine handling /////////////////////
+
+int queueBuffer_OV_2D_VIDEO_ON_PANEL(overlay_data_context_t *ctx,
+        overlay_shared_data* data,
+        unsigned int newState, bool noRot)
+{
+    switch(newState){
+        case OV_2D_VIDEO_ON_PANEL:
+            // nothing to do here
+            break;
+        case OV_2D_VIDEO_ON_TV:
+            LOGI("TV connected, open a new data channel");
+            if(-1 == queueBuffer_OV_2D_VIDEO_ON_PANEL_to_OV_2D_VIDEO_ON_TV(ctx, data))
+                return -1;
+            break;
+        case OV_3D_VIDEO_2D_PANEL:
+        case OV_3D_VIDEO_3D_PANEL:
+        case OV_3D_VIDEO_2D_TV:
+        case OV_3D_VIDEO_3D_TV:
+            LOGE("data: Error in handling OV_2D_VIDEO_ON_PANEL newstate=%d", newState);
+            abort();
+            return -1;
+        default:
+            LOGE("%s Unknown state in queueBuffer %d", __func__, newState);
+            abort();
+    }
+
+    return 0;
+}
+
+int queueBuffer_OV_3D_VIDEO_2D_PANEL(overlay_data_context_t *ctx,
+        overlay_shared_data* data,
+        unsigned int newState, bool noRot)
+{
+    switch(newState){
+        case OV_3D_VIDEO_2D_PANEL:
+            // nothing to do here
+            break;
+        case OV_3D_VIDEO_2D_TV:
+            if(-1 == queueBuffer_OV_3D_VIDEO_2D_PANEL_to_OV_3D_VIDEO_2D_TV(ctx, data))
+                return -1;
+            break;
+        case OV_3D_VIDEO_3D_TV:
+            if(-1 == queueBuffer_OV_3D_VIDEO_2D_PANEL_to_OV_3D_VIDEO_3D_TV(ctx, data))
+                return -1;
+            break;
+        case OV_2D_VIDEO_ON_PANEL:
+        case OV_3D_VIDEO_3D_PANEL:
+        case OV_2D_VIDEO_ON_TV:
+            LOGE("Error in handling OV_3D_VIDEO_2D_PANEL newstate=%d", newState);
+            abort();
+            return -1;
+        default:
+            LOGE("%s Unknown state in queueBuffer %d", __func__, newState);
+            abort();
+    }
+
+    return 0;
+}
+
+int queueBuffer_OV_3D_VIDEO_3D_PANEL(overlay_data_context_t *ctx,
+        overlay_shared_data* data,
+        unsigned int newState, bool noRot)
+{
+    switch(newState){
+        case OV_3D_VIDEO_3D_PANEL:
+            // nothing to do here
+            break;
+        case OV_2D_VIDEO_ON_PANEL:
+        case OV_3D_VIDEO_2D_PANEL:
+        case OV_2D_VIDEO_ON_TV:
+            LOGE("Error in handling OV_3D_VIDEO_3D_PANEL newstate=%d", newState);
+            abort();
+            return -1;
+        case OV_3D_VIDEO_2D_TV:
+            if(-1 == queueBuffer_OV_3D_VIDEO_3D_PANEL_to_OV_3D_VIDEO_2D_TV(ctx, data))
+                return -1;
+            break;
+        case OV_3D_VIDEO_3D_TV:
+            if(-1 == queueBuffer_OV_3D_VIDEO_3D_PANEL_to_OV_3D_VIDEO_3D_TV(ctx, data))
+                return -1;
+            break;
+        default:
+            LOGE("%s Unknown state in queueBuffer %d", __func__, newState);
+            abort();
+    }
+
+    return 0;
+}
+
+int queueBuffer_OV_2D_VIDEO_ON_TV(overlay_data_context_t *ctx,
+        overlay_shared_data* data,
+        unsigned int newState, bool noRot)
+{
+    switch(newState){
+        case OV_2D_VIDEO_ON_TV:
+            // nothing to see here
+            break;
+        case OV_2D_VIDEO_ON_PANEL:
+            queueBuffer_OV_2D_VIDEO_ON_TV_to_OV_2D_VIDEO_ON_PANEL(ctx);
+            break;
+        case OV_3D_VIDEO_2D_PANEL:
+        case OV_3D_VIDEO_3D_PANEL:
+        case OV_3D_VIDEO_2D_TV:
+        case OV_3D_VIDEO_3D_TV:
+            LOGE("Error in handling OV_2D_VIDEO_ON_TV newstate=%d", newState);
+            abort();
+            return -1;
+        default:
+            LOGE("%s Unknown state in queueBuffer %d", __func__, newState);
+            abort();
+    }
+
+    return 0;
+}
+
+int queueBuffer_OV_3D_VIDEO_2D_TV(overlay_data_context_t *ctx,
+        overlay_shared_data* data,
+        unsigned int newState, bool noRot)
+{
+    switch(newState){
+        case OV_3D_VIDEO_2D_TV:
+            // nothing to see here
+            break;
+        case OV_3D_VIDEO_2D_PANEL:
+            queueBuffer_OV_3D_VIDEO_2D_TV_to_OV_3D_VIDEO_2D_PANEL(ctx);
+            break;
+        case OV_3D_VIDEO_3D_PANEL:
+            if(-1 == queueBuffer_OV_3D_VIDEO_2D_TV_to_OV_3D_VIDEO_3D_PANEL(ctx, data, noRot))
+                return -1;
+            break;
+        case OV_2D_VIDEO_ON_PANEL:
+        case OV_2D_VIDEO_ON_TV:
+        case OV_3D_VIDEO_3D_TV:
+            LOGE("Error in handling OV_3D_VIDEO_2D_TV newstate=%d", newState);
+            abort();
+            return -1;
+        default:
+            LOGE("%s Unknown state in queueBuffer %d", __func__, newState);
+            abort();
+    }
+
+    return 0;
+}
+
+int queueBuffer_OV_3D_VIDEO_3D_TV(overlay_data_context_t *ctx,
+        overlay_shared_data* data,
+        unsigned int newState, bool noRot)
+{
+    switch(newState){
+        case OV_3D_VIDEO_3D_TV:
+            // nothing to see here
+            break;
+        case OV_3D_VIDEO_2D_PANEL:
+            if(-1 ==  queueBuffer_OV_3D_VIDEO_3D_TV_to_OV_3D_VIDEO_2D_PANEL(ctx, data, noRot))
+                return -1;
+            break;
+        case OV_3D_VIDEO_3D_PANEL:
+            if(-1 == queueBuffer_OV_3D_VIDEO_3D_TV_to_OV_3D_VIDEO_3D_PANEL(ctx, data, noRot))
+                return -1;
+            break;
+        case OV_2D_VIDEO_ON_PANEL:
+        case OV_2D_VIDEO_ON_TV:
+        case OV_3D_VIDEO_2D_TV:
+            LOGE("Error in handling OV_3D_VIDEO_3D_TV newstate=%d", newState);
+            abort();
+            return -1;
+        default:
+            LOGE("%s Unknown state in queueBuffer %d", __func__, newState);
+            abort();
+    }
+
+    return 0;
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////
+
+/////////////////////////////////////////////////////////////////////////////////////
+