msm8909: Populate display code for msm8x09

Copied from manifest tag LW.BR.1.0-00110-8x09w.0 for
LW.BR.1.0

Bug: 25691995
Change-Id: I42c50111d92ecbdc9198ce4f2a98c26300dfa715
diff --git a/Android.mk b/Android.mk
index 0b984bc..2c9d83a 100644
--- a/Android.mk
+++ b/Android.mk
@@ -14,6 +14,10 @@
 else
 ifneq ($(filter msm8994 msm8992,$(TARGET_BOARD_PLATFORM)),)
     include $(call all-named-subdir-makefiles,msm8994)
+else
+ifneq ($(filter msm8909,$(TARGET_BOARD_PLATFORM)),)
+    include $(call all-named-subdir-makefiles,msm8909)
+endif
 endif
 endif
 endif
diff --git a/msm8909/Android.mk b/msm8909/Android.mk
new file mode 100644
index 0000000..d8b168d
--- /dev/null
+++ b/msm8909/Android.mk
@@ -0,0 +1,10 @@
+display-hals := libgralloc libgenlock libcopybit liblight
+display-hals += libhwcomposer liboverlay libqdutils libhdmi libqservice
+display-hals += libmemtrack
+ifeq ($(call is-vendor-board-platform,QCOM),true)
+    include $(call all-named-subdir-makefiles,$(display-hals))
+else
+ifneq ($(filter msm% apq%,$(TARGET_BOARD_PLATFORM)),)
+    include $(call all-named-subdir-makefiles,$(display-hals))
+endif
+endif
diff --git a/msm8909/common.mk b/msm8909/common.mk
new file mode 100644
index 0000000..252de80
--- /dev/null
+++ b/msm8909/common.mk
@@ -0,0 +1,61 @@
+#Common headers
+common_includes := $(LOCAL_PATH)/../libgralloc
+common_includes += $(LOCAL_PATH)/../liboverlay
+common_includes += $(LOCAL_PATH)/../libcopybit
+common_includes += $(LOCAL_PATH)/../libqdutils
+common_includes += $(LOCAL_PATH)/../libhwcomposer
+common_includes += $(LOCAL_PATH)/../libhdmi
+common_includes += $(LOCAL_PATH)/../libqservice
+
+ifeq ($(TARGET_USES_POST_PROCESSING),true)
+    common_flags     += -DUSES_POST_PROCESSING
+    common_includes  += $(TARGET_OUT_HEADERS)/pp/inc
+endif
+
+common_header_export_path := qcom/display
+
+#Common libraries external to display HAL
+common_libs := liblog libutils libcutils libhardware
+
+#Common C flags
+common_flags := -DDEBUG_CALC_FPS -Wno-missing-field-initializers
+common_flags += -Wconversion -Wall -Werror
+
+ifeq ($(ARCH_ARM_HAVE_NEON),true)
+    common_flags += -D__ARM_HAVE_NEON
+endif
+
+ifeq ($(call is-board-platform-in-list, $(MSM_VIDC_TARGET_LIST)), true)
+    common_flags += -DVENUS_COLOR_FORMAT
+endif
+
+ifeq ($(call is-board-platform-in-list, msm8974 msm8226 msm8610 apq8084 \
+        mpq8092 msm_bronze msm8916 msm8994), true)
+    common_flags += -DMDSS_TARGET
+endif
+ifeq ($(call is-board-platform-in-list, msm8909), true)
+    common_flags += -DVENUS_COLOR_FORMAT
+    common_flags += -DMDSS_TARGET
+endif
+
+common_deps  :=
+kernel_includes :=
+
+# Executed only on QCOM BSPs
+ifeq ($(TARGET_USES_QCOM_BSP),true)
+# Enable QCOM Display features
+    common_flags += -DQTI_BSP
+    common_includes += vendor/qcom/opensource/display-frameworks/include
+endif
+ifneq ($(call is-platform-sdk-version-at-least,18),true)
+    common_flags += -DANDROID_JELLYBEAN_MR1=1
+endif
+ifeq ($(call is-vendor-board-platform,QCOM),true)
+# This check is to pick the kernel headers from the right location.
+# If the macro above is defined, we make the assumption that we have the kernel
+# available in the build tree.
+# If the macro is not present, the headers are picked from hardware/qcom/msmXXXX
+# failing which, they are picked from bionic.
+    common_deps += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr
+    kernel_includes += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr/include
+endif
diff --git a/msm8909/libcopybit/Android.mk b/msm8909/libcopybit/Android.mk
new file mode 100644
index 0000000..f6f7ed5
--- /dev/null
+++ b/msm8909/libcopybit/Android.mk
@@ -0,0 +1,48 @@
+# 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)
+include $(LOCAL_PATH)/../common.mk
+include $(CLEAR_VARS)
+
+LOCAL_COPY_HEADERS_TO         := $(common_header_export_path)
+LOCAL_COPY_HEADERS            := copybit.h copybit_priv.h c2d2.h
+#Copy the headers regardless of whether copybit is built
+include $(BUILD_COPY_HEADERS)
+
+LOCAL_MODULE                  := copybit.$(TARGET_BOARD_PLATFORM)
+LOCAL_MODULE_RELATIVE_PATH    := hw
+LOCAL_MODULE_TAGS             := optional
+LOCAL_C_INCLUDES              := $(common_includes) $(kernel_includes)
+LOCAL_SHARED_LIBRARIES        := $(common_libs) libdl libmemalloc
+LOCAL_CFLAGS                  := $(common_flags) -DLOG_TAG=\"qdcopybit\"
+LOCAL_ADDITIONAL_DEPENDENCIES := $(common_deps)
+
+ifeq ($(TARGET_USES_C2D_COMPOSITION),true)
+    LOCAL_CFLAGS += -DCOPYBIT_Z180=1 -DC2D_SUPPORT_DISPLAY=1
+    LOCAL_SRC_FILES := copybit_c2d.cpp software_converter.cpp
+    include $(BUILD_SHARED_LIBRARY)
+else
+    ifneq ($(call is-chipset-in-board-platform,msm7630),true)
+        ifeq ($(call is-board-platform-in-list,$(MSM7K_BOARD_PLATFORMS)),true)
+            LOCAL_CFLAGS += -DCOPYBIT_MSM7K=1
+            LOCAL_SRC_FILES := software_converter.cpp copybit.cpp
+            include $(BUILD_SHARED_LIBRARY)
+        endif
+        ifeq ($(call is-board-platform-in-list, msm8610 msm8909),true)
+            LOCAL_SRC_FILES := software_converter.cpp copybit.cpp
+            include $(BUILD_SHARED_LIBRARY)
+        endif
+    endif
+endif
diff --git a/msm8909/libcopybit/MODULE_LICENSE_APACHE2 b/msm8909/libcopybit/MODULE_LICENSE_APACHE2
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/msm8909/libcopybit/MODULE_LICENSE_APACHE2
diff --git a/msm8909/libcopybit/NOTICE b/msm8909/libcopybit/NOTICE
new file mode 100644
index 0000000..9c1e63a
--- /dev/null
+++ b/msm8909/libcopybit/NOTICE
@@ -0,0 +1,189 @@
+
+   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/msm8909/libcopybit/c2d2.h b/msm8909/libcopybit/c2d2.h
new file mode 100644
index 0000000..886f38a
--- /dev/null
+++ b/msm8909/libcopybit/c2d2.h
@@ -0,0 +1,683 @@
+/* Copyright (c) 2010-2013, The Linux Foundation. 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 The Linux Foundation. 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
+
+#ifndef C2D_API
+#define C2D_API /* define API export as needed */
+#endif
+#if !defined(int32) && !defined(_INT32_DEFINED)
+typedef int                     int32;
+#define _INT32_DEFINED
+#endif
+#if !defined(uint32) && !defined(_UINT32_DEFINED)
+typedef unsigned int            uint32;
+#define _UINT32_DEFINED
+#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 C2D_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;
+
+/* Configuration bits, used in the config_mask field of C2D_OBJECT struct */
+typedef enum {
+    C2D_OVERRIDE_GLOBAL_TARGET_ROTATE_CONFIG = (1 << 27), /* Overrides TARGET Config */
+    C2D_OVERRIDE_TARGET_ROTATE_0             = (0 << 28), /* no rotation             */
+    C2D_OVERRIDE_TARGET_ROTATE_90            = (1 << 28), /* 90 degree rotation      */
+    C2D_OVERRIDE_TARGET_ROTATE_180           = (2 << 28), /* 180 degree rotation     */
+    C2D_OVERRIDE_TARGET_ROTATE_270           = (3 << 28), /* 270 degree rotation     */
+} C2D_SOURCE_TARGET_CONFIG;
+
+#define C2D_OVERRIDE_SOURCE_CONFIG_TARGET_ROTATION_SHIFT_MASK  28
+#define C2D_OVERRIDE_TARGET_CONFIG_TARGET_ROTATION_SHIFT_MASK  2
+
+
+/* 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_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 already mapped */
+                                        /* this bit is valid with HOST types */
+    C2D_SURFACE_WITH_PHYS_DUMMY = (1<<4), /* physical address already mapped */
+                                        /* this bit is valid with HOST types */
+} C2D_SURFACE_TYPE;
+
+/* 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;
+
+/* Configuration bits, driver capabilities used by 2Dapplications */
+typedef enum {
+    C2D_DRIVER_SUPPORTS_GLOBAL_ALPHA_OP           = (1 << 0),
+    C2D_DRIVER_SUPPORTS_TILE_OP                   = (1 << 1),
+    C2D_DRIVER_SUPPORTS_COLOR_KEY_OP              = (1 << 2),
+    C2D_DRIVER_SUPPORTS_NO_PIXEL_ALPHA_OP         = (1 << 3),
+    C2D_DRIVER_SUPPORTS_TARGET_ROTATE_OP          = (1 << 4),
+    C2D_DRIVER_SUPPORTS_ANTI_ALIASING_OP          = (1 << 5), /* antialiasing */
+    C2D_DRIVER_SUPPORTS_BILINEAR_FILTER_OP        = (1 << 6),
+    C2D_DRIVER_SUPPORTS_LENS_CORRECTION_OP        = (1 << 7),
+    C2D_DRIVER_SUPPORTS_OVERRIDE_TARGET_ROTATE_OP = (1 << 8),
+    C2D_DRIVER_SUPPORTS_SHADER_BLOB_OP            = (1 << 9),
+    C2D_DRIVER_SUPPORTS_MASK_SURFACE_OP           = (1 << 10), /* mask surface */
+    C2D_DRIVER_SUPPORTS_MIRROR_H_OP               = (1 << 11), /* horizontal flip */
+    C2D_DRIVER_SUPPORTS_MIRROR_V_OP               = (1 << 12), /* vertical flip */
+    C2D_DRIVER_SUPPORTS_SCISSOR_RECT_OP           = (1 << 13),
+    C2D_DRIVER_SUPPORTS_SOURCE_RECT_OP            = (1 << 14),
+    C2D_DRIVER_SUPPORTS_TARGET_RECT_OP            = (1 << 15),
+    C2D_DRIVER_SUPPORTS_ROTATE_OP                 = (1 << 16), /* all rotations */
+    C2D_DRIVER_SUPPORTS_FLUSH_WITH_FENCE_FD_OP    = (1 << 17), /* all rotations */
+    C2D_DRIVER_SUPPORTS_ALL_CAPABILITIES_OP       = ((0xFFFFFFFF) >> (31 - 17)) /* mask for all capabilities supported */
+} C2D_DRIVER_CAPABILITIES;
+
+/* 2D driver workaround bits used by the 2D applications */
+typedef enum {
+    C2D_DRIVER_WORKAROUND_NONE  = 0, /* NO workaround */
+    C2D_DRIVER_WORKAROUND_SWAP_UV_FOR_YUV_TARGET  = (1 << 0), /* Swap UV when this flag set */
+} C2D_DRIVER_WORKAROUND;
+
+/* Structure to query Driver information */
+typedef struct {
+    uint32 capabilities_mask;
+    uint32 workaround_mask;
+    uint32 reserved1;
+    uint32 reserved2;
+    uint32 reserved3;
+} C2D_DRIVER_INFO;
+
+/* Structure to query Driver information */
+typedef struct {
+    uint32          max_surface_template_needed;
+    uint32          reserved1;
+    uint32          reserved2;
+    uint32          reserved3;
+} C2D_DRIVER_SETUP_INFO;
+
+/*****************************************************************************/
+/**************************** 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.
+
+ * 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);
+
+/* allows user to map a memory region to the gpu. only supported on linux
+ * mem_fd is the fd of the memory region, hostptr is the host pointer to the region,
+ * len and offset are the size and offset of the memory.
+ * flags is one of the memory types supported by gsl
+ * gpaddr is passed by refernce back to the user
+ */
+C2D_API C2D_STATUS c2dMapAddr ( int mem_fd, void * hostptr, uint32 len, uint32 offset, uint32 flags, void ** gpuaddr);
+
+/* allows user to unmap memory region mapped by c2dMapAddr.
+ * gpaddr is the gpuaddr to unmap */
+C2D_API C2D_STATUS c2dUnMapAddr (void * gpuaddr);
+
+/* allows user to query driver capabilities.
+ * driver_info is the information about driver */
+C2D_API C2D_STATUS c2dGetDriverCapabilities( C2D_DRIVER_INFO * driver_info);
+
+/* create a fence fd for the timestamp */
+C2D_API C2D_STATUS c2dCreateFenceFD( uint32 target_id, c2d_ts_handle timestamp, int32 *fd);
+
+/*****************************************************************************/
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __c2d2_h_ */
diff --git a/msm8909/libcopybit/copybit.cpp b/msm8909/libcopybit/copybit.cpp
new file mode 100644
index 0000000..b2d0d40
--- /dev/null
+++ b/msm8909/libcopybit/copybit.cpp
@@ -0,0 +1,787 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * Copyright (c) 2010 - 2014, The Linux Foundation. All rights reserved.
+ *
+ * Not a Contribution, Apache license notifications and license are retained
+ * for attribution purposes only.
+ *
+ * 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 <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 <copybit.h>
+
+#include "gralloc_priv.h"
+#include "software_converter.h"
+#include <qdMetaData.h>
+
+#define DEBUG_MDP_ERRORS 1
+
+/******************************************************************************/
+
+#define MAX_SCALE_FACTOR    (4)
+#define MAX_DIMENSION       (4096)
+
+/******************************************************************************/
+struct blitReq{
+    struct  mdp_buf_sync sync;
+    uint32_t count;
+    struct mdp_blit_req req[10];
+};
+
+/** State information for each device instance */
+struct copybit_context_t {
+    struct copybit_device_t device;
+    int     mFD;
+    uint8_t mAlpha;
+    int     mFlags;
+    bool    mBlitToFB;
+    int     acqFence[MDP_MAX_FENCE_FD];
+    int     relFence;
+    struct  mdp_buf_sync sync;
+    struct  blitReq list;
+    uint8_t dynamic_fps;
+};
+
+/**
+ * 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);
+}
+
+static bool validateCopybitRect(struct copybit_rect_t *rect) {
+    return ((rect->b > rect->t) && (rect->r > rect->l)) ;
+}
+
+/** 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_BGRX_8888:     return MDP_BGRX_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_I:   return MDP_YCRYCB_H2V1;
+        case HAL_PIXEL_FORMAT_YCbCr_422_I:   return MDP_YCBYCR_H2V1;
+        case HAL_PIXEL_FORMAT_YCrCb_422_SP:  return MDP_Y_CRCB_H2V1;
+        case HAL_PIXEL_FORMAT_YCrCb_420_SP:  return MDP_Y_CRCB_H2V2;
+        case HAL_PIXEL_FORMAT_YCbCr_422_SP:  return MDP_Y_CBCR_H2V1;
+        case HAL_PIXEL_FORMAT_YCbCr_420_SP:  return MDP_Y_CBCR_H2V2;
+        case HAL_PIXEL_FORMAT_YCrCb_420_SP_ADRENO: return MDP_Y_CBCR_H2V2_ADRENO;
+        case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS: return MDP_Y_CBCR_H2V2_VENUS;
+        case HAL_PIXEL_FORMAT_NV12_ENCODEABLE: return MDP_Y_CBCR_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;
+    if(hnd == NULL){
+        ALOGE("copybit: Invalid handle");
+        return;
+    }
+    img->width      = rhs->w;
+    img->height     = rhs->h;
+    img->format     = get_format(rhs->format);
+    img->offset     = (uint32_t)hnd->offset;
+    img->memory_id  = hnd->fd;
+}
+/** setup rectangles */
+static bool 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) {
+    struct copybit_rect_t clip;
+    intersect(&clip, scissor, dst);
+
+    if (!validateCopybitRect(&clip))
+       return false;
+
+    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, delta_x, delta_y;
+    if (dev->mFlags & COPYBIT_TRANSFORM_ROT_90) {
+        delta_x = (clip.t - dst->t);
+        delta_y = (dst->r - clip.r);
+        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 {
+        delta_x  = (clip.l - dst->l);
+        delta_y  = (clip.t - dst->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(&delta_x, &e->src_rect.w, src->r - src->l, W);
+    MULDIV(&delta_y, &e->src_rect.h, src->b - src->t, H);
+
+    e->src_rect.x = delta_x + src->l;
+    e->src_rect.y = delta_y + src->t;
+
+    if (dev->mFlags & COPYBIT_TRANSFORM_FLIP_V) {
+        if (dev->mFlags & COPYBIT_TRANSFORM_ROT_90) {
+            e->src_rect.x = (src->l + src->r) - (e->src_rect.x + e->src_rect.w);
+        }else{
+            e->src_rect.y = (src->t + src->b) - (e->src_rect.y + e->src_rect.h);
+        }
+    }
+
+    if (dev->mFlags & COPYBIT_TRANSFORM_FLIP_H) {
+        if (dev->mFlags & COPYBIT_TRANSFORM_ROT_90) {
+            e->src_rect.y = (src->t + src->b) - (e->src_rect.y + e->src_rect.h);
+        }else{
+            e->src_rect.x = (src->l + src->r) - (e->src_rect.x + e->src_rect.w);
+        }
+    }
+    return true;
+}
+
+/** setup mdp request */
+static void set_infos(struct copybit_context_t *dev,
+                      struct mdp_blit_req *req, int flags)
+{
+    req->alpha = dev->mAlpha;
+    req->fps = dev->dynamic_fps;
+    req->transp_mask = MDP_TRANSP_NOP;
+    req->flags = dev->mFlags | flags;
+    // check if we are blitting to f/b
+    if (COPYBIT_ENABLE == dev->mBlitToFB) {
+        req->flags |= MDP_MEMORY_ID_TYPE_FB;
+    }
+#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;
+    if (dev->relFence != -1) {
+        close(dev->relFence);
+        dev->relFence = -1;
+    }
+    err = ioctl(dev->mFD, MSMFB_ASYNC_BLIT,
+                    (struct mdp_async_blit_req_list const*)list);
+    ALOGE_IF(err<0, "copyBits failed (%s)", strerror(errno));
+    if (err == 0) {
+        return 0;
+    } else {
+#if DEBUG_MDP_ERRORS
+        struct mdp_async_blit_req_list const* l =
+            (struct mdp_async_blit_req_list const*)list;
+        for (unsigned int i=0 ; i<l->count ; i++) {
+            ALOGE("%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=%08x, fps=%d"
+                  ,
+                  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,
+                  l->req[i].fps
+                 );
+        }
+#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:
+                        ALOGE("Invalid value for COPYBIT_ROTATION_DEG");
+                        status = -EINVAL;
+                        break;
+                }
+                break;
+            case COPYBIT_PLANE_ALPHA:
+                if (value < 0)      value = MDP_ALPHA_NOP;
+                if (value >= 256)   value = 255;
+                ctx->mAlpha = (uint8_t)value;
+                break;
+            case COPYBIT_DYNAMIC_FPS:
+                ctx->dynamic_fps = (uint8_t)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_BLEND_MODE:
+                if(value == COPYBIT_BLENDING_PREMULT) {
+                    ctx->mFlags |= MDP_BLEND_FG_PREMULT;
+                } else {
+                    ctx->mFlags &= ~MDP_BLEND_FG_PREMULT;
+                }
+                break;
+            case COPYBIT_TRANSFORM:
+                ctx->mFlags &= ~0x7;
+                ctx->mFlags |= value & 0x7;
+                break;
+            case COPYBIT_BLIT_TO_FRAMEBUFFER:
+                if (COPYBIT_ENABLE == value) {
+                    ctx->mBlitToFB = value;
+                } else if (COPYBIT_DISABLE == value) {
+                    ctx->mBlitToFB = value;
+                } else {
+                    ALOGE ("%s:Invalid input for COPYBIT_BLIT_TO_FRAMEBUFFER : %d",
+                            __FUNCTION__, value);
+                }
+                break;
+            case COPYBIT_FG_LAYER:
+                if(value == COPYBIT_ENABLE) {
+                     ctx->mFlags |= MDP_IS_FG;
+                } else if (value == COPYBIT_DISABLE) {
+                    ctx->mFlags &= ~MDP_IS_FG;
+                }
+                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;
+}
+
+static int set_sync_copybit(struct copybit_device_t *dev,
+    int acquireFenceFd)
+{
+    struct copybit_context_t* ctx = (struct copybit_context_t*)dev;
+    if (acquireFenceFd != -1) {
+        if (ctx->list.sync.acq_fen_fd_cnt < (MDP_MAX_FENCE_FD - 1)) {
+            ctx->acqFence[ctx->list.sync.acq_fen_fd_cnt++] = acquireFenceFd;
+        } else {
+            int ret = -EINVAL;
+            struct blitReq *list = &ctx->list;
+
+            // Since fence is full kick off what is already in the list
+            ret = msm_copybit(ctx, list);
+            if (ret < 0) {
+                ALOGE("%s: Blit call failed", __FUNCTION__);
+                return -EINVAL;
+            }
+            list->count = 0;
+            list->sync.acq_fen_fd_cnt = 0;
+            ctx->acqFence[list->sync.acq_fen_fd_cnt++] = acquireFenceFd;
+        }
+    }
+    return 0;
+}
+
+/** 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;
+    struct blitReq *list;
+    int status = 0;
+    private_handle_t *yv12_handle = NULL;
+
+    if (ctx) {
+        list = &ctx->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:
+                    ALOGE ("%s : Unsupported Pixel format %d", __FUNCTION__,
+                           src->format);
+                    return -EINVAL;
+            }
+        }
+
+        if (src_rect->l < 0 || (uint32_t)src_rect->r > src->w ||
+            src_rect->t < 0 || (uint32_t)src_rect->b > src->h) {
+            // this is always invalid
+            ALOGE ("%s : Invalid source rectangle : src_rect l %d t %d r %d b %d",\
+                   __FUNCTION__, src_rect->l, src_rect->t, src_rect->r, src_rect->b);
+
+            return -EINVAL;
+        }
+
+        if (src->w > MAX_DIMENSION || src->h > MAX_DIMENSION) {
+            ALOGE ("%s : Invalid source dimensions w %d h %d", __FUNCTION__, src->w, src->h);
+            return -EINVAL;
+        }
+
+        if (dst->w > MAX_DIMENSION || dst->h > MAX_DIMENSION) {
+            ALOGE ("%s : Invalid DST dimensions w %d h %d", __FUNCTION__, dst->w, dst->h);
+            return -EINVAL;
+        }
+
+        if(src->format ==  HAL_PIXEL_FORMAT_YV12) {
+            int usage =
+            GRALLOC_USAGE_PRIVATE_IOMMU_HEAP | GRALLOC_USAGE_PRIVATE_UNCACHED;
+            if (0 == alloc_buffer(&yv12_handle,src->w,src->h,
+                                  src->format, usage)){
+                if(0 == convertYV12toYCrCb420SP(src,yv12_handle)){
+                    (const_cast<copybit_image_t *>(src))->format =
+                        HAL_PIXEL_FORMAT_YCrCb_420_SP;
+                    (const_cast<copybit_image_t *>(src))->handle =
+                        yv12_handle;
+                    (const_cast<copybit_image_t *>(src))->base =
+                        (void *)yv12_handle->base;
+                }
+                else{
+                    ALOGE("Error copybit conversion from yv12 failed");
+                    if(yv12_handle)
+                        free_buffer(yv12_handle);
+                    return -EINVAL;
+                }
+            }
+            else{
+                ALOGE("Error:unable to allocate memeory for yv12 software conversion");
+                return -EINVAL;
+            }
+        }
+        const uint32_t maxCount =
+                (uint32_t)(sizeof(list->req)/sizeof(list->req[0]));
+        const struct copybit_rect_t bounds = { 0, 0, (int)dst->w, (int)dst->h };
+        struct copybit_rect_t clip;
+        status = 0;
+        while ((status == 0) && region->next(region, &clip)) {
+            intersect(&clip, &bounds, &clip);
+            mdp_blit_req* req = &list->req[list->count];
+            int flags = 0;
+
+            private_handle_t* src_hnd = (private_handle_t*)src->handle;
+            if(src_hnd != NULL &&
+                (!(src_hnd->flags & private_handle_t::PRIV_FLAGS_CACHED))) {
+                flags |=  MDP_BLIT_NON_CACHED;
+            }
+
+            // Set Color Space for MDP to configure CSC matrix
+            req->color_space = ITU_R_601;
+            MetaData_t *metadata = NULL;
+
+            if (src_hnd != NULL)
+                metadata = (MetaData_t *)src_hnd->base_metadata;
+
+            if (metadata && (metadata->operation & UPDATE_COLOR_SPACE)) {
+                req->color_space = metadata->colorSpace;
+            }
+
+            set_infos(ctx, req, flags);
+            set_image(&req->dst, dst);
+            set_image(&req->src, src);
+            if (set_rects(ctx, req, dst_rect, src_rect, &clip) == false)
+                continue;
+
+            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->sync.acq_fen_fd_cnt = 0;
+                list->count = 0;
+            }
+        }
+        if(yv12_handle) {
+            //Before freeing the buffer we need buffer passed through blit call
+            if (list->count != 0) {
+                status = msm_copybit(ctx, list);
+                list->sync.acq_fen_fd_cnt = 0;
+                list->count = 0;
+            }
+            free_buffer(yv12_handle);
+        }
+    } else {
+        ALOGE ("%s : Invalid COPYBIT context", __FUNCTION__);
+        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, (int)dst->w, (int)dst->h };
+    struct copybit_rect_t sr = { 0, 0, (int)src->w, (int)src->h };
+    return stretch_copybit(dev, dst, src, &dr, &sr, region);
+}
+
+static int finish_copybit(struct copybit_device_t *dev)
+{
+    // NOP for MDP copybit
+    if(!dev)
+       return -EINVAL;
+
+    return 0;
+}
+static int clear_copybit(struct copybit_device_t *dev,
+                         struct copybit_image_t const *buf,
+                         struct copybit_rect_t *rect)
+{
+    struct copybit_context_t* ctx = (struct copybit_context_t*)dev;
+    uint32_t color = 0; // black color
+
+    if (!ctx) {
+        ALOGE ("%s: Invalid copybit context", __FUNCTION__);
+        return -EINVAL;
+    }
+
+    struct blitReq list1;
+    memset((char *)&list1 , 0 ,sizeof (struct blitReq) );
+    list1.count = 1;
+    int my_tmp_get_fence = -1;
+
+    list1.sync.acq_fen_fd  =  ctx->acqFence;
+    list1.sync.rel_fen_fd  =  &my_tmp_get_fence;
+    list1.sync.acq_fen_fd_cnt = ctx->list.sync.acq_fen_fd_cnt;
+    mdp_blit_req* req = &list1.req[0];
+
+    if(!req) {
+        ALOGE ("%s : Invalid request", __FUNCTION__);
+        return -EINVAL;
+    }
+
+    set_image(&req->dst, buf);
+    set_image(&req->src, buf);
+
+    if (rect->l < 0 || (uint32_t)(rect->r - rect->l) > req->dst.width ||
+       rect->t < 0 || (uint32_t)(rect->b - rect->t) > req->dst.height) {
+       ALOGE ("%s : Invalid rect : src_rect l %d t %d r %d b %d",\
+       __FUNCTION__, rect->l, rect->t, rect->r, rect->b);
+       return -EINVAL;
+    }
+
+    req->dst_rect.x  = rect->l;
+    req->dst_rect.y  = rect->t;
+    req->dst_rect.w  = rect->r - rect->l;
+    req->dst_rect.h  = rect->b - rect->t;
+
+    req->src_rect = req->dst_rect;
+
+    req->const_color.b = (uint32_t)((color >> 16) & 0xff);
+    req->const_color.g = (uint32_t)((color >> 8) & 0xff);
+    req->const_color.r = (uint32_t)((color >> 0) & 0xff);
+    req->const_color.alpha = MDP_ALPHA_NOP;
+
+    req->transp_mask = MDP_TRANSP_NOP;
+    req->flags = MDP_SOLID_FILL | MDP_MEMORY_ID_TYPE_FB | MDP_BLEND_FG_PREMULT;
+    int status = msm_copybit(ctx, &list1);
+
+    ctx->list.sync.acq_fen_fd_cnt = 0;
+    if (my_tmp_get_fence !=  -1)
+        close(my_tmp_get_fence);
+
+    return status;
+}
+
+/** Fill the rect on dst with RGBA color **/
+static int fill_color(struct copybit_device_t *dev,
+                      struct copybit_image_t const *dst,
+                      struct copybit_rect_t const *rect,
+                      uint32_t color)
+{
+    struct copybit_context_t* ctx = (struct copybit_context_t*)dev;
+    if (!ctx) {
+        ALOGE("%s: Invalid copybit context", __FUNCTION__);
+        return -EINVAL;
+    }
+
+    if (dst->w > MAX_DIMENSION || dst->h > MAX_DIMENSION) {
+        ALOGE("%s: Invalid DST w=%d h=%d", __FUNCTION__, dst->w, dst->h);
+        return -EINVAL;
+    }
+
+    if (rect->l < 0 || (uint32_t)(rect->r - rect->l) > dst->w ||
+        rect->t < 0 || (uint32_t)(rect->b - rect->t) > dst->h) {
+        ALOGE("%s: Invalid destination rect: l=%d t=%d r=%d b=%d",
+                __FUNCTION__, rect->l, rect->t, rect->r, rect->b);
+        return -EINVAL;
+    }
+
+    int status = 0;
+    struct blitReq* list = &ctx->list;
+    mdp_blit_req* req = &list->req[list->count++];
+    set_infos(ctx, req, MDP_SOLID_FILL);
+    set_image(&req->src, dst);
+    set_image(&req->dst, dst);
+
+    req->dst_rect.x = rect->l;
+    req->dst_rect.y = rect->t;
+    req->dst_rect.w = rect->r - rect->l;
+    req->dst_rect.h = rect->b - rect->t;
+    req->src_rect = req->dst_rect;
+
+    req->const_color.r = (uint32_t)((color >> 0) & 0xff);
+    req->const_color.g = (uint32_t)((color >> 8) & 0xff);
+    req->const_color.b = (uint32_t)((color >> 16) & 0xff);
+    req->const_color.alpha = (uint32_t)((color >> 24) & 0xff);
+
+    if (list->count == sizeof(list->req)/sizeof(list->req[0])) {
+        status = msm_copybit(ctx, list);
+        list->sync.acq_fen_fd_cnt = 0;
+        list->count = 0;
+    }
+    return status;
+}
+
+/*****************************************************************************/
+
+/** 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;
+}
+
+static int flush_get_fence(struct copybit_device_t *dev, int* fd)
+{
+    struct copybit_context_t* ctx = (struct copybit_context_t*)dev;
+    struct blitReq *list = &ctx->list;
+    int ret = -EINVAL;
+
+    if (list->count) {
+        ret = msm_copybit(ctx, list);
+        if (ret < 0)
+            ALOGE("%s: Blit call failed", __FUNCTION__);
+        list->count = 0;
+    }
+    *fd = ctx->relFence;
+    list->sync.acq_fen_fd_cnt = 0;
+    ctx->relFence = -1;
+    return ret;
+}
+
+/** 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;
+
+    if (strcmp(name, COPYBIT_HARDWARE_COPYBIT0)) {
+        return COPYBIT_FAILURE;
+    }
+    copybit_context_t *ctx;
+    ctx = (copybit_context_t *)malloc(sizeof(copybit_context_t));
+
+    if (ctx == NULL ) {
+       return COPYBIT_FAILURE;
+    }
+
+    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.set_sync = set_sync_copybit;
+    ctx->device.stretch = stretch_copybit;
+    ctx->device.finish = finish_copybit;
+    ctx->device.fill_color = fill_color;
+    ctx->device.flush_get_fence = flush_get_fence;
+    ctx->device.clear = clear_copybit;
+    ctx->mAlpha = MDP_ALPHA_NOP;
+    //dynamic_fps is zero means default
+    //panel refresh rate for driver.
+    ctx->dynamic_fps = 0;
+    ctx->mFlags = 0;
+    ctx->sync.flags = 0;
+    ctx->relFence = -1;
+    for (int i=0; i < MDP_MAX_FENCE_FD; i++) {
+        ctx->acqFence[i] = -1;
+    }
+    ctx->sync.acq_fen_fd = ctx->acqFence;
+    ctx->sync.rel_fen_fd = &ctx->relFence;
+    ctx->list.count = 0;
+    ctx->list.sync.acq_fen_fd_cnt = 0;
+    ctx->list.sync.rel_fen_fd = ctx->sync.rel_fen_fd;
+    ctx->list.sync.acq_fen_fd = ctx->sync.acq_fen_fd;
+    ctx->mFD = open("/dev/graphics/fb0", O_RDWR, 0);
+    if (ctx->mFD < 0) {
+        status = errno;
+        ALOGE("Error opening frame buffer errno=%d (%s)",
+              status, strerror(status));
+        status = -status;
+    } else {
+        status = 0;
+        *device = &ctx->device.common;
+    }
+    return status;
+}
diff --git a/msm8909/libcopybit/copybit.h b/msm8909/libcopybit/copybit.h
new file mode 100644
index 0000000..b4af021
--- /dev/null
+++ b/msm8909/libcopybit/copybit.h
@@ -0,0 +1,304 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * Copyright (c) 2012-2015, The Linux Foundation. All rights reserved.
+ *
+ * Not a Contribution, Apache license notifications and license are retained
+ * for attribution purposes only.
+ *
+ * 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 ANDROID_COPYBIT_INTERFACE_H
+#define ANDROID_COPYBIT_INTERFACE_H
+
+#include <hardware/hardware.h>
+
+#include <stdint.h>
+#include <sys/cdefs.h>
+#include <sys/types.h>
+#include <gralloc_priv.h>
+
+__BEGIN_DECLS
+
+/**
+ * The id of this module
+ */
+#define COPYBIT_HARDWARE_MODULE_ID "copybit"
+
+/**
+ * Name of the graphics device to open
+ */
+#define COPYBIT_HARDWARE_COPYBIT0 "copybit0"
+
+/* supported pixel-formats. these must be compatible with
+ * graphics/PixelFormat.java, ui/PixelFormat.h, pixelflinger/format.h
+ */
+enum {
+    COPYBIT_FORMAT_RGBA_8888    = HAL_PIXEL_FORMAT_RGBA_8888,
+    COPYBIT_FORMAT_RGBX_8888    = HAL_PIXEL_FORMAT_RGBX_8888,
+    COPYBIT_FORMAT_RGB_888      = HAL_PIXEL_FORMAT_RGB_888,
+    COPYBIT_FORMAT_RGB_565      = HAL_PIXEL_FORMAT_RGB_565,
+    COPYBIT_FORMAT_BGRA_8888    = HAL_PIXEL_FORMAT_BGRA_8888,
+    COPYBIT_FORMAT_YCbCr_422_SP = 0x10,
+    COPYBIT_FORMAT_YCrCb_420_SP = 0x11,
+};
+
+/* name for copybit_set_parameter */
+enum {
+    /* Default blit destination is offline buffer */
+    /* clients to set this to '1', if blitting to framebuffer */
+    /* and reset to '0', after calling blit/stretch */
+    COPYBIT_BLIT_TO_FRAMEBUFFER = 0,
+    /* rotation of the source image in degrees (0 to 359) */
+    COPYBIT_ROTATION_DEG    = 1,
+    /* plane alpha value */
+    COPYBIT_PLANE_ALPHA     = 2,
+    /* enable or disable dithering */
+    COPYBIT_DITHER          = 3,
+    /* transformation applied (this is a superset of COPYBIT_ROTATION_DEG) */
+    COPYBIT_TRANSFORM       = 4,
+    /* blurs the copied bitmap. The amount of blurring cannot be changed
+     * at this time. */
+    COPYBIT_BLUR            = 5,
+    /* Blend mode */
+    COPYBIT_BLEND_MODE  = 6,
+    /* FB width */
+    COPYBIT_FRAMEBUFFER_WIDTH = 7,
+    /* FB height */
+    COPYBIT_FRAMEBUFFER_HEIGHT = 8,
+    COPYBIT_FG_LAYER = 9,
+    COPYBIT_DYNAMIC_FPS = 10,
+};
+
+/* values for copybit_set_parameter(COPYBIT_TRANSFORM) */
+enum {
+    /* flip source image horizontally */
+    COPYBIT_TRANSFORM_FLIP_H    = HAL_TRANSFORM_FLIP_H,
+    /* flip source image vertically */
+    COPYBIT_TRANSFORM_FLIP_V    = HAL_TRANSFORM_FLIP_V,
+    /* rotate source image 90 degres */
+    COPYBIT_TRANSFORM_ROT_90    = HAL_TRANSFORM_ROT_90,
+    /* rotate source image 180 degres */
+    COPYBIT_TRANSFORM_ROT_180   = HAL_TRANSFORM_ROT_180,
+    /* rotate source image 270 degres */
+    COPYBIT_TRANSFORM_ROT_270   = HAL_TRANSFORM_ROT_270,
+};
+
+/* enable/disable value copybit_set_parameter */
+enum {
+    COPYBIT_DISABLE = 0,
+    COPYBIT_ENABLE  = 1
+};
+
+/*
+ * copybit blending values. same as HWC blending values
+ */
+enum {
+    /* no blending */
+    COPYBIT_BLENDING_NONE     = 0x0100,
+
+    /* ONE / ONE_MINUS_SRC_ALPHA */
+    COPYBIT_BLENDING_PREMULT  = 0x0105,
+
+    /* SRC_ALPHA / ONE_MINUS_SRC_ALPHA */
+    COPYBIT_BLENDING_COVERAGE = 0x0405
+};
+
+/* use get_static_info() to query static informations about the hardware */
+enum {
+    /* Maximum amount of minification supported by the hardware*/
+    COPYBIT_MINIFICATION_LIMIT  = 1,
+    /* Maximum amount of magnification supported by the hardware */
+    COPYBIT_MAGNIFICATION_LIMIT = 2,
+    /* Number of fractional bits support by the scaling engine */
+    COPYBIT_SCALING_FRAC_BITS   = 3,
+    /* Supported rotation step in degres. */
+    COPYBIT_ROTATION_STEP_DEG   = 4,
+};
+
+/* Image structure */
+struct copybit_image_t {
+    /* width */
+    uint32_t    w;
+    /* height */
+    uint32_t    h;
+    /* format COPYBIT_FORMAT_xxx */
+    int32_t     format;
+    /* base of buffer with image */
+    void        *base;
+    /* handle to the image */
+    native_handle_t* handle;
+    /* number of pixels added for the stride */
+    uint32_t    horiz_padding;
+    /* number of pixels added for the vertical stride */
+    uint32_t    vert_padding;
+};
+
+/* Rectangle */
+struct copybit_rect_t {
+    /* left */
+    int l;
+    /* top */
+    int t;
+    /* right */
+    int r;
+    /* bottom */
+    int b;
+};
+
+/* Region */
+struct copybit_region_t {
+    int (*next)(struct copybit_region_t const *region, struct copybit_rect_t *rect);
+};
+
+/**
+ * Every hardware module must have a data structure named HAL_MODULE_INFO_SYM
+ * and the fields of this data structure must begin with hw_module_t
+ * followed by module specific information.
+ */
+struct copybit_module_t {
+    struct hw_module_t common;
+};
+
+/**
+ * Every device data structure must begin with hw_device_t
+ * followed by module specific public methods and attributes.
+ */
+struct copybit_device_t {
+    struct hw_device_t common;
+
+    /**
+     * Set a copybit parameter.
+     *
+     * @param dev from open
+     * @param name one for the COPYBIT_NAME_xxx
+     * @param value one of the COPYBIT_VALUE_xxx
+     *
+     * @return 0 if successful
+     */
+    int (*set_parameter)(struct copybit_device_t *dev, int name, int value);
+
+    /**
+     * Get a static copybit information.
+     *
+     * @param dev from open
+     * @param name one of the COPYBIT_STATIC_xxx
+     *
+     * @return value or -EINVAL if error
+     */
+    int (*get)(struct copybit_device_t *dev, int name);
+
+    /**
+     * Execute the bit blit copy operation
+     *
+     * @param dev from open
+     * @param dst is the destination image
+     * @param src is the source image
+     * @param region the clip region
+     *
+     * @return 0 if successful
+     */
+    int (*blit)(struct copybit_device_t *dev,
+                struct copybit_image_t const *dst,
+                struct copybit_image_t const *src,
+                struct copybit_region_t const *region);
+
+    /**
+     * Give acquire fence to copybit to be used in upcoming stretch
+     * call
+     *
+     * @param dev from open
+     * @param acquireFenceFd is the acquire fence
+     *
+     * @return 0 if successful
+     */
+    int (*set_sync)(struct copybit_device_t *dev,
+                   int acquireFenceFd);
+
+    /**
+     * Execute the stretch bit blit copy operation
+     *
+     * @param dev from open
+     * @param dst is the destination image
+     * @param src is the source image
+     * @param dst_rect is the destination rectangle
+     * @param src_rect is the source rectangle
+     * @param region the clip region
+     *
+     * @return 0 if successful
+     */
+    int (*stretch)(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);
+
+    /**
+     * Fill the rect on dst with RGBA color
+     *
+     * @param dev from open
+     * @param dst is destination image
+     * @param rect is destination rectangle
+     * @param color is RGBA color to fill
+     *
+     * @return 0 if successful
+     */
+    int (*fill_color)(struct copybit_device_t *dev,
+                      struct copybit_image_t const *dst,
+                      struct copybit_rect_t const *rect,
+                      uint32_t color);
+
+  /**
+    * Execute the completion of the copybit draw operation.
+    *
+    * @param dev from open
+    *
+    * @return 0 if successful
+    */
+  int (*finish)(struct copybit_device_t *dev);
+
+  /**
+    * Trigger the copybit draw operation(async).
+    *
+    * @param dev from open
+    *
+    * @param fd - gets the fencefd
+    *
+    * @return 0 if successful
+    */
+  int (*flush_get_fence)(struct copybit_device_t *dev, int* fd);
+
+  /* Clears the buffer
+   */
+  int (*clear)(struct copybit_device_t *dev, struct copybit_image_t const *buf,
+               struct copybit_rect_t *rect);
+};
+
+
+/** convenience API for opening and closing a device */
+
+static inline int copybit_open(const struct hw_module_t* module,
+                               struct copybit_device_t** device) {
+    return module->methods->open(module,
+                                 COPYBIT_HARDWARE_COPYBIT0, (struct hw_device_t**)device);
+}
+
+static inline int copybit_close(struct copybit_device_t* device) {
+    return device->common.close(&device->common);
+}
+
+
+__END_DECLS
+
+#endif  // ANDROID_COPYBIT_INTERFACE_H
diff --git a/msm8909/libcopybit/copybit_c2d.cpp b/msm8909/libcopybit/copybit_c2d.cpp
new file mode 100644
index 0000000..158bdca
--- /dev/null
+++ b/msm8909/libcopybit/copybit_c2d.cpp
@@ -0,0 +1,1773 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * Copyright (c) 2010-2015, The Linux Foundation. All rights reserved.
+ *
+ * Not a Contribution, Apache license notifications and license are retained
+ * for attribution purposes only.
+ *
+ * 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 <sys/resource.h>
+#include <sys/prctl.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 <EGL/eglplatform.h>
+#include <cutils/native_handle.h>
+
+#include <copybit.h>
+#include <alloc_controller.h>
+#include <memalloc.h>
+
+#include "c2d2.h"
+#include "software_converter.h"
+
+#include <dlfcn.h>
+
+using gralloc::IMemAlloc;
+using gralloc::IonController;
+using gralloc::alloc_data;
+
+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 );
+
+C2D_STATUS (*LINK_c2dMapAddr) ( int mem_fd, void * hostptr, size_t len,
+                                size_t offset, uint32 flags, void ** gpuaddr);
+
+C2D_STATUS (*LINK_c2dUnMapAddr) ( void * gpuaddr);
+
+C2D_STATUS (*LINK_c2dGetDriverCapabilities) ( C2D_DRIVER_INFO * driver_info);
+
+/* create a fence fd for the timestamp */
+C2D_STATUS (*LINK_c2dCreateFenceFD) ( uint32 target_id, c2d_ts_handle timestamp,
+                                                            int32 *fd);
+
+C2D_STATUS (*LINK_c2dFillSurface) ( uint32 surface_id, uint32 fill_color,
+                                    C2D_RECT * fill_rect);
+
+/******************************************************************************/
+
+#if defined(COPYBIT_Z180)
+#define MAX_SCALE_FACTOR    (4096)
+#define MAX_DIMENSION       (4096)
+#else
+#error "Unsupported HW version"
+#endif
+
+// The following defines can be changed as required i.e. as we encounter
+// complex use cases.
+#define MAX_RGB_SURFACES 32       // Max. RGB layers currently supported per draw
+#define MAX_YUV_2_PLANE_SURFACES 4// Max. 2-plane YUV layers currently supported per draw
+#define MAX_YUV_3_PLANE_SURFACES 1// Max. 3-plane YUV layers currently supported per draw
+// +1 for the destination surface. We cannot have multiple destination surfaces.
+#define MAX_SURFACES (MAX_RGB_SURFACES + MAX_YUV_2_PLANE_SURFACES + MAX_YUV_3_PLANE_SURFACES + 1)
+#define NUM_SURFACE_TYPES 3      // RGB_SURFACE + YUV_SURFACE_2_PLANES + YUV_SURFACE_3_PLANES
+#define MAX_BLIT_OBJECT_COUNT 50 // Max. blit objects that can be passed per draw
+
+enum {
+    RGB_SURFACE,
+    YUV_SURFACE_2_PLANES,
+    YUV_SURFACE_3_PLANES
+};
+
+enum eConversionType {
+    CONVERT_TO_ANDROID_FORMAT,
+    CONVERT_TO_C2D_FORMAT
+};
+
+enum eC2DFlags {
+    FLAGS_PREMULTIPLIED_ALPHA  = 1<<0,
+    FLAGS_YUV_DESTINATION      = 1<<1,
+    FLAGS_TEMP_SRC_DST         = 1<<2
+};
+
+static gralloc::IAllocController* sAlloc = 0;
+/******************************************************************************/
+
+/** State information for each device instance */
+struct copybit_context_t {
+    struct copybit_device_t device;
+    // Templates for the various source surfaces. These templates are created
+    // to avoid the expensive create/destroy C2D Surfaces
+    C2D_OBJECT_STR blit_rgb_object[MAX_RGB_SURFACES];
+    C2D_OBJECT_STR blit_yuv_2_plane_object[MAX_YUV_2_PLANE_SURFACES];
+    C2D_OBJECT_STR blit_yuv_3_plane_object[MAX_YUV_3_PLANE_SURFACES];
+    C2D_OBJECT_STR blit_list[MAX_BLIT_OBJECT_COUNT]; // Z-ordered list of blit objects
+    C2D_DRIVER_INFO c2d_driver_info;
+    void *libc2d2;
+    alloc_data temp_src_buffer;
+    alloc_data temp_dst_buffer;
+    unsigned int dst[NUM_SURFACE_TYPES]; // dst surfaces
+    uintptr_t mapped_gpu_addr[MAX_SURFACES]; // GPU addresses mapped inside copybit
+    int blit_rgb_count;         // Total RGB surfaces being blit
+    int blit_yuv_2_plane_count; // Total 2 plane YUV surfaces being
+    int blit_yuv_3_plane_count; // Total 3 plane YUV  surfaces being blit
+    int blit_count;             // Total blit objects.
+    unsigned int trg_transform;      /* target transform */
+    int fb_width;
+    int fb_height;
+    int src_global_alpha;
+    int config_mask;
+    int dst_surface_type;
+    bool is_premultiplied_alpha;
+    void* time_stamp;
+    bool dst_surface_mapped; // Set when dst surface is mapped to GPU addr
+    void* dst_surface_base; // Stores the dst surface addr
+
+    // used for signaling the wait thread
+    bool wait_timestamp;
+    pthread_t wait_thread_id;
+    bool stop_thread;
+    pthread_mutex_t wait_cleanup_lock;
+    pthread_cond_t wait_cleanup_cond;
+
+};
+
+struct bufferInfo {
+    int width;
+    int height;
+    int format;
+};
+
+struct yuvPlaneInfo {
+    int yStride;       //luma stride
+    int plane1_stride;
+    int plane2_stride;
+    size_t plane1_offset;
+    size_t plane2_offset;
+};
+
+/**
+ * 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
+        }
+};
+
+
+/* thread function which waits on the timeStamp and cleans up the surfaces */
+static void* c2d_wait_loop(void* ptr) {
+    copybit_context_t* ctx = (copybit_context_t*)(ptr);
+    char thread_name[64] = "copybitWaitThr";
+    prctl(PR_SET_NAME, (unsigned long) &thread_name, 0, 0, 0);
+    setpriority(PRIO_PROCESS, 0, HAL_PRIORITY_URGENT_DISPLAY);
+
+    while(ctx->stop_thread == false) {
+        pthread_mutex_lock(&ctx->wait_cleanup_lock);
+        while(ctx->wait_timestamp == false && !ctx->stop_thread) {
+            pthread_cond_wait(&(ctx->wait_cleanup_cond),
+                              &(ctx->wait_cleanup_lock));
+        }
+        if(ctx->wait_timestamp) {
+            if(LINK_c2dWaitTimestamp(ctx->time_stamp)) {
+                ALOGE("%s: LINK_c2dWaitTimeStamp ERROR!!", __FUNCTION__);
+            }
+            ctx->wait_timestamp = false;
+            // Unmap any mapped addresses.
+            for (int i = 0; i < MAX_SURFACES; i++) {
+                if (ctx->mapped_gpu_addr[i]) {
+                    LINK_c2dUnMapAddr( (void*)ctx->mapped_gpu_addr[i]);
+                    ctx->mapped_gpu_addr[i] = 0;
+                }
+            }
+            // Reset the counts after the draw.
+            ctx->blit_rgb_count = 0;
+            ctx->blit_yuv_2_plane_count = 0;
+            ctx->blit_yuv_3_plane_count = 0;
+            ctx->blit_count = 0;
+            ctx->dst_surface_mapped = false;
+            ctx->dst_surface_base = 0;
+        }
+        pthread_mutex_unlock(&ctx->wait_cleanup_lock);
+        if(ctx->stop_thread)
+            break;
+    }
+    pthread_exit(NULL);
+    return NULL;
+}
+
+
+/* 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_RGB_888:        return C2D_COLOR_FORMAT_888_RGB |
+                                              C2D_FORMAT_SWAP_RB;
+        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_YCbCr_420_SP:   return C2D_COLOR_FORMAT_420_NV12;
+        case HAL_PIXEL_FORMAT_NV12_ENCODEABLE: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:                              ALOGE("%s: invalid format (0x%x",
+                                                     __FUNCTION__, format);
+                                              return -EINVAL;
+    }
+    return -EINVAL;
+}
+
+/* Get the C2D formats needed for conversion to YUV */
+static int get_c2d_format_for_yuv_destination(int halFormat) {
+    switch (halFormat) {
+        // We do not swap the RB when the target is YUV
+        case HAL_PIXEL_FORMAT_RGBX_8888:      return C2D_COLOR_FORMAT_8888_ARGB |
+                                              C2D_FORMAT_DISABLE_ALPHA;
+        case HAL_PIXEL_FORMAT_RGBA_8888:      return C2D_COLOR_FORMAT_8888_ARGB;
+        // The U and V need to be interchanged when the target is YUV
+        case HAL_PIXEL_FORMAT_YCbCr_420_SP:   return C2D_COLOR_FORMAT_420_NV21;
+        case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:return C2D_COLOR_FORMAT_420_NV21;
+        case HAL_PIXEL_FORMAT_YCrCb_420_SP:   return C2D_COLOR_FORMAT_420_NV12;
+        default:                              return get_format(halFormat);
+    }
+    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_888_RGB:
+            c2dBpp = 24;
+            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:
+            ALOGE("%s ERROR", __func__);
+            break;
+    }
+    return c2dBpp;
+}
+
+static size_t c2d_get_gpuaddr(copybit_context_t* ctx,
+                              struct private_handle_t *handle, int &mapped_idx)
+{
+    uint32 memtype;
+    size_t *gpuaddr = 0;
+    C2D_STATUS rc;
+    int freeindex = 0;
+    bool mapaddr = false;
+
+    if(!handle)
+        return 0;
+
+    if (handle->flags & (private_handle_t::PRIV_FLAGS_USES_PMEM |
+                         private_handle_t::PRIV_FLAGS_USES_PMEM_ADSP))
+        memtype = KGSL_USER_MEM_TYPE_PMEM;
+    else if (handle->flags & private_handle_t::PRIV_FLAGS_USES_ASHMEM)
+        memtype = KGSL_USER_MEM_TYPE_ASHMEM;
+    else if (handle->flags & private_handle_t::PRIV_FLAGS_USES_ION)
+        memtype = KGSL_USER_MEM_TYPE_ION;
+    else {
+        ALOGE("Invalid handle flags: 0x%x", handle->flags);
+        return 0;
+    }
+
+    // Check for a freeindex in the mapped_gpu_addr list
+    for (freeindex = 0; freeindex < MAX_SURFACES; freeindex++) {
+        if (ctx->mapped_gpu_addr[freeindex] == 0) {
+            // free index is available
+            // map GPU addr and use this as mapped_idx
+            mapaddr = true;
+            break;
+        }
+    }
+
+    if(mapaddr) {
+        rc = LINK_c2dMapAddr(handle->fd, (void*)handle->base, handle->size,
+                             handle->offset, memtype, (void**)&gpuaddr);
+
+        if (rc == C2D_STATUS_OK) {
+            // We have mapped the GPU address inside copybit. We need to unmap
+            // this address after the blit. Store this address
+            ctx->mapped_gpu_addr[freeindex] = (size_t)gpuaddr;
+            mapped_idx = freeindex;
+        }
+    }
+    return (size_t)gpuaddr;
+}
+
+static void unmap_gpuaddr(copybit_context_t* ctx, int mapped_idx)
+{
+    if (!ctx || (mapped_idx == -1))
+        return;
+
+    if (ctx->mapped_gpu_addr[mapped_idx]) {
+        LINK_c2dUnMapAddr( (void*)ctx->mapped_gpu_addr[mapped_idx]);
+        ctx->mapped_gpu_addr[mapped_idx] = 0;
+    }
+}
+
+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_888:
+        case HAL_PIXEL_FORMAT_RGB_565:
+        case HAL_PIXEL_FORMAT_BGRA_8888: {
+            return COPYBIT_SUCCESS;
+        }
+        default:
+            return COPYBIT_FAILURE;
+    }
+}
+
+static int get_num_planes(int format)
+{
+    switch(format) {
+        case HAL_PIXEL_FORMAT_YCbCr_420_SP:
+        case HAL_PIXEL_FORMAT_YCrCb_420_SP:
+        case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:
+        case HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED: {
+            return 2;
+        }
+        case HAL_PIXEL_FORMAT_YV12: {
+            return 3;
+        }
+        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_NV12_ENCODEABLE:
+        case HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED: {
+            return COPYBIT_SUCCESS;
+        }
+        default:
+            return COPYBIT_FAILURE;
+    }
+}
+
+static int is_valid_destination_format(int format)
+{
+    if (format == HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED) {
+        // C2D does not support NV12Tile as a destination format.
+        return COPYBIT_FAILURE;
+    }
+    return COPYBIT_SUCCESS;
+}
+
+static int calculate_yuv_offset_and_stride(const bufferInfo& info,
+                                           yuvPlaneInfo& yuvInfo)
+{
+    int width  = info.width;
+    int height = info.height;
+    int format = info.format;
+
+    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;
+            yuvInfo.plane1_offset = ALIGN(size,8192);
+            yuvInfo.yStride = aligned_width;
+            yuvInfo.plane1_stride = aligned_width;
+            break;
+        }
+        case HAL_PIXEL_FORMAT_YCbCr_420_SP:
+        case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:
+        case HAL_PIXEL_FORMAT_YCrCb_420_SP: {
+            aligned_width = ALIGN(width, 32);
+            yuvInfo.yStride = aligned_width;
+            yuvInfo.plane1_stride = aligned_width;
+            if (HAL_PIXEL_FORMAT_NV12_ENCODEABLE == format) {
+                // The encoder requires a 2K aligned chroma offset
+                yuvInfo.plane1_offset = ALIGN(aligned_width * height, 2048);
+            } else
+                yuvInfo.plane1_offset = aligned_width * height;
+
+            break;
+        }
+        default: {
+            return COPYBIT_FAILURE;
+        }
+    }
+    return COPYBIT_SUCCESS;
+}
+
+/** create C2D surface from copybit image */
+static int set_image(copybit_context_t* ctx, uint32 surfaceId,
+                      const struct copybit_image_t *rhs,
+                      const eC2DFlags flags, int &mapped_idx)
+{
+    struct private_handle_t* handle = (struct private_handle_t*)rhs->handle;
+    C2D_SURFACE_TYPE surfaceType;
+    int status = COPYBIT_SUCCESS;
+    uint64_t gpuaddr = 0;
+    int c2d_format;
+    mapped_idx = -1;
+
+    if (flags & FLAGS_YUV_DESTINATION) {
+        c2d_format = get_c2d_format_for_yuv_destination(rhs->format);
+    } else {
+        c2d_format = get_format(rhs->format);
+    }
+
+    if(c2d_format == -EINVAL) {
+        ALOGE("%s: invalid format", __FUNCTION__);
+        return -EINVAL;
+    }
+
+    if(handle == NULL) {
+        ALOGE("%s: invalid handle", __func__);
+        return -EINVAL;
+    }
+
+    if (handle->gpuaddr == 0) {
+        gpuaddr = c2d_get_gpuaddr(ctx, handle, mapped_idx);
+        if(!gpuaddr) {
+            ALOGE("%s: c2d_get_gpuaddr failed", __FUNCTION__);
+            return COPYBIT_FAILURE;
+        }
+    } else {
+        gpuaddr = handle->gpuaddr;
+    }
+
+    /* 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*) gpuaddr;
+        surfaceDef.buffer = (void*) (handle->base);
+
+        surfaceDef.format = c2d_format |
+            ((flags & FLAGS_PREMULTIPLIED_ALPHA) ? C2D_FORMAT_PREMULTIPLIED : 0);
+        surfaceDef.width = rhs->w;
+        surfaceDef.height = rhs->h;
+        int aligned_width = ALIGN((int)surfaceDef.width,32);
+        surfaceDef.stride = (aligned_width * c2diGetBpp(surfaceDef.format))>>3;
+
+        if(LINK_c2dUpdateSurface( surfaceId,C2D_TARGET | C2D_SOURCE, surfaceType,
+                                  &surfaceDef)) {
+            ALOGE("%s: RGB Surface c2dUpdateSurface ERROR", __FUNCTION__);
+            unmap_gpuaddr(ctx, mapped_idx);
+            status = COPYBIT_FAILURE;
+        }
+    } else if (is_supported_yuv_format(rhs->format) == COPYBIT_SUCCESS) {
+        C2D_YUV_SURFACE_DEF surfaceDef;
+        memset(&surfaceDef, 0, sizeof(surfaceDef));
+        surfaceType = (C2D_SURFACE_TYPE)(C2D_SURFACE_YUV_HOST | C2D_SURFACE_WITH_PHYS);
+        surfaceDef.format = c2d_format;
+
+        bufferInfo info;
+        info.width = rhs->w;
+        info.height = rhs->h;
+        info.format = rhs->format;
+
+        yuvPlaneInfo yuvInfo = {0};
+        status = calculate_yuv_offset_and_stride(info, yuvInfo);
+        if(status != COPYBIT_SUCCESS) {
+            ALOGE("%s: calculate_yuv_offset_and_stride error", __FUNCTION__);
+            unmap_gpuaddr(ctx, mapped_idx);
+        }
+
+        surfaceDef.width = rhs->w;
+        surfaceDef.height = rhs->h;
+        surfaceDef.plane0 = (void*) (handle->base);
+        surfaceDef.phys0 = (void*) (gpuaddr);
+        surfaceDef.stride0 = yuvInfo.yStride;
+
+        surfaceDef.plane1 = (void*) (handle->base + yuvInfo.plane1_offset);
+        surfaceDef.phys1 = (void*) (gpuaddr + yuvInfo.plane1_offset);
+        surfaceDef.stride1 = yuvInfo.plane1_stride;
+        if (3 == get_num_planes(rhs->format)) {
+            surfaceDef.plane2 = (void*) (handle->base + yuvInfo.plane2_offset);
+            surfaceDef.phys2 = (void*) (gpuaddr + yuvInfo.plane2_offset);
+            surfaceDef.stride2 = yuvInfo.plane2_stride;
+        }
+
+        if(LINK_c2dUpdateSurface( surfaceId,C2D_TARGET | C2D_SOURCE, surfaceType,
+                                  &surfaceDef)) {
+            ALOGE("%s: YUV Surface c2dUpdateSurface ERROR", __FUNCTION__);
+            unmap_gpuaddr(ctx, mapped_idx);
+            status = COPYBIT_FAILURE;
+        }
+    } else {
+        ALOGE("%s: invalid format 0x%x", __FUNCTION__, rhs->format);
+        unmap_gpuaddr(ctx, mapped_idx);
+        status = COPYBIT_FAILURE;
+    }
+
+    return status;
+}
+
+/** copy the bits */
+static int msm_copybit(struct copybit_context_t *ctx, unsigned int target)
+{
+    if (ctx->blit_count == 0) {
+        return COPYBIT_SUCCESS;
+    }
+
+    for (int i = 0; i < ctx->blit_count; i++)
+    {
+        ctx->blit_list[i].next = &(ctx->blit_list[i+1]);
+    }
+    ctx->blit_list[ctx->blit_count-1].next = NULL;
+    uint32_t target_transform = ctx->trg_transform;
+    if (ctx->c2d_driver_info.capabilities_mask &
+        C2D_DRIVER_SUPPORTS_OVERRIDE_TARGET_ROTATE_OP) {
+        // For A3xx - set 0x0 as the transform is set in the config_mask
+        target_transform = 0x0;
+    }
+    if(LINK_c2dDraw(target, target_transform, 0x0, 0, 0, ctx->blit_list,
+                    ctx->blit_count)) {
+        ALOGE("%s: LINK_c2dDraw ERROR", __FUNCTION__);
+        return COPYBIT_FAILURE;
+    }
+    return COPYBIT_SUCCESS;
+}
+
+
+
+static int flush_get_fence_copybit (struct copybit_device_t *dev, int* fd)
+{
+    struct copybit_context_t* ctx = (struct copybit_context_t*)dev;
+    int status = COPYBIT_FAILURE;
+    if (!ctx)
+        return COPYBIT_FAILURE;
+    pthread_mutex_lock(&ctx->wait_cleanup_lock);
+    status = msm_copybit(ctx, ctx->dst[ctx->dst_surface_type]);
+
+    if(LINK_c2dFlush(ctx->dst[ctx->dst_surface_type], &ctx->time_stamp)) {
+        ALOGE("%s: LINK_c2dFlush ERROR", __FUNCTION__);
+        // unlock the mutex and return failure
+        pthread_mutex_unlock(&ctx->wait_cleanup_lock);
+        return COPYBIT_FAILURE;
+    }
+    if(LINK_c2dCreateFenceFD(ctx->dst[ctx->dst_surface_type], ctx->time_stamp,
+                                                                        fd)) {
+        ALOGE("%s: LINK_c2dCreateFenceFD ERROR", __FUNCTION__);
+        status = COPYBIT_FAILURE;
+    }
+    if(status == COPYBIT_SUCCESS) {
+        //signal the wait_thread
+        ctx->wait_timestamp = true;
+        pthread_cond_signal(&ctx->wait_cleanup_cond);
+    }
+    pthread_mutex_unlock(&ctx->wait_cleanup_lock);
+    return status;
+}
+
+static int finish_copybit(struct copybit_device_t *dev)
+{
+    struct copybit_context_t* ctx = (struct copybit_context_t*)dev;
+    if (!ctx)
+        return COPYBIT_FAILURE;
+
+   int status = msm_copybit(ctx, ctx->dst[ctx->dst_surface_type]);
+
+   if(LINK_c2dFinish(ctx->dst[ctx->dst_surface_type])) {
+        ALOGE("%s: LINK_c2dFinish ERROR", __FUNCTION__);
+        return COPYBIT_FAILURE;
+    }
+
+    // Unmap any mapped addresses.
+    for (int i = 0; i < MAX_SURFACES; i++) {
+        if (ctx->mapped_gpu_addr[i]) {
+            LINK_c2dUnMapAddr( (void*)ctx->mapped_gpu_addr[i]);
+            ctx->mapped_gpu_addr[i] = 0;
+        }
+    }
+
+    // Reset the counts after the draw.
+    ctx->blit_rgb_count = 0;
+    ctx->blit_yuv_2_plane_count = 0;
+    ctx->blit_yuv_3_plane_count = 0;
+    ctx->blit_count = 0;
+    ctx->dst_surface_mapped = false;
+    ctx->dst_surface_base = 0;
+
+    return status;
+}
+
+static int clear_copybit(struct copybit_device_t *dev,
+                         struct copybit_image_t const *buf,
+                         struct copybit_rect_t *rect)
+{
+    int ret = COPYBIT_SUCCESS;
+    int flags = FLAGS_PREMULTIPLIED_ALPHA;
+    int mapped_dst_idx = -1;
+    struct copybit_context_t* ctx = (struct copybit_context_t*)dev;
+    C2D_RECT c2drect = {rect->l, rect->t, rect->r - rect->l, rect->b - rect->t};
+    pthread_mutex_lock(&ctx->wait_cleanup_lock);
+    if(!ctx->dst_surface_mapped) {
+        ret = set_image(ctx, ctx->dst[RGB_SURFACE], buf,
+                        (eC2DFlags)flags, mapped_dst_idx);
+        if(ret) {
+            ALOGE("%s: set_image error", __FUNCTION__);
+            unmap_gpuaddr(ctx, mapped_dst_idx);
+            pthread_mutex_unlock(&ctx->wait_cleanup_lock);
+            return COPYBIT_FAILURE;
+        }
+        //clear_copybit is the first call made by HWC for each composition
+        //with the dest surface, hence set dst_surface_mapped.
+        ctx->dst_surface_mapped = true;
+        ctx->dst_surface_base = buf->base;
+        ret = LINK_c2dFillSurface(ctx->dst[RGB_SURFACE], 0x0, &c2drect);
+    }
+    pthread_mutex_unlock(&ctx->wait_cleanup_lock);
+    return ret;
+}
+
+
+/** 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)
+{
+    // Set the target rect.
+    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        = ctx->fb_width?
+                (ALIGN(ctx->fb_width,32)- dst->r):dst->r;
+        c2dObject->target_rect.y        = c2dObject->target_rect.y<<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?(ctx->fb_height - dst->b):dst->b;
+        c2dObject->target_rect.x        = c2dObject->target_rect.x<<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?(ctx->fb_height - dst->b):dst->b;
+        c2dObject->target_rect.y        = c2dObject->target_rect.y<<16;
+        c2dObject->target_rect.x        = ctx->fb_width?
+                (ALIGN(ctx->fb_width,32) - dst->r):dst->r;
+        c2dObject->target_rect.x        = c2dObject->target_rect.x<<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;
+
+    // Set the source rect
+    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;
+
+    // Set the scissor rect
+    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;
+}
+
+/*****************************************************************************/
+
+/** 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 = COPYBIT_SUCCESS;
+    if (!ctx) {
+        ALOGE("%s: null context", __FUNCTION__);
+        return -EINVAL;
+    }
+
+    pthread_mutex_lock(&ctx->wait_cleanup_lock);
+    switch(name) {
+        case COPYBIT_PLANE_ALPHA:
+        {
+            if (value < 0)      value = 0;
+            if (value >= 256)   value = 255;
+
+            ctx->src_global_alpha = value;
+            if (value < 255)
+                ctx->config_mask |= C2D_GLOBAL_ALPHA_BIT;
+            else
+                ctx->config_mask &= ~C2D_GLOBAL_ALPHA_BIT;
+        }
+        break;
+        case COPYBIT_BLEND_MODE:
+        {
+            if (value == COPYBIT_BLENDING_NONE) {
+                ctx->config_mask |= C2D_ALPHA_BLEND_NONE;
+                ctx->is_premultiplied_alpha = true;
+            } else if (value == COPYBIT_BLENDING_PREMULT) {
+                ctx->is_premultiplied_alpha = true;
+            } else {
+                ctx->config_mask &= ~C2D_ALPHA_BLEND_NONE;
+            }
+        }
+        break;
+        case COPYBIT_TRANSFORM:
+        {
+            unsigned int transform = 0;
+            uint32 config_mask = 0;
+            config_mask |= C2D_OVERRIDE_GLOBAL_TARGET_ROTATE_CONFIG;
+            if((value & 0x7) == COPYBIT_TRANSFORM_ROT_180) {
+                transform = C2D_TARGET_ROTATE_180;
+                config_mask |= C2D_OVERRIDE_TARGET_ROTATE_180;
+            } else if((value & 0x7) == COPYBIT_TRANSFORM_ROT_270) {
+                transform = C2D_TARGET_ROTATE_90;
+                config_mask |= C2D_OVERRIDE_TARGET_ROTATE_90;
+            } else if(value == COPYBIT_TRANSFORM_ROT_90) {
+                transform = C2D_TARGET_ROTATE_270;
+                config_mask |= C2D_OVERRIDE_TARGET_ROTATE_270;
+            } else {
+                config_mask |= C2D_OVERRIDE_TARGET_ROTATE_0;
+                if(value & COPYBIT_TRANSFORM_FLIP_H) {
+                    config_mask |= C2D_MIRROR_H_BIT;
+                } else if(value & COPYBIT_TRANSFORM_FLIP_V) {
+                    config_mask |= C2D_MIRROR_V_BIT;
+                }
+            }
+
+            if (ctx->c2d_driver_info.capabilities_mask &
+                C2D_DRIVER_SUPPORTS_OVERRIDE_TARGET_ROTATE_OP) {
+                ctx->config_mask |= config_mask;
+            } else {
+                // The transform for this surface does not match the current
+                // target transform. Draw all previous surfaces. This will be
+                // changed once we have a new mechanism to send different
+                // target rotations to c2d.
+                finish_copybit(dev);
+            }
+            ctx->trg_transform = transform;
+        }
+        break;
+        case COPYBIT_FRAMEBUFFER_WIDTH:
+            ctx->fb_width = value;
+            break;
+        case COPYBIT_FRAMEBUFFER_HEIGHT:
+            ctx->fb_height = value;
+            break;
+        case COPYBIT_ROTATION_DEG:
+        case COPYBIT_DITHER:
+        case COPYBIT_BLUR:
+        case COPYBIT_BLIT_TO_FRAMEBUFFER:
+            // Do nothing
+            break;
+        default:
+            ALOGE("%s: default case param=0x%x", __FUNCTION__, name);
+            status = -EINVAL;
+            break;
+    }
+    pthread_mutex_unlock(&ctx->wait_cleanup_lock);
+    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) {
+        ALOGE("%s: null context error", __FUNCTION__);
+        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:
+            ALOGE("%s: default case param=0x%x", __FUNCTION__, name);
+            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;
+}
+
+/* Function to check if we need a temporary buffer for the blit.
+ * This would happen if the requested destination stride and the
+ * C2D stride do not match. We ignore RGB buffers, since their
+ * stride is always aligned to 32.
+ */
+static bool need_temp_buffer(struct copybit_image_t const *img)
+{
+    if (COPYBIT_SUCCESS == is_supported_rgb_format(img->format))
+        return false;
+
+    struct private_handle_t* handle = (struct private_handle_t*)img->handle;
+
+    // The width parameter in the handle contains the aligned_w. We check if we
+    // need to convert based on this param. YUV formats have bpp=1, so checking
+    // if the requested stride is aligned should suffice.
+    if (0 == (handle->width)%32) {
+        return false;
+    }
+
+    return true;
+}
+
+/* Function to extract the information from the copybit image and set the corresponding
+ * values in the bufferInfo struct.
+ */
+static void populate_buffer_info(struct copybit_image_t const *img, bufferInfo& info)
+{
+    info.width = img->w;
+    info.height = img->h;
+    info.format = img->format;
+}
+
+/* Function to get the required size for a particular format, inorder for C2D to perform
+ * the blit operation.
+ */
+static int get_size(const bufferInfo& info)
+{
+    int size = 0;
+    int w = info.width;
+    int h = info.height;
+    int aligned_w = ALIGN(w, 32);
+    switch(info.format) {
+        case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:
+            {
+                // Chroma for this format is aligned to 2K.
+                size = ALIGN((aligned_w*h), 2048) +
+                        ALIGN(aligned_w/2, 32) * (h/2) *2;
+                size = ALIGN(size, 4096);
+            } break;
+        case HAL_PIXEL_FORMAT_YCbCr_420_SP:
+        case HAL_PIXEL_FORMAT_YCrCb_420_SP:
+            {
+                size = aligned_w * h +
+                       ALIGN(aligned_w/2, 32) * (h/2) * 2;
+                size = ALIGN(size, 4096);
+            } break;
+        default: break;
+    }
+    return size;
+}
+
+/* Function to allocate memory for the temporary buffer. This memory is
+ * allocated from Ashmem. It is the caller's responsibility to free this
+ * memory.
+ */
+static int get_temp_buffer(const bufferInfo& info, alloc_data& data)
+{
+    ALOGD("%s E", __FUNCTION__);
+    // Alloc memory from system heap
+    data.base = 0;
+    data.fd = -1;
+    data.offset = 0;
+    data.size = get_size(info);
+    data.align = getpagesize();
+    data.uncached = true;
+    int allocFlags = GRALLOC_USAGE_PRIVATE_SYSTEM_HEAP;
+
+    if (sAlloc == 0) {
+        sAlloc = gralloc::IAllocController::getInstance();
+    }
+
+    if (sAlloc == 0) {
+        ALOGE("%s: sAlloc is still NULL", __FUNCTION__);
+        return COPYBIT_FAILURE;
+    }
+
+    int err = sAlloc->allocate(data, allocFlags);
+    if (0 != err) {
+        ALOGE("%s: allocate failed", __FUNCTION__);
+        return COPYBIT_FAILURE;
+    }
+
+    ALOGD("%s X", __FUNCTION__);
+    return err;
+}
+
+/* Function to free the temporary allocated memory.*/
+static void free_temp_buffer(alloc_data &data)
+{
+    if (-1 != data.fd) {
+        IMemAlloc* memalloc = sAlloc->getAllocator(data.allocType);
+        memalloc->free_buffer(data.base, data.size, 0, data.fd);
+    }
+}
+
+/* Function to perform the software color conversion. Convert the
+ * C2D compatible format to the Android compatible format
+ */
+static int copy_image(private_handle_t *src_handle,
+                      struct copybit_image_t const *rhs,
+                      eConversionType conversionType)
+{
+    if (src_handle->fd == -1) {
+        ALOGE("%s: src_handle fd is invalid", __FUNCTION__);
+        return COPYBIT_FAILURE;
+    }
+
+    // Copy the info.
+    int ret = COPYBIT_SUCCESS;
+    switch(rhs->format) {
+        case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:
+        case HAL_PIXEL_FORMAT_YCbCr_420_SP:
+        case HAL_PIXEL_FORMAT_YCrCb_420_SP:
+            {
+                if (CONVERT_TO_ANDROID_FORMAT == conversionType) {
+                    return convert_yuv_c2d_to_yuv_android(src_handle, rhs);
+                } else {
+                    return convert_yuv_android_to_yuv_c2d(src_handle, rhs);
+                }
+
+            } break;
+        default: {
+            ALOGE("%s: invalid format 0x%x", __FUNCTION__, rhs->format);
+            ret = COPYBIT_FAILURE;
+        } break;
+    }
+    return ret;
+}
+
+static void delete_handle(private_handle_t *handle)
+{
+    if (handle) {
+        delete handle;
+        handle = 0;
+    }
+}
+
+static bool need_to_execute_draw(eC2DFlags flags)
+{
+    if (flags & FLAGS_TEMP_SRC_DST) {
+        return true;
+    }
+    if (flags & FLAGS_YUV_DESTINATION) {
+        return true;
+    }
+    return false;
+}
+
+/** 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;
+    int flags = 0;
+    int src_surface_type;
+    int mapped_src_idx = -1, mapped_dst_idx = -1;
+    C2D_OBJECT_STR src_surface;
+
+    if (!ctx) {
+        ALOGE("%s: null context error", __FUNCTION__);
+        return -EINVAL;
+    }
+
+    if (src->w > MAX_DIMENSION || src->h > MAX_DIMENSION) {
+        ALOGE("%s: src dimension error", __FUNCTION__);
+        return -EINVAL;
+    }
+
+    if (dst->w > MAX_DIMENSION || dst->h > MAX_DIMENSION) {
+        ALOGE("%s : dst dimension error dst w %d h %d",  __FUNCTION__, dst->w,
+                                                         dst->h);
+        return -EINVAL;
+    }
+
+    if (is_valid_destination_format(dst->format) == COPYBIT_FAILURE) {
+        ALOGE("%s: Invalid destination format format = 0x%x", __FUNCTION__,
+                                                              dst->format);
+        return COPYBIT_FAILURE;
+    }
+
+    int dst_surface_type;
+    if (is_supported_rgb_format(dst->format) == COPYBIT_SUCCESS) {
+        dst_surface_type = RGB_SURFACE;
+        flags |= FLAGS_PREMULTIPLIED_ALPHA;
+    } else if (is_supported_yuv_format(dst->format) == COPYBIT_SUCCESS) {
+        int num_planes = get_num_planes(dst->format);
+        flags |= FLAGS_YUV_DESTINATION;
+        if (num_planes == 2) {
+            dst_surface_type = YUV_SURFACE_2_PLANES;
+        } else if (num_planes == 3) {
+            dst_surface_type = YUV_SURFACE_3_PLANES;
+        } else {
+            ALOGE("%s: dst number of YUV planes is invalid dst format = 0x%x",
+                  __FUNCTION__, dst->format);
+            return COPYBIT_FAILURE;
+        }
+    } else {
+        ALOGE("%s: Invalid dst surface format 0x%x", __FUNCTION__,
+                                                     dst->format);
+        return COPYBIT_FAILURE;
+    }
+
+    if (ctx->blit_rgb_count == MAX_RGB_SURFACES ||
+        ctx->blit_yuv_2_plane_count == MAX_YUV_2_PLANE_SURFACES ||
+        ctx->blit_yuv_3_plane_count == MAX_YUV_2_PLANE_SURFACES ||
+        ctx->blit_count == MAX_BLIT_OBJECT_COUNT ||
+        ctx->dst_surface_type != dst_surface_type) {
+        // we have reached the max. limits of our internal structures or
+        // changed the target.
+        // Draw the remaining surfaces. We need to do the finish here since
+        // we need to free up the surface templates.
+        finish_copybit(dev);
+    }
+
+    ctx->dst_surface_type = dst_surface_type;
+
+    // Update the destination
+    copybit_image_t dst_image;
+    dst_image.w = dst->w;
+    dst_image.h = dst->h;
+    dst_image.format = dst->format;
+    dst_image.handle = dst->handle;
+    // Check if we need a temp. copy for the destination. We'd need this the destination
+    // width is not aligned to 32. This case occurs for YUV formats. RGB formats are
+    // aligned to 32.
+    bool need_temp_dst = need_temp_buffer(dst);
+    bufferInfo dst_info;
+    populate_buffer_info(dst, dst_info);
+    private_handle_t* dst_hnd = new private_handle_t(-1, 0, 0, 0, dst_info.format,
+                                                     dst_info.width, dst_info.height);
+    if (dst_hnd == NULL) {
+        ALOGE("%s: dst_hnd is null", __FUNCTION__);
+        return COPYBIT_FAILURE;
+    }
+    if (need_temp_dst) {
+        if (get_size(dst_info) != (int) ctx->temp_dst_buffer.size) {
+            free_temp_buffer(ctx->temp_dst_buffer);
+            // Create a temp buffer and set that as the destination.
+            if (COPYBIT_FAILURE == get_temp_buffer(dst_info, ctx->temp_dst_buffer)) {
+                ALOGE("%s: get_temp_buffer(dst) failed", __FUNCTION__);
+                delete_handle(dst_hnd);
+                return COPYBIT_FAILURE;
+            }
+        }
+        dst_hnd->fd = ctx->temp_dst_buffer.fd;
+        dst_hnd->size = ctx->temp_dst_buffer.size;
+        dst_hnd->flags = ctx->temp_dst_buffer.allocType;
+        dst_hnd->base = (uintptr_t)(ctx->temp_dst_buffer.base);
+        dst_hnd->offset = ctx->temp_dst_buffer.offset;
+        dst_hnd->gpuaddr = 0;
+        dst_image.handle = dst_hnd;
+    }
+    if(!ctx->dst_surface_mapped) {
+        //map the destination surface to GPU address
+        status = set_image(ctx, ctx->dst[ctx->dst_surface_type], &dst_image,
+                           (eC2DFlags)flags, mapped_dst_idx);
+        if(status) {
+            ALOGE("%s: dst: set_image error", __FUNCTION__);
+            delete_handle(dst_hnd);
+            unmap_gpuaddr(ctx, mapped_dst_idx);
+            return COPYBIT_FAILURE;
+        }
+        ctx->dst_surface_mapped = true;
+        ctx->dst_surface_base = dst->base;
+    } else if(ctx->dst_surface_mapped && ctx->dst_surface_base != dst->base) {
+        // Destination surface for the operation should be same for multiple
+        // requests, this check is catch if there is any case when the
+        // destination changes
+        ALOGE("%s: a different destination surface!!", __FUNCTION__);
+    }
+
+    // Update the source
+    flags = 0;
+    if(is_supported_rgb_format(src->format) == COPYBIT_SUCCESS) {
+        src_surface_type = RGB_SURFACE;
+        src_surface = ctx->blit_rgb_object[ctx->blit_rgb_count];
+    } else if (is_supported_yuv_format(src->format) == COPYBIT_SUCCESS) {
+        int num_planes = get_num_planes(src->format);
+        if (num_planes == 2) {
+            src_surface_type = YUV_SURFACE_2_PLANES;
+            src_surface = ctx->blit_yuv_2_plane_object[ctx->blit_yuv_2_plane_count];
+        } else if (num_planes == 3) {
+            src_surface_type = YUV_SURFACE_3_PLANES;
+            src_surface = ctx->blit_yuv_3_plane_object[ctx->blit_yuv_2_plane_count];
+        } else {
+            ALOGE("%s: src number of YUV planes is invalid src format = 0x%x",
+                  __FUNCTION__, src->format);
+            delete_handle(dst_hnd);
+            unmap_gpuaddr(ctx, mapped_dst_idx);
+            return -EINVAL;
+        }
+    } else {
+        ALOGE("%s: Invalid source surface format 0x%x", __FUNCTION__,
+                                                        src->format);
+        delete_handle(dst_hnd);
+        unmap_gpuaddr(ctx, mapped_dst_idx);
+        return -EINVAL;
+    }
+
+    copybit_image_t src_image;
+    src_image.w = src->w;
+    src_image.h = src->h;
+    src_image.format = src->format;
+    src_image.handle = src->handle;
+
+    bool need_temp_src = need_temp_buffer(src);
+    bufferInfo src_info;
+    populate_buffer_info(src, src_info);
+    private_handle_t* src_hnd = new private_handle_t(-1, 0, 0, 0, src_info.format,
+                                                 src_info.width, src_info.height);
+    if (NULL == src_hnd) {
+        ALOGE("%s: src_hnd is null", __FUNCTION__);
+        delete_handle(dst_hnd);
+        unmap_gpuaddr(ctx, mapped_dst_idx);
+        return COPYBIT_FAILURE;
+    }
+    if (need_temp_src) {
+        if (get_size(src_info) != (int) ctx->temp_src_buffer.size) {
+            free_temp_buffer(ctx->temp_src_buffer);
+            // Create a temp buffer and set that as the destination.
+            if (COPYBIT_SUCCESS != get_temp_buffer(src_info,
+                                               ctx->temp_src_buffer)) {
+                ALOGE("%s: get_temp_buffer(src) failed", __FUNCTION__);
+                delete_handle(dst_hnd);
+                delete_handle(src_hnd);
+                unmap_gpuaddr(ctx, mapped_dst_idx);
+                return COPYBIT_FAILURE;
+            }
+        }
+        src_hnd->fd = ctx->temp_src_buffer.fd;
+        src_hnd->size = ctx->temp_src_buffer.size;
+        src_hnd->flags = ctx->temp_src_buffer.allocType;
+        src_hnd->base = (uintptr_t)(ctx->temp_src_buffer.base);
+        src_hnd->offset = ctx->temp_src_buffer.offset;
+        src_hnd->gpuaddr = 0;
+        src_image.handle = src_hnd;
+
+        // Copy the source.
+        status = copy_image((private_handle_t *)src->handle, &src_image,
+                                CONVERT_TO_C2D_FORMAT);
+        if (status == COPYBIT_FAILURE) {
+            ALOGE("%s:copy_image failed in temp source",__FUNCTION__);
+            delete_handle(dst_hnd);
+            delete_handle(src_hnd);
+            unmap_gpuaddr(ctx, mapped_dst_idx);
+            return status;
+        }
+
+        // Clean the cache
+        IMemAlloc* memalloc = sAlloc->getAllocator(src_hnd->flags);
+        if (memalloc->clean_buffer((void *)(src_hnd->base), src_hnd->size,
+                                   src_hnd->offset, src_hnd->fd,
+                                   gralloc::CACHE_CLEAN)) {
+            ALOGE("%s: clean_buffer failed", __FUNCTION__);
+            delete_handle(dst_hnd);
+            delete_handle(src_hnd);
+            unmap_gpuaddr(ctx, mapped_dst_idx);
+            return COPYBIT_FAILURE;
+        }
+    }
+
+    flags |= (ctx->is_premultiplied_alpha) ? FLAGS_PREMULTIPLIED_ALPHA : 0;
+    flags |= (ctx->dst_surface_type != RGB_SURFACE) ? FLAGS_YUV_DESTINATION : 0;
+    status = set_image(ctx, src_surface.surface_id, &src_image,
+                       (eC2DFlags)flags, mapped_src_idx);
+    if(status) {
+        ALOGE("%s: set_image (src) error", __FUNCTION__);
+        delete_handle(dst_hnd);
+        delete_handle(src_hnd);
+        unmap_gpuaddr(ctx, mapped_dst_idx);
+        unmap_gpuaddr(ctx, mapped_src_idx);
+        return COPYBIT_FAILURE;
+    }
+
+    src_surface.config_mask = C2D_NO_ANTIALIASING_BIT | ctx->config_mask;
+    src_surface.global_alpha = ctx->src_global_alpha;
+    if (enableBlend) {
+        if(src_surface.config_mask & C2D_GLOBAL_ALPHA_BIT) {
+            src_surface.config_mask &= ~C2D_ALPHA_BLEND_NONE;
+            if(!(src_surface.global_alpha)) {
+                // src alpha is zero
+                delete_handle(dst_hnd);
+                delete_handle(src_hnd);
+                unmap_gpuaddr(ctx, mapped_dst_idx);
+                unmap_gpuaddr(ctx, mapped_src_idx);
+                return COPYBIT_FAILURE;
+            }
+        }
+    } else {
+        src_surface.config_mask |= C2D_ALPHA_BLEND_NONE;
+    }
+
+    if (src_surface_type == RGB_SURFACE) {
+        ctx->blit_rgb_object[ctx->blit_rgb_count] = src_surface;
+        ctx->blit_rgb_count++;
+    } else if (src_surface_type == YUV_SURFACE_2_PLANES) {
+        ctx->blit_yuv_2_plane_object[ctx->blit_yuv_2_plane_count] = src_surface;
+        ctx->blit_yuv_2_plane_count++;
+    } else {
+        ctx->blit_yuv_3_plane_object[ctx->blit_yuv_3_plane_count] = src_surface;
+        ctx->blit_yuv_3_plane_count++;
+    }
+
+    struct copybit_rect_t clip;
+    while ((status == 0) && region->next(region, &clip)) {
+        set_rects(ctx, &(src_surface), dst_rect, src_rect, &clip);
+        if (ctx->blit_count == MAX_BLIT_OBJECT_COUNT) {
+            ALOGW("Reached end of blit count");
+            finish_copybit(dev);
+        }
+        ctx->blit_list[ctx->blit_count] = src_surface;
+        ctx->blit_count++;
+    }
+
+    // Check if we need to perform an early draw-finish.
+    flags |= (need_temp_dst || need_temp_src) ? FLAGS_TEMP_SRC_DST : 0;
+    if (need_to_execute_draw((eC2DFlags)flags))
+    {
+        finish_copybit(dev);
+    }
+
+    if (need_temp_dst) {
+        // copy the temp. destination without the alignment to the actual
+        // destination.
+        status = copy_image(dst_hnd, dst, CONVERT_TO_ANDROID_FORMAT);
+        if (status == COPYBIT_FAILURE) {
+            ALOGE("%s:copy_image failed in temp Dest",__FUNCTION__);
+            delete_handle(dst_hnd);
+            delete_handle(src_hnd);
+            unmap_gpuaddr(ctx, mapped_dst_idx);
+            unmap_gpuaddr(ctx, mapped_src_idx);
+            return status;
+        }
+        // Clean the cache.
+        IMemAlloc* memalloc = sAlloc->getAllocator(dst_hnd->flags);
+        memalloc->clean_buffer((void *)(dst_hnd->base), dst_hnd->size,
+                               dst_hnd->offset, dst_hnd->fd,
+                               gralloc::CACHE_CLEAN);
+    }
+    delete_handle(dst_hnd);
+    delete_handle(src_hnd);
+
+    ctx->is_premultiplied_alpha = false;
+    ctx->fb_width = 0;
+    ctx->fb_height = 0;
+    ctx->config_mask = 0;
+    return status;
+}
+
+static int set_sync_copybit(struct copybit_device_t *dev,
+    int /*acquireFenceFd*/)
+{
+    if(!dev)
+        return -EINVAL;
+
+    return 0;
+}
+
+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 = COPYBIT_SUCCESS;
+    bool needsBlending = (ctx->src_global_alpha != 0);
+    pthread_mutex_lock(&ctx->wait_cleanup_lock);
+    status = stretch_copybit_internal(dev, dst, src, dst_rect, src_rect,
+                                    region, needsBlending);
+    pthread_mutex_unlock(&ctx->wait_cleanup_lock);
+    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)
+{
+    int status = COPYBIT_SUCCESS;
+    struct copybit_context_t* ctx = (struct copybit_context_t*)dev;
+    struct copybit_rect_t dr = { 0, 0, (int)dst->w, (int)dst->h };
+    struct copybit_rect_t sr = { 0, 0, (int)src->w, (int)src->h };
+    pthread_mutex_lock(&ctx->wait_cleanup_lock);
+    status = stretch_copybit_internal(dev, dst, src, &dr, &sr, region, false);
+    pthread_mutex_unlock(&ctx->wait_cleanup_lock);
+    return status;
+}
+
+/** Fill the rect on dst with RGBA color **/
+static int fill_color(struct copybit_device_t *dev,
+                      struct copybit_image_t const *dst,
+                      struct copybit_rect_t const *rect,
+                      uint32_t /*color*/)
+{
+    // TODO: Implement once c2d driver supports color fill
+    if(!dev || !dst || !rect)
+       return -EINVAL;
+
+    return -EINVAL;
+}
+
+/*****************************************************************************/
+
+static void clean_up(copybit_context_t* ctx)
+{
+    void* ret;
+    if (!ctx)
+        return;
+
+    // stop the wait_cleanup_thread
+    pthread_mutex_lock(&ctx->wait_cleanup_lock);
+    ctx->stop_thread = true;
+    // Signal waiting thread
+    pthread_cond_signal(&ctx->wait_cleanup_cond);
+    pthread_mutex_unlock(&ctx->wait_cleanup_lock);
+    // waits for the cleanup thread to exit
+    pthread_join(ctx->wait_thread_id, &ret);
+    pthread_mutex_destroy(&ctx->wait_cleanup_lock);
+    pthread_cond_destroy (&ctx->wait_cleanup_cond);
+
+    for (int i = 0; i < NUM_SURFACE_TYPES; i++) {
+        if (ctx->dst[i])
+            LINK_c2dDestroySurface(ctx->dst[i]);
+    }
+
+    for (int i = 0; i < MAX_RGB_SURFACES; i++) {
+        if (ctx->blit_rgb_object[i].surface_id)
+            LINK_c2dDestroySurface(ctx->blit_rgb_object[i].surface_id);
+    }
+
+    for (int i = 0; i < MAX_YUV_2_PLANE_SURFACES; i++) {
+        if (ctx->blit_yuv_2_plane_object[i].surface_id)
+            LINK_c2dDestroySurface(ctx->blit_yuv_2_plane_object[i].surface_id);
+    }
+
+    for (int i = 0; i < MAX_YUV_3_PLANE_SURFACES; i++) {
+        if (ctx->blit_yuv_3_plane_object[i].surface_id)
+            LINK_c2dDestroySurface(ctx->blit_yuv_3_plane_object[i].surface_id);
+    }
+
+    if (ctx->libc2d2) {
+        ::dlclose(ctx->libc2d2);
+        ALOGV("dlclose(libc2d2)");
+    }
+
+    free(ctx);
+}
+
+/** 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) {
+        free_temp_buffer(ctx->temp_src_buffer);
+        free_temp_buffer(ctx->temp_dst_buffer);
+    }
+    clean_up(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;
+    if (strcmp(name, COPYBIT_HARDWARE_COPYBIT0)) {
+        return COPYBIT_FAILURE;
+    }
+
+    C2D_RGB_SURFACE_DEF surfDefinition = {0};
+    C2D_YUV_SURFACE_DEF yuvSurfaceDef = {0} ;
+    struct copybit_context_t *ctx;
+
+    ctx = (struct copybit_context_t *)malloc(sizeof(struct copybit_context_t));
+    if(!ctx) {
+        ALOGE("%s: malloc failed", __FUNCTION__);
+        return COPYBIT_FAILURE;
+    }
+
+    /* initialize drawstate */
+    memset(ctx, 0, sizeof(*ctx));
+    ctx->libc2d2 = ::dlopen("libC2D2.so", RTLD_NOW);
+    if (!ctx->libc2d2) {
+        ALOGE("FATAL ERROR: could not dlopen libc2d2.so: %s", dlerror());
+        clean_up(ctx);
+        status = COPYBIT_FAILURE;
+        *device = NULL;
+        return status;
+    }
+    *(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");
+    *(void **)&LINK_c2dMapAddr = ::dlsym(ctx->libc2d2,
+                                         "c2dMapAddr");
+    *(void **)&LINK_c2dUnMapAddr = ::dlsym(ctx->libc2d2,
+                                           "c2dUnMapAddr");
+    *(void **)&LINK_c2dGetDriverCapabilities = ::dlsym(ctx->libc2d2,
+                                           "c2dGetDriverCapabilities");
+    *(void **)&LINK_c2dCreateFenceFD = ::dlsym(ctx->libc2d2,
+                                           "c2dCreateFenceFD");
+    *(void **)&LINK_c2dFillSurface = ::dlsym(ctx->libc2d2,
+                                           "c2dFillSurface");
+
+    if (!LINK_c2dCreateSurface || !LINK_c2dUpdateSurface || !LINK_c2dReadSurface
+        || !LINK_c2dDraw || !LINK_c2dFlush || !LINK_c2dWaitTimestamp ||
+        !LINK_c2dFinish  || !LINK_c2dDestroySurface ||
+        !LINK_c2dGetDriverCapabilities || !LINK_c2dCreateFenceFD ||
+        !LINK_c2dFillSurface) {
+        ALOGE("%s: dlsym ERROR", __FUNCTION__);
+        clean_up(ctx);
+        status = COPYBIT_FAILURE;
+        *device = NULL;
+        return status;
+    }
+
+    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.set_sync = set_sync_copybit;
+    ctx->device.stretch = stretch_copybit;
+    ctx->device.finish = finish_copybit;
+    ctx->device.flush_get_fence = flush_get_fence_copybit;
+    ctx->device.clear = clear_copybit;
+    ctx->device.fill_color = fill_color;
+
+    /* 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[RGB_SURFACE]), C2D_TARGET | C2D_SOURCE,
+                              (C2D_SURFACE_TYPE)(C2D_SURFACE_RGB_HOST |
+                                                 C2D_SURFACE_WITH_PHYS |
+                                                 C2D_SURFACE_WITH_PHYS_DUMMY ),
+                                                 &surfDefinition)) {
+        ALOGE("%s: create ctx->dst_surface[RGB_SURFACE] failed", __FUNCTION__);
+        ctx->dst[RGB_SURFACE] = 0;
+        clean_up(ctx);
+        status = COPYBIT_FAILURE;
+        *device = NULL;
+        return status;
+    }
+
+    unsigned int surface_id = 0;
+    for (int i = 0; i < MAX_RGB_SURFACES; i++)
+    {
+        if (LINK_c2dCreateSurface(&surface_id, C2D_TARGET | C2D_SOURCE,
+                              (C2D_SURFACE_TYPE)(C2D_SURFACE_RGB_HOST |
+                                                 C2D_SURFACE_WITH_PHYS |
+                                                 C2D_SURFACE_WITH_PHYS_DUMMY ),
+                                                 &surfDefinition)) {
+            ALOGE("%s: create RGB source surface %d failed", __FUNCTION__, i);
+            ctx->blit_rgb_object[i].surface_id = 0;
+            status = COPYBIT_FAILURE;
+            break;
+        } else {
+            ctx->blit_rgb_object[i].surface_id = surface_id;
+            ALOGW("%s i = %d surface_id=%d",  __FUNCTION__, i,
+                                          ctx->blit_rgb_object[i].surface_id);
+        }
+    }
+
+    if (status == COPYBIT_FAILURE) {
+        clean_up(ctx);
+        status = COPYBIT_FAILURE;
+        *device = NULL;
+        return status;
+    }
+
+    // Create 2 plane YUV surfaces
+    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->dst[YUV_SURFACE_2_PLANES]),
+                              C2D_TARGET | C2D_SOURCE,
+                              (C2D_SURFACE_TYPE)(C2D_SURFACE_YUV_HOST |
+                               C2D_SURFACE_WITH_PHYS |
+                               C2D_SURFACE_WITH_PHYS_DUMMY),
+                              &yuvSurfaceDef)) {
+        ALOGE("%s: create ctx->dst[YUV_SURFACE_2_PLANES] failed", __FUNCTION__);
+        ctx->dst[YUV_SURFACE_2_PLANES] = 0;
+        clean_up(ctx);
+        status = COPYBIT_FAILURE;
+        *device = NULL;
+        return status;
+    }
+
+    for (int i=0; i < MAX_YUV_2_PLANE_SURFACES; i++)
+    {
+        if (LINK_c2dCreateSurface(&surface_id, C2D_TARGET | C2D_SOURCE,
+                              (C2D_SURFACE_TYPE)(C2D_SURFACE_YUV_HOST |
+                                                 C2D_SURFACE_WITH_PHYS |
+                                                 C2D_SURFACE_WITH_PHYS_DUMMY ),
+                              &yuvSurfaceDef)) {
+            ALOGE("%s: create YUV source %d failed", __FUNCTION__, i);
+            ctx->blit_yuv_2_plane_object[i].surface_id = 0;
+            status = COPYBIT_FAILURE;
+            break;
+        } else {
+            ctx->blit_yuv_2_plane_object[i].surface_id = surface_id;
+            ALOGW("%s: 2 Plane YUV i=%d surface_id=%d",  __FUNCTION__, i,
+                                   ctx->blit_yuv_2_plane_object[i].surface_id);
+        }
+    }
+
+    if (status == COPYBIT_FAILURE) {
+        clean_up(ctx);
+        status = COPYBIT_FAILURE;
+        *device = NULL;
+        return status;
+    }
+
+    // Create YUV 3 plane surfaces
+    yuvSurfaceDef.format = C2D_COLOR_FORMAT_420_YV12;
+    yuvSurfaceDef.plane2 = (void*)0xaaaaaaaa;
+    yuvSurfaceDef.phys2 = (void*) 0xaaaaaaaa;
+    yuvSurfaceDef.stride2 = 4;
+
+    if (LINK_c2dCreateSurface(&(ctx->dst[YUV_SURFACE_3_PLANES]),
+                              C2D_TARGET | C2D_SOURCE,
+                              (C2D_SURFACE_TYPE)(C2D_SURFACE_YUV_HOST |
+                                                 C2D_SURFACE_WITH_PHYS |
+                                                 C2D_SURFACE_WITH_PHYS_DUMMY),
+                              &yuvSurfaceDef)) {
+        ALOGE("%s: create ctx->dst[YUV_SURFACE_3_PLANES] failed", __FUNCTION__);
+        ctx->dst[YUV_SURFACE_3_PLANES] = 0;
+        clean_up(ctx);
+        status = COPYBIT_FAILURE;
+        *device = NULL;
+        return status;
+    }
+
+    for (int i=0; i < MAX_YUV_3_PLANE_SURFACES; i++)
+    {
+        if (LINK_c2dCreateSurface(&(surface_id),
+                              C2D_TARGET | C2D_SOURCE,
+                              (C2D_SURFACE_TYPE)(C2D_SURFACE_YUV_HOST |
+                                                 C2D_SURFACE_WITH_PHYS |
+                                                 C2D_SURFACE_WITH_PHYS_DUMMY),
+                              &yuvSurfaceDef)) {
+            ALOGE("%s: create 3 plane YUV surface %d failed", __FUNCTION__, i);
+            ctx->blit_yuv_3_plane_object[i].surface_id = 0;
+            status = COPYBIT_FAILURE;
+            break;
+        } else {
+            ctx->blit_yuv_3_plane_object[i].surface_id = surface_id;
+            ALOGW("%s: 3 Plane YUV i=%d surface_id=%d",  __FUNCTION__, i,
+                                   ctx->blit_yuv_3_plane_object[i].surface_id);
+        }
+    }
+
+    if (status == COPYBIT_FAILURE) {
+        clean_up(ctx);
+        status = COPYBIT_FAILURE;
+        *device = NULL;
+        return status;
+    }
+
+    if (LINK_c2dGetDriverCapabilities(&(ctx->c2d_driver_info))) {
+         ALOGE("%s: LINK_c2dGetDriverCapabilities failed", __FUNCTION__);
+         clean_up(ctx);
+         status = COPYBIT_FAILURE;
+        *device = NULL;
+        return status;
+    }
+    // Initialize context variables.
+    ctx->trg_transform = C2D_TARGET_ROTATE_0;
+
+    ctx->temp_src_buffer.fd = -1;
+    ctx->temp_src_buffer.base = 0;
+    ctx->temp_src_buffer.size = 0;
+
+    ctx->temp_dst_buffer.fd = -1;
+    ctx->temp_dst_buffer.base = 0;
+    ctx->temp_dst_buffer.size = 0;
+
+    ctx->fb_width = 0;
+    ctx->fb_height = 0;
+
+    ctx->blit_rgb_count = 0;
+    ctx->blit_yuv_2_plane_count = 0;
+    ctx->blit_yuv_3_plane_count = 0;
+    ctx->blit_count = 0;
+
+    ctx->wait_timestamp = false;
+    ctx->stop_thread = false;
+    pthread_mutex_init(&(ctx->wait_cleanup_lock), NULL);
+    pthread_cond_init(&(ctx->wait_cleanup_cond), NULL);
+    /* Start the wait thread */
+    pthread_attr_t attr;
+    pthread_attr_init(&attr);
+    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
+
+    pthread_create(&ctx->wait_thread_id, &attr, &c2d_wait_loop,
+                                                            (void *)ctx);
+    pthread_attr_destroy(&attr);
+
+    *device = &ctx->device.common;
+    return status;
+}
diff --git a/msm8909/libcopybit/copybit_priv.h b/msm8909/libcopybit/copybit_priv.h
new file mode 100644
index 0000000..68dfac4
--- /dev/null
+++ b/msm8909/libcopybit/copybit_priv.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2011, The Linux Foundation. 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 The Linux Foundation 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.
+ */
+
+#include <copybit.h>
+struct copybit_iterator : public copybit_region_t {
+    copybit_iterator(const copybit_rect_t& rect) {
+        mRect = rect;
+        mCount = 1;
+        this->next = iterate;
+    }
+private:
+    static int iterate(copybit_region_t const * self, copybit_rect_t* rect) {
+        if (!self || !rect) {
+            return 0;
+        }
+
+        copybit_iterator const* me = static_cast<copybit_iterator const*>(self);
+        if (me->mCount) {
+            rect->l = me->mRect.l;
+            rect->t = me->mRect.t;
+            rect->r = me->mRect.r;
+            rect->b = me->mRect.b;
+            me->mCount--;
+            return 1;
+        }
+        return 0;
+    }
+    copybit_rect_t mRect;
+    mutable int mCount;
+};
diff --git a/msm8909/libcopybit/software_converter.cpp b/msm8909/libcopybit/software_converter.cpp
new file mode 100644
index 0000000..e5c03b5
--- /dev/null
+++ b/msm8909/libcopybit/software_converter.cpp
@@ -0,0 +1,263 @@
+/*
+ * Copyright (c) 2011-2014, The Linux Foundation. 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 The Linux Foundation 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.
+ */
+
+#include <cutils/log.h>
+#include <stdlib.h>
+#include <errno.h>
+#include "software_converter.h"
+
+/** Convert YV12 to YCrCb_420_SP */
+int convertYV12toYCrCb420SP(const copybit_image_t *src, private_handle_t *yv12_handle)
+{
+    private_handle_t* hnd = (private_handle_t*)src->handle;
+
+    if(hnd == NULL || yv12_handle == NULL){
+        ALOGE("Invalid handle");
+        return -1;
+    }
+
+    // Please refer to the description of YV12 in hardware.h
+    // for the formulae used to calculate buffer sizes and offsets
+
+    // In a copybit_image_t, w is the stride and
+    // stride - horiz_padding is the actual width
+    // vertical stride is the same as height, so not considered
+    unsigned int   stride  = src->w;
+    unsigned int   width   = src->w - src->horiz_padding;
+    unsigned int   height  = src->h;
+    unsigned int   y_size  = stride * src->h;
+    unsigned int   c_width = ALIGN(stride/2, (unsigned int)16);
+    unsigned int   c_size  = c_width * src->h/2;
+    unsigned int   chromaPadding = c_width - width/2;
+    unsigned int   chromaSize = c_size * 2;
+    unsigned char* newChroma = (unsigned char *)(yv12_handle->base + y_size);
+    unsigned char* oldChroma = (unsigned char*)(hnd->base + y_size);
+    memcpy((char *)yv12_handle->base,(char *)hnd->base,y_size);
+
+#if defined(__ARM_HAVE_NEON) && !defined(__aarch64__)
+   /* interleave */
+    if(!chromaPadding) {
+        unsigned char * t1 = newChroma;
+        unsigned char * t2 = oldChroma;
+        unsigned char * t3 = t2 + chromaSize/2;
+        for(unsigned int i=0; i < (chromaSize/2)>>3; i++) {
+            __asm__ __volatile__ (
+                                    "vld1.u8 d0, [%0]! \n"
+                                    "vld1.u8 d1, [%1]! \n"
+                                    "vst2.u8 {d0, d1}, [%2]! \n"
+                                    :"+r"(t2), "+r"(t3), "+r"(t1)
+                                    :
+                                    :"memory","d0","d1"
+                                 );
+
+        }
+    }
+#else  //__ARM_HAVE_NEON
+    if(!chromaPadding) {
+        for(unsigned int i = 0; i< chromaSize/2; i++) {
+            newChroma[i*2]   = oldChroma[i];
+            newChroma[i*2+1] = oldChroma[i+chromaSize/2];
+        }
+
+    }
+#endif
+    // If the image is not aligned to 16 pixels,
+    // convert using the C routine below
+    // r1 tracks the row of the source buffer
+    // r2 tracks the row of the destination buffer
+    // The width/2 checks are to avoid copying
+    // from the padding
+
+    if(chromaPadding) {
+        unsigned int r1 = 0, r2 = 0, i = 0, j = 0;
+        while(r1 < height/2) {
+            if(j == width) {
+                j = 0;
+                r2++;
+                continue;
+            }
+            if (j+1 == width) {
+                newChroma[r2*width + j] = oldChroma[r1*c_width+i];
+                r2++;
+                newChroma[r2*width] = oldChroma[r1*c_width+i+c_size];
+                j = 1;
+            } else {
+                newChroma[r2*width + j] = oldChroma[r1*c_width+i];
+                newChroma[r2*width + j + 1] = oldChroma[r1*c_width+i+c_size];
+                j+=2;
+            }
+            i++;
+            if (i == width/2 ) {
+                i = 0;
+                r1++;
+            }
+        }
+    }
+
+  return 0;
+}
+
+struct copyInfo{
+    int width;
+    int height;
+    int src_stride;
+    int dst_stride;
+    size_t src_plane1_offset;
+    size_t src_plane2_offset;
+    size_t dst_plane1_offset;
+    size_t dst_plane2_offset;
+};
+
+/* Internal function to do the actual copy of source to destination */
+static int copy_source_to_destination(const uintptr_t src_base,
+                                      const uintptr_t dst_base,
+                                      copyInfo& info)
+{
+    if (!src_base || !dst_base) {
+        ALOGE("%s: invalid memory src_base = 0x%p dst_base=0x%p",
+             __FUNCTION__, (void*)src_base, (void*)dst_base);
+         return COPYBIT_FAILURE;
+    }
+
+    int width = info.width;
+    int height = info.height;
+    unsigned char *src = (unsigned char*)src_base;
+    unsigned char *dst = (unsigned char*)dst_base;
+
+    // Copy the luma
+    for (int i = 0; i < height; i++) {
+        memcpy(dst, src, width);
+        src += info.src_stride;
+        dst += info.dst_stride;
+    }
+
+    // Copy plane 1
+    src = (unsigned char*)(src_base + info.src_plane1_offset);
+    dst = (unsigned char*)(dst_base + info.dst_plane1_offset);
+    width = width/2;
+    height = height/2;
+    for (int i = 0; i < height; i++) {
+        memcpy(dst, src, info.src_stride);
+        src += info.src_stride;
+        dst += info.dst_stride;
+    }
+    return 0;
+}
+
+
+/*
+ * Function to convert the c2d format into an equivalent Android format
+ *
+ * @param: source buffer handle
+ * @param: destination image
+ *
+ * @return: return status
+ */
+int convert_yuv_c2d_to_yuv_android(private_handle_t *hnd,
+                                   struct copybit_image_t const *rhs)
+{
+    ALOGD("Enter %s", __FUNCTION__);
+    if (!hnd || !rhs) {
+        ALOGE("%s: invalid inputs hnd=%p rhs=%p", __FUNCTION__, hnd, rhs);
+        return COPYBIT_FAILURE;
+    }
+
+    int ret = COPYBIT_SUCCESS;
+    private_handle_t *dst_hnd = (private_handle_t *)rhs->handle;
+
+    copyInfo info;
+    info.width = rhs->w;
+    info.height = rhs->h;
+    info.src_stride = ALIGN(info.width, 32);
+    info.dst_stride = ALIGN(info.width, 16);
+    switch(rhs->format) {
+        case HAL_PIXEL_FORMAT_YCbCr_420_SP:
+        case HAL_PIXEL_FORMAT_YCrCb_420_SP: {
+            info.src_plane1_offset = info.src_stride*info.height;
+            info.dst_plane1_offset = info.dst_stride*info.height;
+        } break;
+        case HAL_PIXEL_FORMAT_NV12_ENCODEABLE: {
+            // Chroma is 2K aligned for the NV12 encodeable format.
+            info.src_plane1_offset = ALIGN(info.src_stride*info.height, 2048);
+            info.dst_plane1_offset = ALIGN(info.dst_stride*info.height, 2048);
+        } break;
+        default:
+            ALOGE("%s: unsupported format (format=0x%x)", __FUNCTION__,
+                 rhs->format);
+            return COPYBIT_FAILURE;
+    }
+
+    ret = copy_source_to_destination((uintptr_t) hnd->base, (uintptr_t) dst_hnd->base, info);
+    return ret;
+}
+
+/*
+ * Function to convert the Android format into an equivalent C2D format
+ *
+ * @param: source buffer handle
+ * @param: destination image
+ *
+ * @return: return status
+ */
+int convert_yuv_android_to_yuv_c2d(private_handle_t *hnd,
+                                   struct copybit_image_t const *rhs)
+{
+    if (!hnd || !rhs) {
+        ALOGE("%s: invalid inputs hnd=%p rhs=%p", __FUNCTION__, hnd, rhs);
+        return COPYBIT_FAILURE;
+    }
+
+    int ret = COPYBIT_SUCCESS;
+    private_handle_t *dst_hnd = (private_handle_t *)rhs->handle;
+
+    copyInfo info;
+    info.width = rhs->w;
+    info.height = rhs->h;
+    info.src_stride = ALIGN(hnd->width, 16);
+    info.dst_stride = ALIGN(info.width, 32);
+    switch(rhs->format) {
+        case HAL_PIXEL_FORMAT_YCbCr_420_SP:
+        case HAL_PIXEL_FORMAT_YCrCb_420_SP: {
+            info.src_plane1_offset = info.src_stride*info.height;
+            info.dst_plane1_offset = info.dst_stride*info.height;
+        } break;
+        case HAL_PIXEL_FORMAT_NV12_ENCODEABLE: {
+            // Chroma is 2K aligned for the NV12 encodeable format.
+            info.src_plane1_offset = ALIGN(info.src_stride*info.height, 2048);
+            info.dst_plane1_offset = ALIGN(info.dst_stride*info.height, 2048);
+        } break;
+        default:
+            ALOGE("%s: unsupported format (format=0x%x)", __FUNCTION__,
+                 rhs->format);
+            return -1;
+    }
+
+    ret = copy_source_to_destination((uintptr_t) hnd->base, (uintptr_t) dst_hnd->base, info);
+    return ret;
+}
diff --git a/msm8909/libcopybit/software_converter.h b/msm8909/libcopybit/software_converter.h
new file mode 100644
index 0000000..6e53e16
--- /dev/null
+++ b/msm8909/libcopybit/software_converter.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2011, The Linux Foundation. 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 The Linux Foundation 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.
+ */
+
+
+
+#include <copybit.h>
+#include "gralloc_priv.h"
+#include "gr.h"
+
+#define COPYBIT_SUCCESS 0
+#define COPYBIT_FAILURE -1
+
+int convertYV12toYCrCb420SP(const copybit_image_t *src,private_handle_t *yv12_handle);
+
+/*
+ * Function to convert the c2d format into an equivalent Android format
+ *
+ * @param: source buffer handle
+ * @param: destination image
+ *
+ * @return: return status
+ */
+int convert_yuv_c2d_to_yuv_android(private_handle_t *hnd,
+                                   struct copybit_image_t const *rhs);
+
+
+/*
+ * Function to convert the Android format into an equivalent C2D format
+ *
+ * @param: source buffer handle
+ * @param: destination image
+ *
+ * @return: return status
+ */
+int convert_yuv_android_to_yuv_c2d(private_handle_t *hnd,
+                                   struct copybit_image_t const *rhs);
diff --git a/msm8909/libgralloc/Android.mk b/msm8909/libgralloc/Android.mk
new file mode 100644
index 0000000..412f1be
--- /dev/null
+++ b/msm8909/libgralloc/Android.mk
@@ -0,0 +1,46 @@
+# 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.
+
+# Gralloc module
+LOCAL_PATH := $(call my-dir)
+include $(LOCAL_PATH)/../common.mk
+include $(CLEAR_VARS)
+
+LOCAL_MODULE                  := gralloc.$(TARGET_BOARD_PLATFORM)
+LOCAL_MODULE_RELATIVE_PATH    := hw
+LOCAL_MODULE_TAGS             := optional
+LOCAL_C_INCLUDES              := $(common_includes) $(kernel_includes)
+LOCAL_SHARED_LIBRARIES        := $(common_libs) libmemalloc libqdMetaData
+LOCAL_SHARED_LIBRARIES        += libqdutils libGLESv1_CM
+LOCAL_CFLAGS                  := $(common_flags) -DLOG_TAG=\"qdgralloc\"
+LOCAL_ADDITIONAL_DEPENDENCIES := $(common_deps) $(kernel_deps)
+LOCAL_SRC_FILES               := gpu.cpp gralloc.cpp framebuffer.cpp mapper.cpp
+LOCAL_COPY_HEADERS_TO         := $(common_header_export_path)
+LOCAL_COPY_HEADERS            := gralloc_priv.h gr.h
+
+include $(BUILD_SHARED_LIBRARY)
+
+# MemAlloc Library
+include $(CLEAR_VARS)
+
+LOCAL_MODULE                  := libmemalloc
+LOCAL_MODULE_TAGS             := optional
+LOCAL_C_INCLUDES              := $(common_includes) $(kernel_includes)
+LOCAL_SHARED_LIBRARIES        := $(common_libs) libqdutils libdl
+LOCAL_CFLAGS                  := $(common_flags) -DLOG_TAG=\"qdmemalloc\"
+LOCAL_ADDITIONAL_DEPENDENCIES := $(common_deps) $(kernel_deps)
+LOCAL_SRC_FILES               := ionalloc.cpp alloc_controller.cpp
+LOCAL_COPY_HEADERS            := alloc_controller.h memalloc.h
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/msm8909/libgralloc/MODULE_LICENSE_APACHE2 b/msm8909/libgralloc/MODULE_LICENSE_APACHE2
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/msm8909/libgralloc/MODULE_LICENSE_APACHE2
diff --git a/msm8909/libgralloc/NOTICE b/msm8909/libgralloc/NOTICE
new file mode 100644
index 0000000..3237da6
--- /dev/null
+++ b/msm8909/libgralloc/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/msm8909/libgralloc/alloc_controller.cpp b/msm8909/libgralloc/alloc_controller.cpp
new file mode 100644
index 0000000..3172c47
--- /dev/null
+++ b/msm8909/libgralloc/alloc_controller.cpp
@@ -0,0 +1,676 @@
+/*
+ * Copyright (c) 2011-2014, The Linux Foundation. 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 The Linux Foundation 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.
+ */
+
+#include <cutils/log.h>
+#include <fcntl.h>
+#include <dlfcn.h>
+#include "gralloc_priv.h"
+#include "alloc_controller.h"
+#include "memalloc.h"
+#include "ionalloc.h"
+#include "gr.h"
+#include "comptype.h"
+#include "mdp_version.h"
+
+#ifdef VENUS_COLOR_FORMAT
+#include <media/msm_media_info.h>
+#else
+#define VENUS_Y_STRIDE(args...) 0
+#define VENUS_Y_SCANLINES(args...) 0
+#define VENUS_BUFFER_SIZE(args...) 0
+#endif
+
+#define ASTC_BLOCK_SIZE 16
+
+using namespace gralloc;
+using namespace qdutils;
+
+ANDROID_SINGLETON_STATIC_INSTANCE(AdrenoMemInfo);
+
+//Common functions
+static bool canFallback(int usage, bool triedSystem)
+{
+    // Fallback to system heap when alloc fails unless
+    // 1. Composition type is MDP
+    // 2. Alloc from system heap was already tried
+    // 3. The heap type is requsted explicitly
+    // 4. The heap type is protected
+    // 5. The buffer is meant for external display only
+
+    if(QCCompositionType::getInstance().getCompositionType() &
+       COMPOSITION_TYPE_MDP)
+        return false;
+    if(triedSystem)
+        return false;
+    if(usage & (GRALLOC_HEAP_MASK | GRALLOC_USAGE_PROTECTED))
+        return false;
+    if(usage & (GRALLOC_HEAP_MASK | GRALLOC_USAGE_PRIVATE_EXTERNAL_ONLY))
+        return false;
+    //Return true by default
+    return true;
+}
+
+/* The default policy is to return cached buffers unless the client explicity
+ * sets the PRIVATE_UNCACHED flag or indicates that the buffer will be rarely
+ * read or written in software. Any combination with a _RARELY_ flag will be
+ * treated as uncached. */
+static bool useUncached(const int& usage) {
+    if((usage & GRALLOC_USAGE_PRIVATE_UNCACHED) or
+            ((usage & GRALLOC_USAGE_SW_WRITE_MASK) ==
+            GRALLOC_USAGE_SW_WRITE_RARELY) or
+            ((usage & GRALLOC_USAGE_SW_READ_MASK) ==
+            GRALLOC_USAGE_SW_READ_RARELY))
+        return true;
+
+    return false;
+}
+
+//-------------- AdrenoMemInfo-----------------------//
+AdrenoMemInfo::AdrenoMemInfo()
+{
+    LINK_adreno_compute_aligned_width_and_height = NULL;
+    LINK_adreno_compute_padding = NULL;
+    LINK_adreno_isMacroTilingSupportedByGpu = NULL;
+    LINK_adreno_compute_compressedfmt_aligned_width_and_height = NULL;
+    LINK_adreno_get_gpu_pixel_alignment = NULL;
+
+    libadreno_utils = ::dlopen("libadreno_utils.so", RTLD_NOW);
+    if (libadreno_utils) {
+        *(void **)&LINK_adreno_compute_aligned_width_and_height =
+                ::dlsym(libadreno_utils, "compute_aligned_width_and_height");
+        *(void **)&LINK_adreno_compute_padding =
+                ::dlsym(libadreno_utils, "compute_surface_padding");
+        *(void **)&LINK_adreno_isMacroTilingSupportedByGpu =
+                ::dlsym(libadreno_utils, "isMacroTilingSupportedByGpu");
+        *(void **)&LINK_adreno_compute_compressedfmt_aligned_width_and_height =
+                ::dlsym(libadreno_utils,
+                        "compute_compressedfmt_aligned_width_and_height");
+        *(void **)&LINK_adreno_get_gpu_pixel_alignment =
+                ::dlsym(libadreno_utils, "get_gpu_pixel_alignment");
+    }
+}
+
+AdrenoMemInfo::~AdrenoMemInfo()
+{
+    if (libadreno_utils) {
+        ::dlclose(libadreno_utils);
+    }
+}
+
+int AdrenoMemInfo::isMacroTilingSupportedByGPU()
+{
+    if ((libadreno_utils)) {
+        if(LINK_adreno_isMacroTilingSupportedByGpu) {
+            return LINK_adreno_isMacroTilingSupportedByGpu();
+        }
+    }
+    return 0;
+}
+
+
+void AdrenoMemInfo::getAlignedWidthAndHeight(int width, int height, int format,
+                            int tile_enabled, int& aligned_w, int& aligned_h)
+{
+    aligned_w = width;
+    aligned_h = height;
+    // Currently surface padding is only computed for RGB* surfaces.
+    if (format <= HAL_PIXEL_FORMAT_BGRA_8888) {
+        aligned_w = ALIGN(width, 32);
+        aligned_h = ALIGN(height, 32);
+        // Don't add any additional padding if debug.gralloc.map_fb_memory
+        // is enabled
+        char property[PROPERTY_VALUE_MAX];
+        if((property_get("debug.gralloc.map_fb_memory", property, NULL) > 0) &&
+           (!strncmp(property, "1", PROPERTY_VALUE_MAX ) ||
+           (!strncasecmp(property,"true", PROPERTY_VALUE_MAX )))) {
+              return;
+        }
+
+        int bpp = 4;
+        switch(format)
+        {
+            case HAL_PIXEL_FORMAT_RGB_888:
+                bpp = 3;
+                break;
+            case HAL_PIXEL_FORMAT_RGB_565:
+                bpp = 2;
+                break;
+            default: break;
+        }
+        if (libadreno_utils) {
+            int raster_mode         = 0;   // Adreno unknown raster mode.
+            int padding_threshold   = 512; // Threshold for padding surfaces.
+            // the function below computes aligned width and aligned height
+            // based on linear or macro tile mode selected.
+            if(LINK_adreno_compute_aligned_width_and_height) {
+                LINK_adreno_compute_aligned_width_and_height(width,
+                                     height, bpp, tile_enabled,
+                                     raster_mode, padding_threshold,
+                                     &aligned_w, &aligned_h);
+
+            } else if(LINK_adreno_compute_padding) {
+                int surface_tile_height = 1;   // Linear surface
+                aligned_w = LINK_adreno_compute_padding(width, bpp,
+                                     surface_tile_height, raster_mode,
+                                     padding_threshold);
+                ALOGW("%s: Warning!! Old GFX API is used to calculate stride",
+                                                            __FUNCTION__);
+            } else {
+                ALOGW("%s: Warning!! Symbols compute_surface_padding and " \
+                    "compute_aligned_width_and_height not found", __FUNCTION__);
+            }
+        }
+    } else {
+        int alignment = 32;
+        switch (format)
+        {
+            case HAL_PIXEL_FORMAT_YCrCb_420_SP:
+            case HAL_PIXEL_FORMAT_YCbCr_420_SP:
+                if (LINK_adreno_get_gpu_pixel_alignment) {
+                    alignment = LINK_adreno_get_gpu_pixel_alignment();
+                }
+                aligned_w = ALIGN(width, alignment);
+                break;
+            case HAL_PIXEL_FORMAT_YCrCb_420_SP_ADRENO:
+                aligned_w = ALIGN(width, alignment);
+                break;
+            case HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED:
+                aligned_w = ALIGN(width, 128);
+                break;
+            case HAL_PIXEL_FORMAT_YV12:
+            case HAL_PIXEL_FORMAT_YCbCr_422_SP:
+            case HAL_PIXEL_FORMAT_YCrCb_422_SP:
+            case HAL_PIXEL_FORMAT_YCbCr_422_I:
+            case HAL_PIXEL_FORMAT_YCrCb_422_I:
+                aligned_w = ALIGN(width, 16);
+                break;
+            case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS:
+            case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:
+                aligned_w = VENUS_Y_STRIDE(COLOR_FMT_NV12, width);
+                aligned_h = VENUS_Y_SCANLINES(COLOR_FMT_NV12, height);
+                break;
+            case HAL_PIXEL_FORMAT_BLOB:
+                break;
+            case HAL_PIXEL_FORMAT_NV21_ZSL:
+                aligned_w = ALIGN(width, 64);
+                aligned_h = ALIGN(height, 64);
+                break;
+            case HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_4x4_KHR:
+            case HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR:
+            case HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_5x4_KHR:
+            case HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR:
+            case HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_5x5_KHR:
+            case HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR:
+            case HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_6x5_KHR:
+            case HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR:
+            case HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_6x6_KHR:
+            case HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR:
+            case HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_8x5_KHR:
+            case HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR:
+            case HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_8x6_KHR:
+            case HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR:
+            case HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_8x8_KHR:
+            case HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR:
+            case HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_10x5_KHR:
+            case HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR:
+            case HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_10x6_KHR:
+            case HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR:
+            case HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_10x8_KHR:
+            case HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR:
+            case HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_10x10_KHR:
+            case HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR:
+            case HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_12x10_KHR:
+            case HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR:
+            case HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_12x12_KHR:
+            case HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR:
+                if(LINK_adreno_compute_compressedfmt_aligned_width_and_height) {
+                    int bytesPerPixel = 0;
+                    int raster_mode         = 0;   //Adreno unknown raster mode.
+                    int padding_threshold   = 512; //Threshold for padding
+                    //surfaces.
+
+                    LINK_adreno_compute_compressedfmt_aligned_width_and_height(
+                        width, height, format, 0,raster_mode, padding_threshold,
+                        &aligned_w, &aligned_h, &bytesPerPixel);
+
+                } else {
+                    ALOGW("%s: Warning!! Symbols" \
+                          " compute_compressedfmt_aligned_width_and_height" \
+                          " not found", __FUNCTION__);
+                }
+                break;
+            default: break;
+        }
+    }
+}
+
+//-------------- IAllocController-----------------------//
+IAllocController* IAllocController::sController = NULL;
+IAllocController* IAllocController::getInstance(void)
+{
+    if(sController == NULL) {
+        sController = new IonController();
+    }
+    return sController;
+}
+
+
+//-------------- IonController-----------------------//
+IonController::IonController()
+{
+    allocateIonMem();
+}
+
+void IonController::allocateIonMem()
+{
+   mIonAlloc = new IonAlloc();
+}
+
+int IonController::allocate(alloc_data& data, int usage)
+{
+    int ionFlags = 0;
+    int ret;
+
+    data.uncached = useUncached(usage);
+    data.allocType = 0;
+
+    if(usage & GRALLOC_USAGE_PRIVATE_UI_CONTIG_HEAP)
+        ionFlags |= ION_HEAP(ION_SF_HEAP_ID);
+
+    if(usage & GRALLOC_USAGE_PRIVATE_SYSTEM_HEAP)
+        ionFlags |= ION_HEAP(ION_SYSTEM_HEAP_ID);
+
+    if(usage & GRALLOC_USAGE_PRIVATE_IOMMU_HEAP)
+        ionFlags |= ION_HEAP(ION_IOMMU_HEAP_ID);
+
+    if(usage & GRALLOC_USAGE_PROTECTED) {
+        if (usage & GRALLOC_USAGE_PRIVATE_MM_HEAP) {
+            ionFlags |= ION_HEAP(ION_CP_MM_HEAP_ID);
+            ionFlags |= ION_SECURE;
+        } else {
+            // for targets/OEMs which do not need HW level protection
+            // do not set ion secure flag & MM heap. Fallback to IOMMU heap.
+            ionFlags |= ION_HEAP(ION_IOMMU_HEAP_ID);
+        }
+    } else if(usage & GRALLOC_USAGE_PRIVATE_MM_HEAP) {
+        //MM Heap is exclusively a secure heap.
+        //If it is used for non secure cases, fallback to IOMMU heap
+        ALOGW("GRALLOC_USAGE_PRIVATE_MM_HEAP \
+                                cannot be used as an insecure heap!\
+                                trying to use IOMMU instead !!");
+        ionFlags |= ION_HEAP(ION_IOMMU_HEAP_ID);
+    }
+
+    if(usage & GRALLOC_USAGE_PRIVATE_CAMERA_HEAP)
+        ionFlags |= ION_HEAP(ION_CAMERA_HEAP_ID);
+
+    if(usage & GRALLOC_USAGE_PRIVATE_ADSP_HEAP)
+        ionFlags |= ION_HEAP(ION_ADSP_HEAP_ID);
+
+    if(ionFlags & ION_SECURE)
+         data.allocType |= private_handle_t::PRIV_FLAGS_SECURE_BUFFER;
+
+    // if no flags are set, default to
+    // SF + IOMMU heaps, so that bypass can work
+    // we can fall back to system heap if
+    // we run out.
+    if(!ionFlags)
+        ionFlags = ION_HEAP(ION_SF_HEAP_ID) | ION_HEAP(ION_IOMMU_HEAP_ID);
+
+    data.flags = ionFlags;
+    ret = mIonAlloc->alloc_buffer(data);
+
+    // Fallback
+    if(ret < 0 && canFallback(usage,
+                              (ionFlags & ION_SYSTEM_HEAP_ID)))
+    {
+        ALOGW("Falling back to system heap");
+        data.flags = ION_HEAP(ION_SYSTEM_HEAP_ID);
+        ret = mIonAlloc->alloc_buffer(data);
+    }
+
+    if(ret >= 0 ) {
+        data.allocType |= private_handle_t::PRIV_FLAGS_USES_ION;
+    }
+
+    return ret;
+}
+
+IMemAlloc* IonController::getAllocator(int flags)
+{
+    IMemAlloc* memalloc = NULL;
+    if (flags & private_handle_t::PRIV_FLAGS_USES_ION) {
+        memalloc = mIonAlloc;
+    } else {
+        ALOGE("%s: Invalid flags passed: 0x%x", __FUNCTION__, flags);
+    }
+
+    return memalloc;
+}
+
+bool isMacroTileEnabled(int format, int usage)
+{
+    bool tileEnabled = false;
+
+    // Check whether GPU & MDSS supports MacroTiling feature
+    if(AdrenoMemInfo::getInstance().isMacroTilingSupportedByGPU() &&
+            qdutils::MDPVersion::getInstance().supportsMacroTile())
+    {
+        // check the format
+        switch(format)
+        {
+            case  HAL_PIXEL_FORMAT_RGBA_8888:
+            case  HAL_PIXEL_FORMAT_RGBX_8888:
+            case  HAL_PIXEL_FORMAT_BGRA_8888:
+            case  HAL_PIXEL_FORMAT_RGB_565:
+                {
+                    tileEnabled = true;
+                    // check the usage flags
+                    if (usage & (GRALLOC_USAGE_SW_READ_MASK |
+                                GRALLOC_USAGE_SW_WRITE_MASK)) {
+                        // Application intends to use CPU for rendering
+                        tileEnabled = false;
+                    }
+                    break;
+                }
+            default:
+                break;
+        }
+    }
+    return tileEnabled;
+}
+
+// helper function
+unsigned int getSize(int format, int width, int height, const int alignedw,
+        const int alignedh) {
+    unsigned int size = 0;
+
+    switch (format) {
+        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_RAW16:
+            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(width/2, 32) * ALIGN(height/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
+            size  = ALIGN( alignedw * alignedh, 8192);
+            size += ALIGN( alignedw * ALIGN(height/2, 32), 8192);
+            break;
+        case HAL_PIXEL_FORMAT_YV12:
+            if ((format == HAL_PIXEL_FORMAT_YV12) && ((width&1) || (height&1))) {
+                ALOGE("w or h is odd for the YV12 format");
+                return 0;
+            }
+            size = alignedw*alignedh +
+                    (ALIGN(alignedw/2, 16) * (alignedh/2))*2;
+            size = ALIGN(size, (unsigned int)4096);
+            break;
+        case HAL_PIXEL_FORMAT_YCbCr_420_SP:
+        case HAL_PIXEL_FORMAT_YCrCb_420_SP:
+            size = ALIGN((alignedw*alignedh) + (alignedw* alignedh)/2 + 1, 4096);
+            break;
+        case HAL_PIXEL_FORMAT_YCbCr_422_SP:
+        case HAL_PIXEL_FORMAT_YCrCb_422_SP:
+        case HAL_PIXEL_FORMAT_YCbCr_422_I:
+        case HAL_PIXEL_FORMAT_YCrCb_422_I:
+            if(width & 1) {
+                ALOGE("width is odd for the YUV422_SP format");
+                return 0;
+            }
+            size = ALIGN(alignedw * alignedh * 2, 4096);
+            break;
+        case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS:
+        case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:
+            size = VENUS_BUFFER_SIZE(COLOR_FMT_NV12, width, height);
+            break;
+        case HAL_PIXEL_FORMAT_BLOB:
+            if(height != 1) {
+                ALOGE("%s: Buffers with format HAL_PIXEL_FORMAT_BLOB \
+                      must have height==1 ", __FUNCTION__);
+                return 0;
+            }
+            size = width;
+            break;
+        case HAL_PIXEL_FORMAT_NV21_ZSL:
+            size = ALIGN((alignedw*alignedh) + (alignedw* alignedh)/2, 4096);
+            break;
+        case HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_4x4_KHR:
+        case HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_5x4_KHR:
+        case HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_5x5_KHR:
+        case HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_6x5_KHR:
+        case HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_6x6_KHR:
+        case HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_8x5_KHR:
+        case HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_8x6_KHR:
+        case HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_8x8_KHR:
+        case HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_10x5_KHR:
+        case HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_10x6_KHR:
+        case HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_10x8_KHR:
+        case HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_10x10_KHR:
+        case HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_12x10_KHR:
+        case HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_12x12_KHR:
+        case HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR:
+        case HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR:
+        case HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR:
+        case HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR:
+        case HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR:
+        case HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR:
+        case HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR:
+        case HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR:
+        case HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR:
+        case HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR:
+        case HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR:
+        case HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR:
+        case HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR:
+        case HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR:
+            size = alignedw * alignedh * ASTC_BLOCK_SIZE;
+            break;
+        default:
+            ALOGE("unrecognized pixel format: 0x%x", format);
+            return 0;
+    }
+    return size;
+}
+
+unsigned int getBufferSizeAndDimensions(int width, int height, int format,
+        int& alignedw, int &alignedh)
+{
+    unsigned int size;
+
+    AdrenoMemInfo::getInstance().getAlignedWidthAndHeight(width,
+            height,
+            format,
+            false,
+            alignedw,
+            alignedh);
+
+    size = getSize(format, width, height, alignedw, alignedh);
+
+    return size;
+}
+
+
+unsigned int getBufferSizeAndDimensions(int width, int height, int format,
+        int usage, int& alignedw, int &alignedh)
+{
+    unsigned int size;
+    int tileEnabled = isMacroTileEnabled(format, usage);
+
+    AdrenoMemInfo::getInstance().getAlignedWidthAndHeight(width,
+            height,
+            format,
+            tileEnabled,
+            alignedw,
+            alignedh);
+
+    size = getSize(format, width, height, alignedw, alignedh);
+
+    return size;
+}
+
+
+void getBufferAttributes(int width, int height, int format, int usage,
+        int& alignedw, int &alignedh, int& tileEnabled, unsigned int& size)
+{
+    tileEnabled = isMacroTileEnabled(format, usage);
+
+    AdrenoMemInfo::getInstance().getAlignedWidthAndHeight(width,
+            height,
+            format,
+            tileEnabled,
+            alignedw,
+            alignedh);
+    size = getSize(format, width, height, alignedw, alignedh);
+}
+
+int getYUVPlaneInfo(private_handle_t* hnd, struct android_ycbcr* ycbcr)
+{
+    int err = 0;
+    unsigned int ystride, cstride;
+    memset(ycbcr->reserved, 0, sizeof(ycbcr->reserved));
+
+    // Get the chroma offsets from the handle width/height. We take advantage
+    // of the fact the width _is_ the stride
+    switch (hnd->format) {
+        //Semiplanar
+        case HAL_PIXEL_FORMAT_YCbCr_420_SP:
+        case HAL_PIXEL_FORMAT_YCbCr_422_SP:
+        case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS:
+        case HAL_PIXEL_FORMAT_NV12_ENCODEABLE: //Same as YCbCr_420_SP_VENUS
+            ystride = cstride = hnd->width;
+            ycbcr->y  = (void*)hnd->base;
+            ycbcr->cb = (void*)(hnd->base + ystride * hnd->height);
+            ycbcr->cr = (void*)(hnd->base + ystride * hnd->height + 1);
+            ycbcr->ystride = ystride;
+            ycbcr->cstride = cstride;
+            ycbcr->chroma_step = 2;
+        break;
+
+        case HAL_PIXEL_FORMAT_YCrCb_420_SP:
+        case HAL_PIXEL_FORMAT_YCrCb_422_SP:
+        case HAL_PIXEL_FORMAT_YCrCb_420_SP_ADRENO:
+        case HAL_PIXEL_FORMAT_NV21_ZSL:
+            ystride = cstride = hnd->width;
+            ycbcr->y  = (void*)hnd->base;
+            ycbcr->cr = (void*)(hnd->base + ystride * hnd->height);
+            ycbcr->cb = (void*)(hnd->base + ystride * hnd->height + 1);
+            ycbcr->ystride = ystride;
+            ycbcr->cstride = cstride;
+            ycbcr->chroma_step = 2;
+        break;
+
+        //Planar
+        case HAL_PIXEL_FORMAT_YV12:
+            ystride = hnd->width;
+            cstride = ALIGN(hnd->width/2, 16);
+            ycbcr->y  = (void*)hnd->base;
+            ycbcr->cr = (void*)(hnd->base + ystride * hnd->height);
+            ycbcr->cb = (void*)(hnd->base + ystride * hnd->height +
+                    cstride * hnd->height/2);
+            ycbcr->ystride = ystride;
+            ycbcr->cstride = cstride;
+            ycbcr->chroma_step = 1;
+
+        break;
+        //Unsupported formats
+        case HAL_PIXEL_FORMAT_YCbCr_422_I:
+        case HAL_PIXEL_FORMAT_YCrCb_422_I:
+        case HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED:
+        default:
+        ALOGD("%s: Invalid format passed: 0x%x", __FUNCTION__,
+                hnd->format);
+        err = -EINVAL;
+    }
+    return err;
+
+}
+
+
+
+// Allocate buffer from width, height and format into a
+// private_handle_t. It is the responsibility of the caller
+// to free the buffer using the free_buffer function
+int alloc_buffer(private_handle_t **pHnd, int w, int h, int format, int usage)
+{
+    alloc_data data;
+    int alignedw, alignedh;
+    gralloc::IAllocController* sAlloc =
+        gralloc::IAllocController::getInstance();
+    data.base = 0;
+    data.fd = -1;
+    data.offset = 0;
+    data.size = getBufferSizeAndDimensions(w, h, format, usage, alignedw,
+                                            alignedh);
+
+    data.align = getpagesize();
+    data.uncached = useUncached(usage);
+    int allocFlags = usage;
+
+    int err = sAlloc->allocate(data, allocFlags);
+    if (0 != err) {
+        ALOGE("%s: allocate failed", __FUNCTION__);
+        return -ENOMEM;
+    }
+
+    private_handle_t* hnd = new private_handle_t(data.fd, data.size,
+                                                 data.allocType, 0, format,
+                                                 alignedw, alignedh);
+    hnd->base = (uint64_t) data.base;
+    hnd->offset = data.offset;
+    hnd->gpuaddr = 0;
+    *pHnd = hnd;
+    return 0;
+}
+
+void free_buffer(private_handle_t *hnd)
+{
+    gralloc::IAllocController* sAlloc =
+        gralloc::IAllocController::getInstance();
+    if (hnd && hnd->fd > 0) {
+        IMemAlloc* memalloc = sAlloc->getAllocator(hnd->flags);
+        memalloc->free_buffer((void*)hnd->base, hnd->size, hnd->offset, hnd->fd);
+    }
+    if(hnd)
+        delete hnd;
+
+}
diff --git a/msm8909/libgralloc/alloc_controller.h b/msm8909/libgralloc/alloc_controller.h
new file mode 100644
index 0000000..f0b8ed9
--- /dev/null
+++ b/msm8909/libgralloc/alloc_controller.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2011-2012, The Linux Foundation. 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 The Linux Foundation 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 GRALLOC_ALLOCCONTROLLER_H
+#define GRALLOC_ALLOCCONTROLLER_H
+
+namespace gralloc {
+
+struct alloc_data;
+class IMemAlloc;
+class IonAlloc;
+
+class IAllocController {
+
+    public:
+    /* Allocate using a suitable method
+     * Returns the type of buffer allocated
+     */
+    virtual int allocate(alloc_data& data, int usage) = 0;
+
+    virtual IMemAlloc* getAllocator(int flags) = 0;
+
+    virtual ~IAllocController() {};
+
+    static IAllocController* getInstance(void);
+
+    private:
+    static IAllocController* sController;
+
+};
+
+class IonController : public IAllocController {
+
+    public:
+    virtual int allocate(alloc_data& data, int usage);
+
+    virtual IMemAlloc* getAllocator(int flags);
+
+    IonController();
+
+    private:
+    IonAlloc* mIonAlloc;
+    void allocateIonMem();
+
+};
+} //end namespace gralloc
+#endif // GRALLOC_ALLOCCONTROLLER_H
diff --git a/msm8909/libgralloc/fb_priv.h b/msm8909/libgralloc/fb_priv.h
new file mode 100644
index 0000000..e2eba6a
--- /dev/null
+++ b/msm8909/libgralloc/fb_priv.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * Copyright (c) 2012-2014, The Linux Foundation. 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 FB_PRIV_H
+#define FB_PRIV_H
+#include <linux/fb.h>
+#include <linux/msm_mdp.h>
+
+#define NUM_FRAMEBUFFERS_MIN  2
+#define NUM_FRAMEBUFFERS_MAX  3
+
+#define NO_SURFACEFLINGER_SWAPINTERVAL
+#define COLOR_FORMAT(x) (x & 0xFFF) // Max range for colorFormats is 0 - FFF
+
+struct private_handle_t;
+
+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,
+};
+
+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;
+    struct fb_var_screeninfo info;
+    struct fb_fix_screeninfo finfo;
+    float xdpi;
+    float ydpi;
+    float fps;
+    uint32_t swapInterval;
+};
+
+
+
+#endif /* FB_PRIV_H */
diff --git a/msm8909/libgralloc/framebuffer.cpp b/msm8909/libgralloc/framebuffer.cpp
new file mode 100644
index 0000000..0ebc3db
--- /dev/null
+++ b/msm8909/libgralloc/framebuffer.cpp
@@ -0,0 +1,461 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * Copyright (c) 2010-2014 The Linux Foundation. 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 <cutils/log.h>
+#include <cutils/properties.h>
+#include <dlfcn.h>
+
+#include <hardware/hardware.h>
+
+#include <fcntl.h>
+#include <errno.h>
+#include <sys/ioctl.h>
+#include <string.h>
+#include <stdlib.h>
+#include <pthread.h>
+#include <cutils/atomic.h>
+
+#include <linux/fb.h>
+#include <linux/msm_mdp.h>
+
+#include <GLES/gl.h>
+
+#include "gralloc_priv.h"
+#include "fb_priv.h"
+#include "gr.h"
+#include <cutils/properties.h>
+#include <profiler.h>
+
+#define EVEN_OUT(x) if (x & 0x0001) {x--;}
+/** 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;
+}
+
+enum {
+    PAGE_FLIP = 0x00000001,
+};
+
+struct fb_context_t {
+    framebuffer_device_t  device;
+    //fd - which is returned on open
+    int fbFd;
+};
+
+static int fb_setSwapInterval(struct framebuffer_device_t* dev,
+                              int interval)
+{
+    //XXX: Get the value here and implement along with
+    //single vsync in HWC
+    char pval[PROPERTY_VALUE_MAX];
+    property_get("debug.egl.swapinterval", pval, "-1");
+    int property_interval = atoi(pval);
+    if (property_interval >= 0)
+        interval = property_interval;
+
+    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_post(struct framebuffer_device_t* dev, buffer_handle_t buffer)
+{
+    private_module_t* m =
+        reinterpret_cast<private_module_t*>(dev->common.module);
+    private_handle_t *hnd = static_cast<private_handle_t*>
+        (const_cast<native_handle_t*>(buffer));
+    fb_context_t *ctx = reinterpret_cast<fb_context_t*>(dev);
+    const unsigned int offset = (unsigned int) (hnd->base -
+            m->framebuffer->base);
+    m->info.activate = FB_ACTIVATE_VBL;
+    m->info.yoffset = (int)(offset / m->finfo.line_length);
+    if (ioctl(ctx->fbFd, FBIOPUT_VSCREENINFO, &m->info) == -1) {
+        ALOGE("%s: FBIOPUT_VSCREENINFO for primary failed, str: %s",
+                __FUNCTION__, strerror(errno));
+        return -errno;
+    }
+    return 0;
+}
+
+static int fb_compositionComplete(struct framebuffer_device_t* dev)
+{
+    // TODO: Properly implement composition complete callback
+    if(!dev) {
+        return -1;
+    }
+    glFinish();
+
+    return 0;
+}
+
+int mapFrameBufferLocked(framebuffer_device_t *dev)
+{
+    private_module_t* module =
+        reinterpret_cast<private_module_t*>(dev->common.module);
+    fb_context_t *ctx = reinterpret_cast<fb_context_t*>(dev);
+    // 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) {
+        close(fd);
+        return -errno;
+    }
+
+    struct fb_var_screeninfo info;
+    if (ioctl(fd, FBIOGET_VSCREENINFO, &info) == -1) {
+        close(fd);
+        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;
+    }
+
+    //adreno needs 4k aligned offsets. Max hole size is 4096-1
+    unsigned int size = roundUpToPageSize(info.yres * info.xres *
+                                               (info.bits_per_pixel/8));
+
+    /*
+     * Request NUM_BUFFERS screens (at least 2 for page flipping)
+     */
+    int numberOfBuffers = (int)(finfo.smem_len/size);
+    ALOGV("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;
+
+    ALOGV("We support %d buffers", numberOfBuffers);
+
+    //consider the included hole by 4k alignment
+    uint32_t line_length = (info.xres * info.bits_per_pixel / 8);
+    info.yres_virtual = (uint32_t) ((size * numberOfBuffers) / line_length);
+
+    uint32_t flags = PAGE_FLIP;
+
+    if (info.yres_virtual < ((size * 2) / line_length) ) {
+        // we need at least 2 for page-flipping
+        info.yres_virtual = (int)(size / line_length);
+        flags &= ~PAGE_FLIP;
+        ALOGW("page flipping not supported (yres_virtual=%d, requested=%d)",
+              info.yres_virtual, info.yres*2);
+    }
+
+    if (ioctl(fd, FBIOGET_VSCREENINFO, &info) == -1) {
+        close(fd);
+        return -errno;
+    }
+
+    if (int(info.width) <= 0 || int(info.height) <= 0) {
+        // the driver doesn't return that information
+        // default to 160 dpi
+        info.width  = (uint32_t)(((float)(info.xres) * 25.4f)/160.0f + 0.5f);
+        info.height = (uint32_t)(((float)(info.yres) * 25.4f)/160.0f + 0.5f);
+    }
+
+    float xdpi = ((float)(info.xres) * 25.4f) / (float)info.width;
+    float ydpi = ((float)(info.yres) * 25.4f) / (float)info.height;
+
+#ifdef MSMFB_METADATA_GET
+    struct msmfb_metadata metadata;
+    memset(&metadata, 0 , sizeof(metadata));
+    metadata.op = metadata_op_frame_rate;
+    if (ioctl(fd, MSMFB_METADATA_GET, &metadata) == -1) {
+        ALOGE("Error retrieving panel frame rate");
+        close(fd);
+        return -errno;
+    }
+    float fps = (float)metadata.data.panel_frame_rate;
+#else
+    //XXX: Remove reserved field usage on all baselines
+    //The reserved[3] field is used to store FPS by the driver.
+    float fps  = info.reserved[3] & 0xFF;
+#endif
+    ALOGI("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
+         );
+
+    ALOGI("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) {
+        close(fd);
+        return -errno;
+    }
+
+    if (finfo.smem_len <= 0) {
+        close(fd);
+        return -errno;
+    }
+
+    module->flags = flags;
+    module->info = info;
+    module->finfo = finfo;
+    module->xdpi = xdpi;
+    module->ydpi = ydpi;
+    module->fps = fps;
+    module->swapInterval = 1;
+
+    CALC_INIT();
+
+    /*
+     * map the framebuffer
+     */
+
+    module->numBuffers = info.yres_virtual / info.yres;
+    module->bufferMask = 0;
+    //adreno needs page aligned offsets. Align the fbsize to pagesize.
+    unsigned int fbSize = roundUpToPageSize(finfo.line_length * info.yres)*
+                    module->numBuffers;
+    void* vaddr = mmap(0, fbSize, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
+    if (vaddr == MAP_FAILED) {
+        ALOGE("Error mapping the framebuffer (%s)", strerror(errno));
+        close(fd);
+        return -errno;
+    }
+    //store the framebuffer fd in the ctx
+    ctx->fbFd = fd;
+#ifdef MSMFB_METADATA_GET
+    memset(&metadata, 0 , sizeof(metadata));
+    metadata.op = metadata_op_get_ion_fd;
+    // get the ION fd for the framebuffer, as GPU needs ION fd
+    if (ioctl(fd, MSMFB_METADATA_GET, &metadata) == -1) {
+        ALOGE("Error getting ION fd (%s)", strerror(errno));
+        close(fd);
+        return -errno;
+    }
+    if(metadata.data.fbmem_ionfd < 0) {
+        ALOGE("Error: Ioctl returned invalid ION fd = %d",
+                                        metadata.data.fbmem_ionfd);
+        close(fd);
+        return -errno;
+    }
+    fd = metadata.data.fbmem_ionfd;
+#endif
+    // Create framebuffer handle using the ION fd
+    module->framebuffer = new private_handle_t(fd, fbSize,
+                                        private_handle_t::PRIV_FLAGS_USES_ION,
+                                        BUFFER_TYPE_UI,
+                                        module->fbFormat, info.xres, info.yres);
+    module->framebuffer->base = uint64_t(vaddr);
+    memset(vaddr, 0, fbSize);
+    //Enable vsync
+    int enable = 1;
+    ioctl(ctx->fbFd, MSMFB_OVERLAY_VSYNC_CTRL, &enable);
+    return 0;
+}
+
+static int mapFrameBuffer(framebuffer_device_t *dev)
+{
+    int err = -1;
+    char property[PROPERTY_VALUE_MAX];
+    if((property_get("debug.gralloc.map_fb_memory", property, NULL) > 0) &&
+       (!strncmp(property, "1", PROPERTY_VALUE_MAX ) ||
+        (!strncasecmp(property,"true", PROPERTY_VALUE_MAX )))) {
+        private_module_t* module =
+            reinterpret_cast<private_module_t*>(dev->common.module);
+        pthread_mutex_lock(&module->lock);
+        err = mapFrameBufferLocked(dev);
+        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 (ctx) {
+#ifdef MSMFB_METADATA_GET
+        if(ctx->fbFd >=0) {
+            close(ctx->fbFd);
+        }
+#endif
+        //Hack until fbdev is removed. Framework could close this causing hwc a
+        //pain.
+        //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));
+        if(dev == NULL) {
+            gralloc_close(gralloc_device);
+            return status;
+        }
+        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;
+
+        status = mapFrameBuffer((framebuffer_device_t*)dev);
+        private_module_t* m = (private_module_t*)dev->device.common.module;
+        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) =
+                                                        PRIV_MIN_SWAP_INTERVAL;
+            const_cast<int&>(dev->device.maxSwapInterval) =
+                                                        PRIV_MAX_SWAP_INTERVAL;
+            const_cast<int&>(dev->device.numFramebuffers) = m->numBuffers;
+            dev->device.setUpdateRect = 0;
+
+            *device = &dev->device.common;
+        }
+
+        // Close the gralloc module
+        gralloc_close(gralloc_device);
+    }
+    return status;
+}
diff --git a/msm8909/libgralloc/gpu.cpp b/msm8909/libgralloc/gpu.cpp
new file mode 100644
index 0000000..49274d0
--- /dev/null
+++ b/msm8909/libgralloc/gpu.cpp
@@ -0,0 +1,415 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ * Copyright (c) 2011-2014 The Linux Foundation. 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 <limits.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <cutils/properties.h>
+#include <sys/mman.h>
+
+#include "gr.h"
+#include "gpu.h"
+#include "memalloc.h"
+#include "alloc_controller.h"
+#include <qdMetaData.h>
+
+using namespace gralloc;
+
+#define SZ_1M 0x100000
+
+gpu_context_t::gpu_context_t(const private_module_t* module,
+                             IAllocController* alloc_ctrl ) :
+    mAllocCtrl(alloc_ctrl)
+{
+    // Zero out the alloc_device_t
+    memset(static_cast<alloc_device_t*>(this), 0, sizeof(alloc_device_t));
+
+    // 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;
+    free           = gralloc_free;
+
+}
+
+int gpu_context_t::gralloc_alloc_buffer(unsigned int size, int usage,
+                                        buffer_handle_t* pHandle, int bufferType,
+                                        int format, int width, int height)
+{
+    int err = 0;
+    int flags = 0;
+    size = roundUpToPageSize(size);
+    alloc_data data;
+    data.offset = 0;
+    data.fd = -1;
+    data.base = 0;
+    if(format == HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED)
+        data.align = 8192;
+    else
+        data.align = getpagesize();
+
+    /* force 1MB alignment selectively for secure buffers, MDP5 onwards */
+#ifdef MDSS_TARGET
+    if ((usage & GRALLOC_USAGE_PROTECTED) &&
+        (usage & GRALLOC_USAGE_PRIVATE_MM_HEAP)) {
+        data.align = ALIGN((int) data.align, SZ_1M);
+        size = ALIGN(size, data.align);
+    }
+#endif
+
+    data.size = size;
+    data.pHandle = (uintptr_t) pHandle;
+    err = mAllocCtrl->allocate(data, usage);
+
+    if (!err) {
+        /* allocate memory for enhancement data */
+        alloc_data eData;
+        eData.fd = -1;
+        eData.base = 0;
+        eData.offset = 0;
+        eData.size = ROUND_UP_PAGESIZE(sizeof(MetaData_t));
+        eData.pHandle = data.pHandle;
+        eData.align = getpagesize();
+        int eDataUsage = GRALLOC_USAGE_PRIVATE_SYSTEM_HEAP;
+        int eDataErr = mAllocCtrl->allocate(eData, eDataUsage);
+        ALOGE_IF(eDataErr, "gralloc failed for eDataErr=%s",
+                                          strerror(-eDataErr));
+
+        if (usage & GRALLOC_USAGE_PRIVATE_EXTERNAL_ONLY) {
+            flags |= private_handle_t::PRIV_FLAGS_EXTERNAL_ONLY;
+        }
+        if (usage & GRALLOC_USAGE_PRIVATE_INTERNAL_ONLY) {
+            flags |= private_handle_t::PRIV_FLAGS_INTERNAL_ONLY;
+        }
+
+        ColorSpace_t colorSpace = ITU_R_601;
+        flags |= private_handle_t::PRIV_FLAGS_ITU_R_601;
+        if (bufferType == BUFFER_TYPE_VIDEO) {
+            if (usage & GRALLOC_USAGE_HW_CAMERA_WRITE) {
+#ifndef MDSS_TARGET
+                colorSpace = ITU_R_601_FR;
+                flags |= private_handle_t::PRIV_FLAGS_ITU_R_601_FR;
+#else
+                // Per the camera spec ITU 709 format should be set only for
+                // video encoding.
+                // It should be set to ITU 601 full range format for any other
+                // camera buffer
+                //
+                if (usage & GRALLOC_USAGE_HW_CAMERA_MASK) {
+                    if (usage & GRALLOC_USAGE_HW_VIDEO_ENCODER) {
+                        flags |= private_handle_t::PRIV_FLAGS_ITU_R_709;
+                        colorSpace = ITU_R_709;
+                    } else {
+                        flags |= private_handle_t::PRIV_FLAGS_ITU_R_601_FR;
+                        colorSpace = ITU_R_601_FR;
+                    }
+                }
+#endif
+            }
+        }
+
+        if (usage & GRALLOC_USAGE_HW_VIDEO_ENCODER ) {
+            flags |= private_handle_t::PRIV_FLAGS_VIDEO_ENCODER;
+        }
+
+        if (usage & GRALLOC_USAGE_HW_CAMERA_WRITE) {
+            flags |= private_handle_t::PRIV_FLAGS_CAMERA_WRITE;
+        }
+
+        if (usage & GRALLOC_USAGE_HW_CAMERA_READ) {
+            flags |= private_handle_t::PRIV_FLAGS_CAMERA_READ;
+        }
+
+        if (usage & GRALLOC_USAGE_HW_COMPOSER) {
+            flags |= private_handle_t::PRIV_FLAGS_HW_COMPOSER;
+        }
+
+        if (usage & GRALLOC_USAGE_HW_TEXTURE) {
+            flags |= private_handle_t::PRIV_FLAGS_HW_TEXTURE;
+        }
+
+        if(usage & GRALLOC_USAGE_PRIVATE_SECURE_DISPLAY) {
+            flags |= private_handle_t::PRIV_FLAGS_SECURE_DISPLAY;
+        }
+
+        if(isMacroTileEnabled(format, usage)) {
+            flags |= private_handle_t::PRIV_FLAGS_TILE_RENDERED;
+        }
+
+        if(usage & (GRALLOC_USAGE_SW_READ_MASK | GRALLOC_USAGE_SW_WRITE_MASK)) {
+            flags |= private_handle_t::PRIV_FLAGS_CPU_RENDERED;
+        }
+
+        if (usage & (GRALLOC_USAGE_HW_VIDEO_ENCODER |
+                GRALLOC_USAGE_HW_CAMERA_WRITE |
+                GRALLOC_USAGE_HW_RENDER |
+                GRALLOC_USAGE_HW_FB)) {
+            flags |= private_handle_t::PRIV_FLAGS_NON_CPU_WRITER;
+        }
+
+        if(false == data.uncached) {
+            flags |= private_handle_t::PRIV_FLAGS_CACHED;
+        }
+
+        flags |= data.allocType;
+        uint64_t eBaseAddr = (uint64_t)(eData.base) + eData.offset;
+        private_handle_t *hnd = new private_handle_t(data.fd, size, flags,
+                bufferType, format, width, height, eData.fd, eData.offset,
+                eBaseAddr);
+
+        hnd->offset = data.offset;
+        hnd->base = (uint64_t)(data.base) + data.offset;
+        hnd->gpuaddr = 0;
+        setMetaData(hnd, UPDATE_COLOR_SPACE, (void*) &colorSpace);
+
+        *pHandle = hnd;
+    }
+
+    ALOGE_IF(err, "gralloc failed err=%s", strerror(-err));
+
+    return err;
+}
+
+void gpu_context_t::getGrallocInformationFromFormat(int inputFormat,
+                                                    int *bufferType)
+{
+    *bufferType = BUFFER_TYPE_VIDEO;
+
+    if (inputFormat <= HAL_PIXEL_FORMAT_BGRA_8888) {
+        // RGB formats
+        *bufferType = BUFFER_TYPE_UI;
+    } else if ((inputFormat == HAL_PIXEL_FORMAT_R_8) ||
+               (inputFormat == HAL_PIXEL_FORMAT_RG_88)) {
+        *bufferType = BUFFER_TYPE_UI;
+    }
+}
+
+int gpu_context_t::gralloc_alloc_framebuffer_locked(int usage,
+                                                    buffer_handle_t* pHandle)
+{
+    private_module_t* m = reinterpret_cast<private_module_t*>(common.module);
+
+    // we don't support framebuffer allocations with graphics heap flags
+    if (usage & GRALLOC_HEAP_MASK) {
+        return -EINVAL;
+    }
+
+    if (m->framebuffer == NULL) {
+        ALOGE("%s: Invalid framebuffer", __FUNCTION__);
+        return -EINVAL;
+    }
+
+    const unsigned int bufferMask = m->bufferMask;
+    const uint32_t numBuffers = m->numBuffers;
+    unsigned int bufferSize = m->finfo.line_length * m->info.yres;
+
+    //adreno needs FB size to be page aligned
+    bufferSize = roundUpToPageSize(bufferSize);
+
+    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" handle for it
+    uint64_t vaddr = uint64_t(m->framebuffer->base);
+    // As GPU needs ION FD, the private handle is created
+    // using ION fd and ION flags are set
+    private_handle_t* hnd = new private_handle_t(
+        dup(m->framebuffer->fd), bufferSize,
+        private_handle_t::PRIV_FLAGS_USES_ION |
+        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 |= (uint32_t)(1LU<<i);
+            break;
+        }
+        vaddr += bufferSize;
+    }
+    hnd->base = vaddr;
+    hnd->offset = (unsigned int)(vaddr - m->framebuffer->base);
+    *pHandle = hnd;
+    return 0;
+}
+
+
+int gpu_context_t::gralloc_alloc_framebuffer(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(usage, pHandle);
+    pthread_mutex_unlock(&m->lock);
+    return err;
+}
+
+int gpu_context_t::alloc_impl(int w, int h, int format, int usage,
+                              buffer_handle_t* pHandle, int* pStride,
+                              unsigned int bufferSize) {
+    if (!pHandle || !pStride)
+        return -EINVAL;
+
+    unsigned int size;
+    int alignedw, alignedh;
+    int grallocFormat = format;
+    int bufferType;
+
+    //If input format is HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED then based on
+    //the usage bits, gralloc assigns a format.
+    if(format == HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED ||
+       format == HAL_PIXEL_FORMAT_YCbCr_420_888) {
+        if(usage & GRALLOC_USAGE_HW_VIDEO_ENCODER)
+            grallocFormat = HAL_PIXEL_FORMAT_NV12_ENCODEABLE; //NV12
+        else if((usage & GRALLOC_USAGE_HW_CAMERA_MASK)
+                == GRALLOC_USAGE_HW_CAMERA_ZSL)
+            grallocFormat = HAL_PIXEL_FORMAT_NV21_ZSL; //NV21 ZSL
+        else if(usage & GRALLOC_USAGE_HW_CAMERA_READ)
+            grallocFormat = HAL_PIXEL_FORMAT_YCrCb_420_SP; //NV21
+        else if(usage & GRALLOC_USAGE_HW_CAMERA_WRITE)
+            grallocFormat = HAL_PIXEL_FORMAT_YCrCb_420_SP; //NV21
+        else if(usage & GRALLOC_USAGE_HW_COMPOSER)
+            //XXX: If we still haven't set a format, default to RGBA8888
+            grallocFormat = HAL_PIXEL_FORMAT_RGBA_8888;
+        //If no other usage flags are detected, default the
+        //flexible YUV format to NV21.
+        else if(format == HAL_PIXEL_FORMAT_YCbCr_420_888)
+            grallocFormat = HAL_PIXEL_FORMAT_YCrCb_420_SP;
+    }
+
+    getGrallocInformationFromFormat(grallocFormat, &bufferType);
+    size = getBufferSizeAndDimensions(w, h, grallocFormat, usage, alignedw,
+                   alignedh);
+
+    if ((unsigned int)size <= 0)
+        return -EINVAL;
+    size = (bufferSize >= size)? bufferSize : size;
+
+    bool useFbMem = false;
+    char property[PROPERTY_VALUE_MAX];
+    if((usage & GRALLOC_USAGE_HW_FB) &&
+       (property_get("debug.gralloc.map_fb_memory", property, NULL) > 0) &&
+       (!strncmp(property, "1", PROPERTY_VALUE_MAX ) ||
+        (!strncasecmp(property,"true", PROPERTY_VALUE_MAX )))) {
+        useFbMem = true;
+    }
+
+    int err = 0;
+    if(useFbMem) {
+        err = gralloc_alloc_framebuffer(usage, pHandle);
+    } else {
+        err = gralloc_alloc_buffer(size, usage, pHandle, bufferType,
+                                   grallocFormat, 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) {
+        const unsigned int bufferSize = m->finfo.line_length * m->info.yres;
+        unsigned int index = (unsigned int) ((hnd->base - m->framebuffer->base)
+                / bufferSize);
+        m->bufferMask &= (uint32_t)~(1LU<<index);
+    } else {
+
+        terminateBuffer(&m->base, const_cast<private_handle_t*>(hnd));
+        IMemAlloc* memalloc = mAllocCtrl->getAllocator(hnd->flags);
+        int err = memalloc->free_buffer((void*)hnd->base, hnd->size,
+                                        hnd->offset, hnd->fd);
+        if(err)
+            return err;
+        // free the metadata space
+        unsigned int size = ROUND_UP_PAGESIZE(sizeof(MetaData_t));
+        err = memalloc->free_buffer((void*)hnd->base_metadata,
+                                    size, hnd->offset_metadata,
+                                    hnd->fd_metadata);
+        if (err)
+            return err;
+    }
+    delete hnd;
+    return 0;
+}
+
+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;
+}
+
diff --git a/msm8909/libgralloc/gpu.h b/msm8909/libgralloc/gpu.h
new file mode 100644
index 0000000..2248d30
--- /dev/null
+++ b/msm8909/libgralloc/gpu.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * Copyright (c) 2011-2014, The Linux Foundation. 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_GPU_H_
+#define GRALLOC_GPU_H_
+
+#include <errno.h>
+#include <pthread.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <cutils/log.h>
+
+#include "gralloc_priv.h"
+#include "fb_priv.h"
+
+namespace gralloc {
+class IAllocController;
+class gpu_context_t : public alloc_device_t {
+    public:
+    gpu_context_t(const private_module_t* module,
+                  IAllocController* alloc_ctrl);
+
+    int gralloc_alloc_buffer(unsigned int 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,
+                   unsigned 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);
+    int gralloc_alloc_framebuffer_locked(int usage,
+                                         buffer_handle_t* pHandle);
+
+    int gralloc_alloc_framebuffer(int usage,
+                                  buffer_handle_t* pHandle);
+
+    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);
+
+    private:
+   IAllocController* mAllocCtrl;
+    void getGrallocInformationFromFormat(int inputFormat,
+                                         int *bufferType);
+};
+}
+#endif  // GRALLOC_GPU_H
diff --git a/msm8909/libgralloc/gr.h b/msm8909/libgralloc/gr.h
new file mode 100644
index 0000000..1f902a5
--- /dev/null
+++ b/msm8909/libgralloc/gr.h
@@ -0,0 +1,159 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * Copyright (c) 2011-2012, The Linux Foundation. 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 GR_H_
+#define GR_H_
+
+#include <stdint.h>
+#include <limits.h>
+#include <sys/cdefs.h>
+#include <hardware/gralloc.h>
+#include <pthread.h>
+#include <errno.h>
+
+#include <cutils/native_handle.h>
+#include <utils/Singleton.h>
+
+/*****************************************************************************/
+
+struct private_module_t;
+struct private_handle_t;
+
+inline unsigned int roundUpToPageSize(unsigned int x) {
+    return (x + (PAGE_SIZE-1)) & ~(PAGE_SIZE-1);
+}
+
+template <class Type>
+inline Type ALIGN(Type x, Type align) {
+    return (x + align-1) & ~(align-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);
+unsigned int getBufferSizeAndDimensions(int width, int height, int format,
+        int usage, int& alignedw, int &alignedh);
+unsigned int getBufferSizeAndDimensions(int width, int height, int format,
+        int& alignedw, int &alignedh);
+
+
+// Attributes include aligned width, aligned height, tileEnabled and size of the buffer
+void getBufferAttributes(int width, int height, int format, int usage,
+                           int& alignedw, int &alignedh,
+                           int& tileEnabled, unsigned int &size);
+
+
+bool isMacroTileEnabled(int format, int usage);
+
+int decideBufferHandlingMechanism(int format, const char *compositionUsed,
+                                  int hasBlitEngine, int *needConversion,
+                                  int *useBufferDirectly);
+
+// Allocate buffer from width, height, format into a private_handle_t
+// It is the responsibility of the caller to free the buffer
+int alloc_buffer(private_handle_t **pHnd, int w, int h, int format, int usage);
+void free_buffer(private_handle_t *hnd);
+int getYUVPlaneInfo(private_handle_t* pHnd, struct android_ycbcr* ycbcr);
+
+/*****************************************************************************/
+
+class Locker {
+    pthread_mutex_t mutex;
+    pthread_cond_t cond;
+    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);
+        pthread_cond_init(&cond, 0);
+    }
+    inline ~Locker()       {
+        pthread_mutex_destroy(&mutex);
+        pthread_cond_destroy(&cond);
+    }
+    inline void lock()     { pthread_mutex_lock(&mutex); }
+    inline void wait()     { pthread_cond_wait(&cond, &mutex); }
+    inline void unlock()   { pthread_mutex_unlock(&mutex); }
+    inline void signal()   { pthread_cond_signal(&cond); }
+};
+
+
+class AdrenoMemInfo : public android::Singleton <AdrenoMemInfo>
+{
+    public:
+    AdrenoMemInfo();
+
+    ~AdrenoMemInfo();
+
+    /*
+     * Function to compute the adreno aligned width and aligned height
+     * based on the width and format.
+     *
+     * @return aligned width, aligned height
+     */
+    void getAlignedWidthAndHeight(int width, int height, int format,
+                            int tileEnabled, int& alignedw, int &alignedh);
+
+    /*
+     * Function to return whether GPU support MacroTile feature
+     *
+     * @return >0 : supported
+     *          0 : not supported
+     */
+    int isMacroTilingSupportedByGPU();
+
+    private:
+        // Pointer to the padding library.
+        void *libadreno_utils;
+
+        // link(s)to adreno surface padding library.
+        int (*LINK_adreno_compute_padding) (int width, int bpp,
+                                                int surface_tile_height,
+                                                int screen_tile_height,
+                                                int padding_threshold);
+
+        void (*LINK_adreno_compute_aligned_width_and_height) (int width,
+                                                int height,
+                                                int bpp,
+                                                int tile_mode,
+                                                int raster_mode,
+                                                int padding_threshold,
+                                                int *aligned_w,
+                                                int *aligned_h);
+
+        int (*LINK_adreno_isMacroTilingSupportedByGpu) (void);
+
+        void(*LINK_adreno_compute_compressedfmt_aligned_width_and_height)(
+                                                int width,
+                                                int height,
+                                                int format,
+                                                int tile_mode,
+                                                int raster_mode,
+                                                int padding_threshold,
+                                                int *aligned_w,
+                                                int *aligned_h,
+                                                int *bpp);
+
+        unsigned int (*LINK_adreno_get_gpu_pixel_alignment) ();
+};
+#endif /* GR_H_ */
diff --git a/msm8909/libgralloc/gralloc.cpp b/msm8909/libgralloc/gralloc.cpp
new file mode 100644
index 0000000..c0aa8cb
--- /dev/null
+++ b/msm8909/libgralloc/gralloc.cpp
@@ -0,0 +1,116 @@
+/*
+ * Copyright (C) 2008, The Android Open Source Project
+ * Copyright (c) 2011-2012, The Linux Foundation. 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 <unistd.h>
+#include <fcntl.h>
+
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <cutils/properties.h>
+
+#include "gr.h"
+#include "gpu.h"
+#include "memalloc.h"
+#include "alloc_controller.h"
+
+using namespace gralloc;
+
+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_lock_ycbcr(gralloc_module_t const* module,
+                        buffer_handle_t handle, int usage,
+                        int l, int t, int w, int h,
+                        struct android_ycbcr *ycbcr);
+
+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, ... );
+
+// HAL module methods
+static struct hw_module_methods_t gralloc_module_methods = {
+    open: gralloc_device_open
+};
+
+// HAL module initialize
+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,
+            dso: 0,
+            reserved: {0},
+        },
+        registerBuffer: gralloc_register_buffer,
+        unregisterBuffer: gralloc_unregister_buffer,
+        lock: gralloc_lock,
+        unlock: gralloc_unlock,
+        perform: gralloc_perform,
+        lock_ycbcr: gralloc_lock_ycbcr,
+    },
+    framebuffer: 0,
+    fbFormat: 0,
+    flags: 0,
+    numBuffers: 0,
+    bufferMask: 0,
+    lock: PTHREAD_MUTEX_INITIALIZER,
+};
+
+// Open Gralloc device
+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);
+        gpu_context_t *dev;
+        IAllocController* alloc_ctrl = IAllocController::getInstance();
+        dev = new gpu_context_t(m, alloc_ctrl);
+        if(!dev)
+            return status;
+
+        *device = &dev->common;
+        status = 0;
+    } else {
+        status = fb_device_open(module, name, device);
+    }
+    return status;
+}
diff --git a/msm8909/libgralloc/gralloc_priv.h b/msm8909/libgralloc/gralloc_priv.h
new file mode 100644
index 0000000..2d19517
--- /dev/null
+++ b/msm8909/libgralloc/gralloc_priv.h
@@ -0,0 +1,297 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * Copyright (c) 2011-2014, The Linux Foundation. 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 <cutils/log.h>
+
+#define ROUND_UP_PAGESIZE(x) ( (((unsigned long)(x)) + PAGE_SIZE-1)  & \
+                               (~(PAGE_SIZE-1)) )
+
+enum {
+    /* gralloc usage bits indicating the type
+     * of allocation that should be used */
+
+    /* SYSTEM heap comes from kernel vmalloc,
+     * can never be uncached, is not secured*/
+    GRALLOC_USAGE_PRIVATE_SYSTEM_HEAP     =       GRALLOC_USAGE_PRIVATE_0,
+    /* SF heap is used for application buffers, is not secured */
+    GRALLOC_USAGE_PRIVATE_UI_CONTIG_HEAP  =       GRALLOC_USAGE_PRIVATE_1,
+    /* IOMMU heap comes from manually allocated pages,
+     * can be cached/uncached, is not secured */
+    GRALLOC_USAGE_PRIVATE_IOMMU_HEAP      =       GRALLOC_USAGE_PRIVATE_2,
+    /* MM heap is a carveout heap for video, can be secured*/
+    GRALLOC_USAGE_PRIVATE_MM_HEAP         =       GRALLOC_USAGE_PRIVATE_3,
+    /* ADSP heap is a carveout heap, is not secured*/
+    GRALLOC_USAGE_PRIVATE_ADSP_HEAP       =       0x01000000,
+
+    /* Set this for allocating uncached memory (using O_DSYNC)
+     * cannot be used with noncontiguous heaps */
+    GRALLOC_USAGE_PRIVATE_UNCACHED        =       0x02000000,
+
+    /* Buffer content should be displayed on an primary display only */
+    GRALLOC_USAGE_PRIVATE_INTERNAL_ONLY   =       0x04000000,
+
+    /* Buffer content should be displayed on an external display only */
+    GRALLOC_USAGE_PRIVATE_EXTERNAL_ONLY   =       0x08000000,
+
+    /* This flag is set for WFD usecase */
+    GRALLOC_USAGE_PRIVATE_WFD             =       0x00200000,
+
+    /* CAMERA heap is a carveout heap for camera, is not secured*/
+    GRALLOC_USAGE_PRIVATE_CAMERA_HEAP     =       0x00400000,
+
+    /* This flag is used for SECURE display usecase */
+    GRALLOC_USAGE_PRIVATE_SECURE_DISPLAY  =       0x00800000,
+};
+
+enum {
+    /* Gralloc perform enums
+    */
+    GRALLOC_MODULE_PERFORM_CREATE_HANDLE_FROM_BUFFER = 1,
+    // This will be deprecated from latest graphics drivers. This is kept
+    // for those backward compatibility i.e., newer Display HAL + older graphics
+    // libraries
+    GRALLOC_MODULE_PERFORM_GET_STRIDE,
+    GRALLOC_MODULE_PERFORM_GET_CUSTOM_STRIDE_FROM_HANDLE,
+    GRALLOC_MODULE_PERFORM_GET_CUSTOM_STRIDE_AND_HEIGHT_FROM_HANDLE,
+    GRALLOC_MODULE_PERFORM_GET_ATTRIBUTES,
+    GRALLOC_MODULE_PERFORM_GET_COLOR_SPACE_FROM_HANDLE,
+    GRALLOC_MODULE_PERFORM_GET_YUV_PLANE_INFO,
+};
+
+#define GRALLOC_HEAP_MASK   (GRALLOC_USAGE_PRIVATE_UI_CONTIG_HEAP |\
+                             GRALLOC_USAGE_PRIVATE_SYSTEM_HEAP    |\
+                             GRALLOC_USAGE_PRIVATE_IOMMU_HEAP     |\
+                             GRALLOC_USAGE_PRIVATE_MM_HEAP        |\
+                             GRALLOC_USAGE_PRIVATE_ADSP_HEAP)
+
+#define INTERLACE_MASK 0x80
+#define S3D_FORMAT_MASK 0xFF000
+/*****************************************************************************/
+enum {
+    /* OEM specific HAL formats */
+    HAL_PIXEL_FORMAT_RGBA_5551              = 6,
+    HAL_PIXEL_FORMAT_RGBA_4444              = 7,
+    HAL_PIXEL_FORMAT_NV12_ENCODEABLE        = 0x102,
+    HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS     = 0x7FA30C04,
+    HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED     = 0x7FA30C03,
+    HAL_PIXEL_FORMAT_YCbCr_420_SP           = 0x109,
+    HAL_PIXEL_FORMAT_YCrCb_420_SP_ADRENO    = 0x7FA30C01,
+    HAL_PIXEL_FORMAT_YCrCb_422_SP           = 0x10B,
+    HAL_PIXEL_FORMAT_R_8                    = 0x10D,
+    HAL_PIXEL_FORMAT_RG_88                  = 0x10E,
+    HAL_PIXEL_FORMAT_YCbCr_444_SP           = 0x10F,
+    HAL_PIXEL_FORMAT_YCrCb_444_SP           = 0x110,
+    HAL_PIXEL_FORMAT_YCrCb_422_I            = 0x111,
+    HAL_PIXEL_FORMAT_BGRX_8888              = 0x112,
+    HAL_PIXEL_FORMAT_NV21_ZSL               = 0x113,
+    HAL_PIXEL_FORMAT_INTERLACE              = 0x180,
+    //v4l2_fourcc('Y', 'U', 'Y', 'L'). 24 bpp YUYV 4:2:2 10 bit per component
+    HAL_PIXEL_FORMAT_YCbCr_422_I_10BIT      = 0x4C595559,
+    //v4l2_fourcc('Y', 'B', 'W', 'C'). 10 bit per component. This compressed
+    //format reduces the memory access bandwidth
+    HAL_PIXEL_FORMAT_YCbCr_422_I_10BIT_COMPRESSED = 0x43574259,
+
+    //Khronos ASTC formats
+    HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_4x4_KHR    = 0x93B0,
+    HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_5x4_KHR    = 0x93B1,
+    HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_5x5_KHR    = 0x93B2,
+    HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_6x5_KHR    = 0x93B3,
+    HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_6x6_KHR    = 0x93B4,
+    HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_8x5_KHR    = 0x93B5,
+    HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_8x6_KHR    = 0x93B6,
+    HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_8x8_KHR    = 0x93B7,
+    HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_10x5_KHR   = 0x93B8,
+    HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_10x6_KHR   = 0x93B9,
+    HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_10x8_KHR   = 0x93BA,
+    HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_10x10_KHR  = 0x93BB,
+    HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_12x10_KHR  = 0x93BC,
+    HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_12x12_KHR  = 0x93BD,
+    HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR    = 0x93D0,
+    HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR    = 0x93D1,
+    HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR    = 0x93D2,
+    HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR    = 0x93D3,
+    HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR    = 0x93D4,
+    HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR    = 0x93D5,
+    HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR    = 0x93D6,
+    HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR    = 0x93D7,
+    HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR   = 0x93D8,
+    HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR   = 0x93D9,
+    HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR   = 0x93DA,
+    HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR  = 0x93DB,
+    HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR  = 0x93DC,
+    HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR  = 0x93DD,
+};
+
+/* 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
+};
+
+/*****************************************************************************/
+
+#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_INTERNAL_ONLY      = 0x00000040,
+            PRIV_FLAGS_NON_CPU_WRITER     = 0x00000080,
+            PRIV_FLAGS_NONCONTIGUOUS_MEM  = 0x00000100,
+            PRIV_FLAGS_CACHED             = 0x00000200,
+            PRIV_FLAGS_SECURE_BUFFER      = 0x00000400,
+            // For explicit synchronization
+            PRIV_FLAGS_UNSYNCHRONIZED     = 0x00000800,
+            // Not mapped in userspace
+            PRIV_FLAGS_NOT_MAPPED         = 0x00001000,
+            // Display on external only
+            PRIV_FLAGS_EXTERNAL_ONLY      = 0x00002000,
+            PRIV_FLAGS_VIDEO_ENCODER      = 0x00010000,
+            PRIV_FLAGS_CAMERA_WRITE       = 0x00020000,
+            PRIV_FLAGS_CAMERA_READ        = 0x00040000,
+            PRIV_FLAGS_HW_COMPOSER        = 0x00080000,
+            PRIV_FLAGS_HW_TEXTURE         = 0x00100000,
+            PRIV_FLAGS_ITU_R_601          = 0x00200000,
+            PRIV_FLAGS_ITU_R_601_FR       = 0x00400000,
+            PRIV_FLAGS_ITU_R_709          = 0x00800000,
+            PRIV_FLAGS_SECURE_DISPLAY     = 0x01000000,
+            // Buffer is rendered in Tile Format
+            PRIV_FLAGS_TILE_RENDERED      = 0x02000000,
+            // Buffer rendered using CPU/SW renderer
+            PRIV_FLAGS_CPU_RENDERED       = 0x04000000
+        };
+
+        // file-descriptors
+        int     fd;
+        int     fd_metadata;          // fd for the meta-data
+        // ints
+        int     magic;
+        int     flags;
+        unsigned int  size;
+        unsigned int  offset;
+        int     bufferType;
+        uint64_t base __attribute__((aligned(8)));
+        unsigned int  offset_metadata;
+        // The gpu address mapped into the mmu.
+        uint64_t gpuaddr __attribute__((aligned(8)));
+        int     format;
+        int     width;
+        int     height;
+        uint64_t base_metadata __attribute__((aligned(8)));
+
+#ifdef __cplusplus
+        static const int sNumFds = 2;
+        static inline int sNumInts() {
+            return ((sizeof(private_handle_t) - sizeof(native_handle_t)) /
+                    sizeof(int)) - sNumFds;
+        }
+        static const int sMagic = 'gmsm';
+
+        private_handle_t(int fd, unsigned int size, int flags, int bufferType,
+                         int format, int width, int height, int eFd = -1,
+                         unsigned int eOffset = 0, uint64_t eBase = 0) :
+            fd(fd), fd_metadata(eFd), magic(sMagic),
+            flags(flags), size(size), offset(0), bufferType(bufferType),
+            base(0), offset_metadata(eOffset), gpuaddr(0),
+            format(format), width(width), height(height),
+            base_metadata(eBase)
+        {
+            version = (int) 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)
+            {
+                ALOGD("Invalid gralloc handle (at %p): "
+                      "ver(%d/%zu) ints(%d/%d) fds(%d/%d)"
+                      "magic(%c%c%c%c/%c%c%c%c)",
+                      h,
+                      h ? h->version : -1, sizeof(native_handle),
+                      h ? h->numInts : -1, sNumInts(),
+                      h ? h->numFds : -1, sNumFds,
+                      hnd ? (((hnd->magic >> 24) & 0xFF)?
+                             ((hnd->magic >> 24) & 0xFF) : '-') : '?',
+                      hnd ? (((hnd->magic >> 16) & 0xFF)?
+                             ((hnd->magic >> 16) & 0xFF) : '-') : '?',
+                      hnd ? (((hnd->magic >> 8) & 0xFF)?
+                             ((hnd->magic >> 8) & 0xFF) : '-') : '?',
+                      hnd ? (((hnd->magic >> 0) & 0xFF)?
+                             ((hnd->magic >> 0) & 0xFF) : '-') : '?',
+                      (sMagic >> 24) & 0xFF,
+                      (sMagic >> 16) & 0xFF,
+                      (sMagic >> 8) & 0xFF,
+                      (sMagic >> 0) & 0xFF);
+                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/msm8909/libgralloc/ionalloc.cpp b/msm8909/libgralloc/ionalloc.cpp
new file mode 100644
index 0000000..23e225d
--- /dev/null
+++ b/msm8909/libgralloc/ionalloc.cpp
@@ -0,0 +1,239 @@
+/*
+ * Copyright (c) 2011-2014, The Linux Foundation. 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 The Linux Foundation 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.
+ */
+
+#define DEBUG 0
+#define ATRACE_TAG (ATRACE_TAG_GRAPHICS | ATRACE_TAG_HAL)
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <cutils/log.h>
+#include <errno.h>
+#include <utils/Trace.h>
+#include "gralloc_priv.h"
+#include "ionalloc.h"
+
+using gralloc::IonAlloc;
+
+#define ION_DEVICE "/dev/ion"
+
+int IonAlloc::open_device()
+{
+    if(mIonFd == FD_INIT)
+        mIonFd = open(ION_DEVICE, O_RDONLY);
+
+    if(mIonFd < 0 ) {
+        ALOGE("%s: Failed to open ion device - %s",
+              __FUNCTION__, strerror(errno));
+        mIonFd = FD_INIT;
+        return -errno;
+    }
+    return 0;
+}
+
+void IonAlloc::close_device()
+{
+    if(mIonFd >= 0)
+        close(mIonFd);
+    mIonFd = FD_INIT;
+}
+
+int IonAlloc::alloc_buffer(alloc_data& data)
+{
+    ATRACE_CALL();
+    Locker::Autolock _l(mLock);
+    int err = 0;
+    struct ion_handle_data handle_data;
+    struct ion_fd_data fd_data;
+    struct ion_allocation_data ionAllocData;
+    void *base = 0;
+
+    ionAllocData.len = data.size;
+    ionAllocData.align = data.align;
+    ionAllocData.heap_id_mask = data.flags & ~ION_SECURE;
+    ionAllocData.flags = data.uncached ? 0 : ION_FLAG_CACHED;
+    // ToDo: replace usage of alloc data structure with
+    //  ionallocdata structure.
+    if (data.flags & ION_SECURE)
+        ionAllocData.flags |= ION_SECURE;
+
+    err = open_device();
+    if (err)
+        return err;
+    if(ioctl(mIonFd, ION_IOC_ALLOC, &ionAllocData)) {
+        err = -errno;
+        ALOGE("ION_IOC_ALLOC failed with error - %s", strerror(errno));
+        return err;
+    }
+
+    fd_data.handle = ionAllocData.handle;
+    handle_data.handle = ionAllocData.handle;
+    if(ioctl(mIonFd, ION_IOC_MAP, &fd_data)) {
+        err = -errno;
+        ALOGE("%s: ION_IOC_MAP failed with error - %s",
+              __FUNCTION__, strerror(errno));
+        ioctl(mIonFd, ION_IOC_FREE, &handle_data);
+        return err;
+    }
+
+    if(!(data.flags & ION_SECURE)) {
+        base = mmap(0, ionAllocData.len, PROT_READ|PROT_WRITE,
+                    MAP_SHARED, fd_data.fd, 0);
+        if(base == MAP_FAILED) {
+            err = -errno;
+            ALOGE("%s: Failed to map the allocated memory: %s",
+                  __FUNCTION__, strerror(errno));
+            ioctl(mIonFd, ION_IOC_FREE, &handle_data);
+            return err;
+        }
+    }
+
+    data.base = base;
+    data.fd = fd_data.fd;
+    ioctl(mIonFd, ION_IOC_FREE, &handle_data);
+    ALOGD_IF(DEBUG, "ion: Allocated buffer base:%p size:%zu fd:%d",
+          data.base, ionAllocData.len, data.fd);
+    return 0;
+}
+
+
+int IonAlloc::free_buffer(void* base, unsigned int size, unsigned int offset,
+        int fd)
+{
+    ATRACE_CALL();
+    Locker::Autolock _l(mLock);
+    ALOGD_IF(DEBUG, "ion: Freeing buffer base:%p size:%u fd:%d",
+          base, size, fd);
+    int err = 0;
+    err = open_device();
+    if (err)
+        return err;
+
+    if(base)
+        err = unmap_buffer(base, size, offset);
+    close(fd);
+    return err;
+}
+
+int IonAlloc::map_buffer(void **pBase, unsigned int size, unsigned int offset,
+        int fd)
+{
+    ATRACE_CALL();
+    int err = 0;
+    void *base = 0;
+    // It is a (quirky) requirement of ION to have opened the
+    // ion fd in the process that is doing the mapping
+    err = open_device();
+    if (err)
+        return err;
+
+    base = mmap(0, size, PROT_READ| PROT_WRITE,
+                MAP_SHARED, fd, 0);
+    *pBase = base;
+    if(base == MAP_FAILED) {
+        err = -errno;
+        ALOGE("ion: Failed to map memory in the client: %s",
+              strerror(errno));
+    } else {
+        ALOGD_IF(DEBUG, "ion: Mapped buffer base:%p size:%u offset:%u fd:%d",
+              base, size, offset, fd);
+    }
+    return err;
+}
+
+int IonAlloc::unmap_buffer(void *base, unsigned int size,
+        unsigned int /*offset*/)
+{
+    ATRACE_CALL();
+    ALOGD_IF(DEBUG, "ion: Unmapping buffer  base:%p size:%u", base, size);
+    int err = 0;
+    if(munmap(base, size)) {
+        err = -errno;
+        ALOGE("ion: Failed to unmap memory at %p : %s",
+              base, strerror(errno));
+    }
+    return err;
+
+}
+int IonAlloc::clean_buffer(void *base, unsigned int size, unsigned int offset,
+        int fd, int op)
+{
+    ATRACE_CALL();
+    ATRACE_INT("operation id", op);
+    struct ion_flush_data flush_data;
+    struct ion_fd_data fd_data;
+    struct ion_handle_data handle_data;
+    int err = 0;
+
+    err = open_device();
+    if (err)
+        return err;
+
+    fd_data.fd = fd;
+    if (ioctl(mIonFd, ION_IOC_IMPORT, &fd_data)) {
+        err = -errno;
+        ALOGE("%s: ION_IOC_IMPORT failed with error - %s",
+              __FUNCTION__, strerror(errno));
+        return err;
+    }
+
+    handle_data.handle = fd_data.handle;
+    flush_data.handle  = fd_data.handle;
+    flush_data.vaddr   = base;
+    // offset and length are unsigned int
+    flush_data.offset  = offset;
+    flush_data.length  = size;
+
+    struct ion_custom_data d;
+    switch(op) {
+    case CACHE_CLEAN:
+        d.cmd = ION_IOC_CLEAN_CACHES;
+        break;
+    case CACHE_INVALIDATE:
+            d.cmd = ION_IOC_INV_CACHES;
+        break;
+    case CACHE_CLEAN_AND_INVALIDATE:
+    default:
+        d.cmd = ION_IOC_CLEAN_INV_CACHES;
+    }
+
+    d.arg = (unsigned long int)&flush_data;
+
+    if(ioctl(mIonFd, ION_IOC_CUSTOM, &d)) {
+        err = -errno;
+        ALOGE("%s: ION_IOC_CLEAN_INV_CACHES failed with error - %s",
+
+              __FUNCTION__, strerror(errno));
+        ioctl(mIonFd, ION_IOC_FREE, &handle_data);
+        return err;
+    }
+    ioctl(mIonFd, ION_IOC_FREE, &handle_data);
+    return 0;
+}
+
diff --git a/msm8909/libgralloc/ionalloc.h b/msm8909/libgralloc/ionalloc.h
new file mode 100644
index 0000000..635bda5
--- /dev/null
+++ b/msm8909/libgralloc/ionalloc.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2011-2014, The Linux Foundation. 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 The Linux Foundation 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 GRALLOC_IONALLOC_H
+#define GRALLOC_IONALLOC_H
+
+#include <linux/msm_ion.h>
+#include "memalloc.h"
+#include "gr.h"
+
+namespace gralloc {
+
+class IonAlloc : public IMemAlloc  {
+
+    public:
+    virtual int alloc_buffer(alloc_data& data);
+
+    virtual int free_buffer(void *base, unsigned int size,
+                            unsigned int offset, int fd);
+
+    virtual int map_buffer(void **pBase, unsigned int size,
+                           unsigned int offset, int fd);
+
+    virtual int unmap_buffer(void *base, unsigned int size,
+                             unsigned int offset);
+
+    virtual int clean_buffer(void*base, unsigned int size,
+                             unsigned int offset, int fd, int op);
+
+    IonAlloc() { mIonFd = FD_INIT; }
+
+    ~IonAlloc() { close_device(); }
+
+    private:
+    int mIonFd;
+
+    int open_device();
+
+    void close_device();
+
+    mutable Locker mLock;
+
+};
+
+}
+
+#endif /* GRALLOC_IONALLOC_H */
+
diff --git a/msm8909/libgralloc/mapper.cpp b/msm8909/libgralloc/mapper.cpp
new file mode 100644
index 0000000..147d148
--- /dev/null
+++ b/msm8909/libgralloc/mapper.cpp
@@ -0,0 +1,441 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * Copyright (c) 2011-2014, The Linux Foundation. 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 ATRACE_TAG (ATRACE_TAG_GRAPHICS | ATRACE_TAG_HAL)
+#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 <cutils/log.h>
+#include <cutils/atomic.h>
+#include <utils/Trace.h>
+
+#include <hardware/hardware.h>
+#include <hardware/gralloc.h>
+
+#include "gralloc_priv.h"
+#include "gr.h"
+#include "alloc_controller.h"
+#include "memalloc.h"
+#include <qdMetaData.h>
+
+
+using namespace gralloc;
+/*****************************************************************************/
+
+// Return the type of allocator -
+// these are used for mapping/unmapping
+static IMemAlloc* getAllocator(int flags)
+{
+    IMemAlloc* memalloc;
+    IAllocController* alloc_ctrl = IAllocController::getInstance();
+    memalloc = alloc_ctrl->getAllocator(flags);
+    return memalloc;
+}
+
+static int gralloc_map(gralloc_module_t const* module,
+                       buffer_handle_t handle)
+{
+    ATRACE_CALL();
+    if(!module)
+        return -EINVAL;
+
+    private_handle_t* hnd = (private_handle_t*)handle;
+    unsigned int size = 0;
+    int err = 0;
+    IMemAlloc* memalloc = getAllocator(hnd->flags) ;
+    void *mappedAddress;
+    // Dont map FRAMEBUFFER and SECURE_BUFFERS
+    if (!(hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER) &&
+        !(hnd->flags & private_handle_t::PRIV_FLAGS_SECURE_BUFFER)) {
+        size = hnd->size;
+        err = memalloc->map_buffer(&mappedAddress, size,
+                                       hnd->offset, hnd->fd);
+        if(err || mappedAddress == MAP_FAILED) {
+            ALOGE("Could not mmap handle %p, fd=%d (%s)",
+                  handle, hnd->fd, strerror(errno));
+            hnd->base = 0;
+            return -errno;
+        }
+
+        hnd->base = uint64_t(mappedAddress) + hnd->offset;
+    }
+
+    //Allow mapping of metadata for all buffers and SECURE_BUFFER
+    if (!(hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER)) {
+        mappedAddress = MAP_FAILED;
+        size = ROUND_UP_PAGESIZE(sizeof(MetaData_t));
+        err = memalloc->map_buffer(&mappedAddress, size,
+                                       hnd->offset_metadata, hnd->fd_metadata);
+        if(err || mappedAddress == MAP_FAILED) {
+            ALOGE("Could not mmap handle %p, fd=%d (%s)",
+                  handle, hnd->fd_metadata, strerror(errno));
+            hnd->base_metadata = 0;
+            return -errno;
+        }
+        hnd->base_metadata = uint64_t(mappedAddress) + hnd->offset_metadata;
+    }
+    return 0;
+}
+
+static int gralloc_unmap(gralloc_module_t const* module,
+                         buffer_handle_t handle)
+{
+    ATRACE_CALL();
+    if(!module)
+        return -EINVAL;
+
+    private_handle_t* hnd = (private_handle_t*)handle;
+    if (!(hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER)) {
+        int err = -EINVAL;
+        void* base = (void*)hnd->base;
+        unsigned int size = hnd->size;
+        IMemAlloc* memalloc = getAllocator(hnd->flags) ;
+        if(memalloc != NULL) {
+            err = memalloc->unmap_buffer(base, size, hnd->offset);
+            if (err) {
+                ALOGE("Could not unmap memory at address %p", base);
+            }
+            base = (void*)hnd->base_metadata;
+            size = ROUND_UP_PAGESIZE(sizeof(MetaData_t));
+            err = memalloc->unmap_buffer(base, size, hnd->offset_metadata);
+            if (err) {
+                ALOGE("Could not unmap memory at address %p", base);
+            }
+        }
+    }
+    /* need to initialize the pointer to NULL otherwise unmapping for that
+     * buffer happens twice which leads to crash */
+    hnd->base = 0;
+    hnd->base_metadata = 0;
+    return 0;
+}
+
+/*****************************************************************************/
+
+static pthread_mutex_t sMapLock = PTHREAD_MUTEX_INITIALIZER;
+
+/*****************************************************************************/
+
+int gralloc_register_buffer(gralloc_module_t const* module,
+                            buffer_handle_t handle)
+{
+    ATRACE_CALL();
+    if (!module || 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
+     */
+
+    private_handle_t* hnd = (private_handle_t*)handle;
+    hnd->base = 0;
+    hnd->base_metadata = 0;
+    int err = gralloc_map(module, handle);
+    if (err) {
+        ALOGE("%s: gralloc_map failed", __FUNCTION__);
+        return err;
+    }
+
+    return 0;
+}
+
+int gralloc_unregister_buffer(gralloc_module_t const* module,
+                              buffer_handle_t handle)
+{
+    ATRACE_CALL();
+    if (!module || 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;
+
+    if (hnd->base != 0) {
+        gralloc_unmap(module, handle);
+    }
+    hnd->base = 0;
+    hnd->base_metadata = 0;
+    return 0;
+}
+
+int terminateBuffer(gralloc_module_t const* module,
+                    private_handle_t* hnd)
+{
+    ATRACE_CALL();
+    if(!module)
+        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.
+     */
+
+    if (hnd->base != 0) {
+        // 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 |
+                          private_handle_t::PRIV_FLAGS_USES_ION)) {
+                gralloc_unmap(module, hnd);
+        } else {
+            ALOGE("terminateBuffer: unmapping a non pmem/ashmem buffer flags = 0x%x",
+                  hnd->flags);
+            gralloc_unmap(module, hnd);
+        }
+    }
+
+    return 0;
+}
+
+static int gralloc_map_and_invalidate (gralloc_module_t const* module,
+                                       buffer_handle_t handle, int usage)
+{
+    ATRACE_CALL();
+    if (!module || private_handle_t::validate(handle) < 0)
+        return -EINVAL;
+
+    int err = 0;
+    private_handle_t* hnd = (private_handle_t*)handle;
+    if (usage & (GRALLOC_USAGE_SW_READ_MASK | GRALLOC_USAGE_SW_WRITE_MASK)) {
+        if (hnd->base == 0) {
+            // we need to map for real
+            pthread_mutex_t* const lock = &sMapLock;
+            pthread_mutex_lock(lock);
+            err = gralloc_map(module, handle);
+            pthread_mutex_unlock(lock);
+        }
+        if (hnd->flags & private_handle_t::PRIV_FLAGS_USES_ION and
+                hnd->flags & private_handle_t::PRIV_FLAGS_CACHED) {
+            //Invalidate if CPU reads in software and there are non-CPU
+            //writers. No need to do this for the metadata buffer as it is
+            //only read/written in software.
+            if ((usage & GRALLOC_USAGE_SW_READ_MASK) and
+                    (hnd->flags & private_handle_t::PRIV_FLAGS_NON_CPU_WRITER))
+            {
+                IMemAlloc* memalloc = getAllocator(hnd->flags) ;
+                err = memalloc->clean_buffer((void*)hnd->base,
+                        hnd->size, hnd->offset, hnd->fd,
+                        CACHE_INVALIDATE);
+            }
+            //Mark the buffer to be flushed after CPU write.
+            if (usage & GRALLOC_USAGE_SW_WRITE_MASK) {
+                hnd->flags |= private_handle_t::PRIV_FLAGS_NEEDS_FLUSH;
+            }
+        }
+    }
+
+    return err;
+}
+
+int gralloc_lock(gralloc_module_t const* module,
+                 buffer_handle_t handle, int usage,
+                 int /*l*/, int /*t*/, int /*w*/, int /*h*/,
+                 void** vaddr)
+{
+    ATRACE_CALL();
+    private_handle_t* hnd = (private_handle_t*)handle;
+    int err = gralloc_map_and_invalidate(module, handle, usage);
+    if(!err)
+        *vaddr = (void*)hnd->base;
+    return err;
+}
+
+int gralloc_lock_ycbcr(gralloc_module_t const* module,
+                 buffer_handle_t handle, int usage,
+                 int /*l*/, int /*t*/, int /*w*/, int /*h*/,
+                 struct android_ycbcr *ycbcr)
+{
+    ATRACE_CALL();
+    private_handle_t* hnd = (private_handle_t*)handle;
+    int err = gralloc_map_and_invalidate(module, handle, usage);
+    if(!err)
+        err = getYUVPlaneInfo(hnd, ycbcr);
+    return err;
+}
+
+int gralloc_unlock(gralloc_module_t const* module,
+                   buffer_handle_t handle)
+{
+    ATRACE_CALL();
+    if (!module || private_handle_t::validate(handle) < 0)
+        return -EINVAL;
+
+    int err = 0;
+    private_handle_t* hnd = (private_handle_t*)handle;
+
+    IMemAlloc* memalloc = getAllocator(hnd->flags);
+    if (hnd->flags & private_handle_t::PRIV_FLAGS_NEEDS_FLUSH) {
+        err = memalloc->clean_buffer((void*)hnd->base,
+                hnd->size, hnd->offset, hnd->fd,
+                CACHE_CLEAN);
+        hnd->flags &= ~private_handle_t::PRIV_FLAGS_NEEDS_FLUSH;
+    }
+
+    return err;
+}
+
+/*****************************************************************************/
+
+int gralloc_perform(struct gralloc_module_t const* module,
+                    int operation, ... )
+{
+    int res = -EINVAL;
+    va_list args;
+    if(!module)
+        return res;
+
+    va_start(args, operation);
+    switch (operation) {
+        case GRALLOC_MODULE_PERFORM_CREATE_HANDLE_FROM_BUFFER:
+            {
+                int fd = va_arg(args, int);
+                unsigned int size = va_arg(args, unsigned int);
+                unsigned int offset = va_arg(args, unsigned int);
+                void* base = va_arg(args, void*);
+                int width = va_arg(args, int);
+                int height = va_arg(args, int);
+                int format = va_arg(args, int);
+
+                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());
+                if (hnd) {
+                  hnd->magic = private_handle_t::sMagic;
+                  hnd->fd = fd;
+                  hnd->flags =  private_handle_t::PRIV_FLAGS_USES_ION;
+                  hnd->size = size;
+                  hnd->offset = offset;
+                  hnd->base = uint64_t(base) + offset;
+                  hnd->gpuaddr = 0;
+                  hnd->width = width;
+                  hnd->height = height;
+                  hnd->format = format;
+                  *handle = (native_handle_t *)hnd;
+                  res = 0;
+                }
+                break;
+
+            }
+        case GRALLOC_MODULE_PERFORM_GET_STRIDE:
+            {
+                int width   = va_arg(args, int);
+                int format  = va_arg(args, int);
+                int *stride = va_arg(args, int *);
+                int alignedw = 0, alignedh = 0;
+                AdrenoMemInfo::getInstance().getAlignedWidthAndHeight(width,
+                        0, format, false, alignedw, alignedh);
+                *stride = alignedw;
+                res = 0;
+            } break;
+
+        case GRALLOC_MODULE_PERFORM_GET_CUSTOM_STRIDE_FROM_HANDLE:
+            {
+                private_handle_t* hnd =  va_arg(args, private_handle_t*);
+                int *stride = va_arg(args, int *);
+                if (private_handle_t::validate(hnd)) {
+                    return res;
+                }
+                MetaData_t *metadata = (MetaData_t *)hnd->base_metadata;
+                if(metadata && metadata->operation & UPDATE_BUFFER_GEOMETRY) {
+                    *stride = metadata->bufferDim.sliceWidth;
+                } else {
+                    *stride = hnd->width;
+                }
+                res = 0;
+            } break;
+
+        case GRALLOC_MODULE_PERFORM_GET_CUSTOM_STRIDE_AND_HEIGHT_FROM_HANDLE:
+            {
+                private_handle_t* hnd =  va_arg(args, private_handle_t*);
+                int *stride = va_arg(args, int *);
+                int *height = va_arg(args, int *);
+                if (private_handle_t::validate(hnd)) {
+                    return res;
+                }
+                MetaData_t *metadata = (MetaData_t *)hnd->base_metadata;
+                if(metadata && metadata->operation & UPDATE_BUFFER_GEOMETRY) {
+                    *stride = metadata->bufferDim.sliceWidth;
+                    *height = metadata->bufferDim.sliceHeight;
+                } else {
+                    *stride = hnd->width;
+                    *height = hnd->height;
+                }
+                res = 0;
+            } break;
+
+        case GRALLOC_MODULE_PERFORM_GET_ATTRIBUTES:
+            {
+                int width   = va_arg(args, int);
+                int height  = va_arg(args, int);
+                int format  = va_arg(args, int);
+                int usage   = va_arg(args, int);
+                int *alignedWidth = va_arg(args, int *);
+                int *alignedHeight = va_arg(args, int *);
+                int *tileEnabled = va_arg(args,int *);
+                *tileEnabled = isMacroTileEnabled(format, usage);
+                AdrenoMemInfo::getInstance().getAlignedWidthAndHeight(width,
+                        height, format, *tileEnabled, *alignedWidth,
+                        *alignedHeight);
+                res = 0;
+            } break;
+
+        case GRALLOC_MODULE_PERFORM_GET_COLOR_SPACE_FROM_HANDLE:
+            {
+                private_handle_t* hnd =  va_arg(args, private_handle_t*);
+                int *color_space = va_arg(args, int *);
+                if (private_handle_t::validate(hnd)) {
+                    return res;
+                }
+                MetaData_t *metadata = (MetaData_t *)hnd->base_metadata;
+                if(metadata && metadata->operation & UPDATE_COLOR_SPACE) {
+                    *color_space = metadata->colorSpace;
+                    res = 0;
+                }
+            } break;
+        case GRALLOC_MODULE_PERFORM_GET_YUV_PLANE_INFO:
+            {
+                private_handle_t* hnd =  va_arg(args, private_handle_t*);
+                android_ycbcr* ycbcr = va_arg(args, struct android_ycbcr *);
+                if (!private_handle_t::validate(hnd)) {
+                    res = getYUVPlaneInfo(hnd, ycbcr);
+                }
+            } break;
+
+        default:
+            break;
+    }
+    va_end(args);
+    return res;
+}
diff --git a/msm8909/libgralloc/memalloc.h b/msm8909/libgralloc/memalloc.h
new file mode 100644
index 0000000..2bc1ddf
--- /dev/null
+++ b/msm8909/libgralloc/memalloc.h
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2011-2014, The Linux Foundation. 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 The Linux Foundation 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 GRALLOC_MEMALLOC_H
+#define GRALLOC_MEMALLOC_H
+
+#include <stdlib.h>
+
+namespace gralloc {
+
+enum {
+    CACHE_CLEAN = 0x1,
+    CACHE_INVALIDATE,
+    CACHE_CLEAN_AND_INVALIDATE,
+};
+
+struct alloc_data {
+    void           *base;
+    int            fd;
+    unsigned int   offset;
+    unsigned int   size;
+    unsigned int   align;
+    uintptr_t      pHandle;
+    bool           uncached;
+    unsigned int   flags;
+    int            allocType;
+};
+
+class IMemAlloc {
+
+    public:
+    // Allocate buffer - fill in the alloc_data
+    // structure and pass it in. Mapped address
+    // and fd are returned in the alloc_data struct
+    virtual int alloc_buffer(alloc_data& data) = 0;
+
+    // Free buffer
+    virtual int free_buffer(void *base, unsigned int size,
+                            unsigned int offset, int fd) = 0;
+
+    // Map buffer
+    virtual int map_buffer(void **pBase, unsigned int size,
+                           unsigned int offset, int fd) = 0;
+
+    // Unmap buffer
+    virtual int unmap_buffer(void *base, unsigned int size,
+                             unsigned int offset) = 0;
+
+    // Clean and invalidate
+    virtual int clean_buffer(void *base, unsigned int size,
+                             unsigned int offset, int fd, int op) = 0;
+
+    // Destructor
+    virtual ~IMemAlloc() {};
+
+    enum {
+        FD_INIT = -1,
+    };
+
+};
+
+} // end gralloc namespace
+#endif // GRALLOC_MEMALLOC_H
diff --git a/msm8909/libhdmi/Android.mk b/msm8909/libhdmi/Android.mk
new file mode 100644
index 0000000..89ba4a9
--- /dev/null
+++ b/msm8909/libhdmi/Android.mk
@@ -0,0 +1,13 @@
+LOCAL_PATH := $(call my-dir)
+include $(LOCAL_PATH)/../common.mk
+include $(CLEAR_VARS)
+
+LOCAL_MODULE                  := libhdmi
+LOCAL_MODULE_TAGS             := optional
+LOCAL_C_INCLUDES              := $(common_includes) $(kernel_includes)
+LOCAL_SHARED_LIBRARIES        := $(common_libs) liboverlay libqdutils
+LOCAL_CFLAGS                  := $(common_flags) -DLOG_TAG=\"qdhdmi\"
+LOCAL_ADDITIONAL_DEPENDENCIES := $(common_deps)
+LOCAL_SRC_FILES               := hdmi.cpp
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/msm8909/libhdmi/hdmi.cpp b/msm8909/libhdmi/hdmi.cpp
new file mode 100644
index 0000000..4fb7cfa
--- /dev/null
+++ b/msm8909/libhdmi/hdmi.cpp
@@ -0,0 +1,699 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ * Copyright (C) 2012-2014, The Linux Foundation. All rights reserved.
+ *
+ * Not a Contribution, Apache license notifications and license are
+ * retained for attribution purposes only.
+ *
+ * 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 DEBUG 0
+#include <fcntl.h>
+#include <linux/msm_mdp.h>
+#include <video/msm_hdmi_modes.h>
+#include <linux/fb.h>
+#include <sys/ioctl.h>
+#include <cutils/properties.h>
+#include "hwc_utils.h"
+#include "hdmi.h"
+#include "overlayUtils.h"
+#include "overlay.h"
+#include "qd_utils.h"
+
+using namespace android;
+using namespace qdutils;
+
+namespace qhwc {
+#define UNKNOWN_STRING                  "unknown"
+#define SPD_NAME_LENGTH                 16
+
+/* The array gEDIDData contains a list of modes currently
+ * supported by HDMI and display, and modes that are not
+ * supported i.e. interlaced modes.
+
+ * In order to add support for a new mode, the mode must be
+ * appended to the end of the array.
+ *
+ * Each new entry must contain the following:
+ * -Mode: a video format defined in msm_hdmi_modes.h
+ * -Width: x resolution for the mode
+ * -Height: y resolution for the mode
+ * -FPS: the frame rate for the mode
+ * -Mode Order: the priority for the new mode that is used when determining
+ *  the best mode when the HDMI display is connected.
+ */
+EDIDData gEDIDData [] = {
+    EDIDData(HDMI_VFRMT_1440x480i60_4_3, 1440, 480, 60, 1),
+    EDIDData(HDMI_VFRMT_1440x480i60_16_9, 1440, 480, 60, 2),
+    EDIDData(HDMI_VFRMT_1440x576i50_4_3, 1440, 576, 50, 3),
+    EDIDData(HDMI_VFRMT_1440x576i50_16_9, 1440, 576, 50, 4),
+    EDIDData(HDMI_VFRMT_1920x1080i60_16_9, 1920, 1080, 60, 5),
+    EDIDData(HDMI_VFRMT_640x480p60_4_3, 640, 480, 60, 6),
+    EDIDData(HDMI_VFRMT_720x480p60_4_3, 720, 480, 60, 7),
+    EDIDData(HDMI_VFRMT_720x480p60_16_9, 720, 480, 60, 8),
+    EDIDData(HDMI_VFRMT_720x576p50_4_3, 720, 576, 50, 9),
+    EDIDData(HDMI_VFRMT_720x576p50_16_9, 720, 576, 50, 10),
+    EDIDData(HDMI_VFRMT_800x600p60_4_3, 800, 600, 60, 11),
+    EDIDData(HDMI_VFRMT_848x480p60_16_9, 848, 480, 60, 12),
+    EDIDData(HDMI_VFRMT_1024x768p60_4_3, 1024, 768, 60, 13),
+    EDIDData(HDMI_VFRMT_1280x1024p60_5_4, 1280, 1024, 60, 14),
+    EDIDData(HDMI_VFRMT_1280x720p50_16_9, 1280, 720, 50, 15),
+    EDIDData(HDMI_VFRMT_1280x720p60_16_9, 1280, 720, 60, 16),
+    EDIDData(HDMI_VFRMT_1280x800p60_16_10, 1280, 800, 60, 17),
+    EDIDData(HDMI_VFRMT_1280x960p60_4_3, 1280, 960, 60, 18),
+    EDIDData(HDMI_VFRMT_1360x768p60_16_9, 1360, 768, 60, 19),
+    EDIDData(HDMI_VFRMT_1366x768p60_16_10, 1366, 768, 60, 20),
+    EDIDData(HDMI_VFRMT_1440x900p60_16_10, 1440, 900, 60, 21),
+    EDIDData(HDMI_VFRMT_1400x1050p60_4_3, 1400, 1050, 60, 22),
+    EDIDData(HDMI_VFRMT_1680x1050p60_16_10, 1680, 1050, 60, 23),
+    EDIDData(HDMI_VFRMT_1600x1200p60_4_3, 1600, 1200, 60, 24),
+    EDIDData(HDMI_VFRMT_1920x1080p24_16_9, 1920, 1080, 24, 25),
+    EDIDData(HDMI_VFRMT_1920x1080p25_16_9, 1920, 1080, 25, 26),
+    EDIDData(HDMI_VFRMT_1920x1080p30_16_9, 1920, 1080, 30, 27),
+    EDIDData(HDMI_VFRMT_1920x1080p50_16_9, 1920, 1080, 50, 28),
+    EDIDData(HDMI_VFRMT_1920x1080p60_16_9, 1920, 1080, 60, 29),
+    EDIDData(HDMI_VFRMT_1920x1200p60_16_10, 1920, 1200, 60, 30),
+    EDIDData(HDMI_VFRMT_2560x1600p60_16_9, 2560, 1600, 60, 31),
+    EDIDData(HDMI_VFRMT_3840x2160p24_16_9, 3840, 2160, 24, 32),
+    EDIDData(HDMI_VFRMT_3840x2160p25_16_9, 3840, 2160, 25, 33),
+    EDIDData(HDMI_VFRMT_3840x2160p30_16_9, 3840, 2160, 30, 34),
+    EDIDData(HDMI_VFRMT_4096x2160p24_16_9, 4096, 2160, 24, 35),
+};
+
+// Number of modes in gEDIDData
+const int gEDIDCount = (sizeof(gEDIDData)/sizeof(gEDIDData)[0]);
+
+int HDMIDisplay::configure() {
+    if(!openFrameBuffer()) {
+        ALOGE("%s: Failed to open FB: %d", __FUNCTION__, mFbNum);
+        return -1;
+    }
+    readCEUnderscanInfo();
+    readResolution();
+    // TODO: Move this to activate
+    /* Used for changing the resolution
+     * getUserMode will get the preferred
+     * mode set thru adb shell */
+    mCurrentMode = getUserMode();
+    if (mCurrentMode == -1) {
+        //Get the best mode and set
+        mCurrentMode = getBestMode();
+    }
+    setAttributes();
+    // set system property
+    property_set("hw.hdmiON", "1");
+
+    // Read the system property to determine if downscale feature is enabled.
+    char value[PROPERTY_VALUE_MAX];
+    mMDPDownscaleEnabled = false;
+    if(property_get("sys.hwc.mdp_downscale_enabled", value, "false")
+            && !strcmp(value, "true")) {
+        mMDPDownscaleEnabled = true;
+    }
+    return 0;
+}
+
+void HDMIDisplay::getAttributes(uint32_t& width, uint32_t& height) {
+    uint32_t fps = 0;
+    getAttrForMode(width, height, fps);
+}
+
+int HDMIDisplay::teardown() {
+    closeFrameBuffer();
+    resetInfo();
+    // unset system property
+    property_set("hw.hdmiON", "0");
+    return 0;
+}
+
+HDMIDisplay::HDMIDisplay():mFd(-1),
+    mCurrentMode(-1), mModeCount(0), mPrimaryWidth(0), mPrimaryHeight(0),
+    mUnderscanSupported(false)
+{
+    memset(&mVInfo, 0, sizeof(mVInfo));
+
+    mDisplayId = HWC_DISPLAY_EXTERNAL;
+    // Update the display if HDMI is connected as primary
+    if (isHDMIPrimaryDisplay()) {
+        mDisplayId = HWC_DISPLAY_PRIMARY;
+    }
+
+    mFbNum = overlay::Overlay::getInstance()->getFbForDpy(mDisplayId);
+    // disable HPD at start, it will be enabled later
+    // when the display powers on
+    // This helps for framework reboot or adb shell stop/start
+    writeHPDOption(0);
+
+    // for HDMI - retreive all the modes supported by the driver
+    if(mFbNum != -1) {
+        supported_video_mode_lut =
+                        new msm_hdmi_mode_timing_info[HDMI_VFRMT_MAX];
+        // Populate the mode table for supported modes
+        MSM_HDMI_MODES_INIT_TIMINGS(supported_video_mode_lut);
+        MSM_HDMI_MODES_SET_SUPP_TIMINGS(supported_video_mode_lut,
+                                        MSM_HDMI_MODES_ALL);
+        // Update the Source Product Information
+        // Vendor Name
+        setSPDInfo("vendor_name", "ro.product.manufacturer");
+        // Product Description
+        setSPDInfo("product_description", "ro.product.name");
+    }
+
+    ALOGD_IF(DEBUG, "%s mDisplayId(%d) mFbNum(%d)",
+            __FUNCTION__, mDisplayId, mFbNum);
+}
+/* gets the product manufacturer and product name and writes it
+ * to the sysfs node, so that the driver can get that information
+ * Used to show QCOM 8974 instead of Input 1 for example
+ */
+void HDMIDisplay::setSPDInfo(const char* node, const char* property) {
+    char info[PROPERTY_VALUE_MAX];
+    ssize_t err = -1;
+    int spdFile = openDeviceNode(node, O_RDWR);
+    if (spdFile >= 0) {
+        memset(info, 0, sizeof(info));
+        property_get(property, info, UNKNOWN_STRING);
+        ALOGD_IF(DEBUG, "In %s: %s = %s",
+                __FUNCTION__, property, info);
+        if (strncmp(info, UNKNOWN_STRING, SPD_NAME_LENGTH)) {
+            err = write(spdFile, info, strlen(info));
+            if (err <= 0) {
+                ALOGE("%s: file write failed for '%s'"
+                      "err no = %d", __FUNCTION__, node, errno);
+            }
+        } else {
+            ALOGD_IF(DEBUG, "%s: property_get failed for SPD %s",
+                         __FUNCTION__, node);
+        }
+        close(spdFile);
+    }
+}
+
+void HDMIDisplay::setHPD(uint32_t value) {
+    ALOGD_IF(DEBUG,"HPD enabled=%d", value);
+    writeHPDOption(value);
+}
+
+void HDMIDisplay::setActionSafeDimension(int w, int h) {
+    ALOGD_IF(DEBUG,"ActionSafe w=%d h=%d", w, h);
+    char actionsafeWidth[PROPERTY_VALUE_MAX];
+    char actionsafeHeight[PROPERTY_VALUE_MAX];
+    snprintf(actionsafeWidth, sizeof(actionsafeWidth), "%d", w);
+    property_set("persist.sys.actionsafe.width", actionsafeWidth);
+    snprintf(actionsafeHeight, sizeof(actionsafeHeight), "%d", h);
+    property_set("persist.sys.actionsafe.height", actionsafeHeight);
+}
+
+int HDMIDisplay::getModeCount() const {
+    ALOGD_IF(DEBUG,"HPD mModeCount=%d", mModeCount);
+    return mModeCount;
+}
+
+void HDMIDisplay::readCEUnderscanInfo()
+{
+    int hdmiScanInfoFile = -1;
+    ssize_t len = -1;
+    char scanInfo[17];
+    char *ce_info_str = NULL;
+    char *save_ptr;
+    const char token[] = ", \n";
+    int ce_info = -1;
+
+    memset(scanInfo, 0, sizeof(scanInfo));
+    hdmiScanInfoFile = openDeviceNode("scan_info", O_RDONLY);
+    if (hdmiScanInfoFile < 0) {
+        return;
+    } else {
+        len = read(hdmiScanInfoFile, scanInfo, sizeof(scanInfo)-1);
+        ALOGD("%s: Scan Info string: %s length = %zu",
+                 __FUNCTION__, scanInfo, len);
+        if (len <= 0) {
+            close(hdmiScanInfoFile);
+            ALOGE("%s: Scan Info file empty", __FUNCTION__);
+            return;
+        }
+        scanInfo[len] = '\0';  /* null terminate the string */
+        close(hdmiScanInfoFile);
+    }
+
+    /*
+     * The scan_info contains the three fields
+     * PT - preferred video format
+     * IT - video format
+     * CE video format - containing the underscan support information
+     */
+
+    /* PT */
+    ce_info_str = strtok_r(scanInfo, token, &save_ptr);
+    if (ce_info_str) {
+        /* IT */
+        ce_info_str = strtok_r(NULL, token, &save_ptr);
+        if (ce_info_str) {
+            /* CE */
+            ce_info_str = strtok_r(NULL, token, &save_ptr);
+            if (ce_info_str)
+                ce_info = atoi(ce_info_str);
+        }
+    }
+
+    if (ce_info_str) {
+        // ce_info contains the underscan information
+        if (ce_info == HDMI_SCAN_ALWAYS_UNDERSCANED ||
+            ce_info == HDMI_SCAN_BOTH_SUPPORTED)
+            // if TV supported underscan, then driver will always underscan
+            // hence no need to apply action safe rectangle
+            mUnderscanSupported = true;
+    } else {
+        ALOGE("%s: scan_info string error", __FUNCTION__);
+    }
+
+    // Store underscan support info in a system property
+    const char* prop = (mUnderscanSupported) ? "1" : "0";
+    property_set("hw.underscan_supported", prop);
+    return;
+}
+
+HDMIDisplay::~HDMIDisplay()
+{
+    delete [] supported_video_mode_lut;
+    closeFrameBuffer();
+}
+
+/*
+ * sets the fb_var_screeninfo from the hdmi_mode_timing_info
+ */
+void setDisplayTiming(struct fb_var_screeninfo &info,
+                                const msm_hdmi_mode_timing_info* mode)
+{
+    info.reserved[0] = 0;
+    info.reserved[1] = 0;
+    info.reserved[2] = 0;
+#ifndef FB_METADATA_VIDEO_INFO_CODE_SUPPORT
+    info.reserved[3] = (info.reserved[3] & 0xFFFF) |
+              (mode->video_format << 16);
+#endif
+    info.xoffset = 0;
+    info.yoffset = 0;
+    info.xres = mode->active_h;
+    info.yres = mode->active_v;
+
+    info.pixclock = (mode->pixel_freq)*1000;
+    info.vmode = mode->interlaced ?
+                    FB_VMODE_INTERLACED : FB_VMODE_NONINTERLACED;
+
+    info.right_margin = mode->front_porch_h;
+    info.hsync_len = mode->pulse_width_h;
+    info.left_margin = mode->back_porch_h;
+    info.lower_margin = mode->front_porch_v;
+    info.vsync_len = mode->pulse_width_v;
+    info.upper_margin = mode->back_porch_v;
+}
+
+int HDMIDisplay::parseResolution(char* edidStr)
+{
+    char delim = ',';
+    int count = 0;
+    char *start, *end;
+    // EDIDs are string delimited by ','
+    // Ex: 16,4,5,3,32,34,1
+    // Parse this string to get mode(int)
+    start = (char*) edidStr;
+    end = &delim;
+    while(*end == delim) {
+        mEDIDModes[count] = (int) strtol(start, &end, 10);
+        start = end+1;
+        count++;
+    }
+    ALOGD_IF(DEBUG, "In %s: count = %d", __FUNCTION__, count);
+    for (int i = 0; i < count; i++)
+        ALOGD_IF(DEBUG, "Mode[%d] = %d", i, mEDIDModes[i]);
+    return count;
+}
+
+bool HDMIDisplay::readResolution()
+{
+    ssize_t len = -1;
+    char edidStr[128] = {'\0'};
+
+    int hdmiEDIDFile = openDeviceNode("edid_modes", O_RDONLY);
+    if (hdmiEDIDFile < 0) {
+        return false;
+    } else {
+        len = read(hdmiEDIDFile, edidStr, sizeof(edidStr)-1);
+        ALOGD_IF(DEBUG, "%s: EDID string: %s length = %zu",
+                 __FUNCTION__, edidStr, len);
+        if (len <= 0) {
+            ALOGE("%s: edid_modes file empty", __FUNCTION__);
+            edidStr[0] = '\0';
+        }
+        else {
+            while (len > 1 && isspace(edidStr[len-1])) {
+                --len;
+            }
+            edidStr[len] = '\0';
+        }
+        close(hdmiEDIDFile);
+    }
+    if(len > 0) {
+        // Get EDID modes from the EDID strings
+        mModeCount = parseResolution(edidStr);
+        ALOGD_IF(DEBUG, "%s: mModeCount = %d", __FUNCTION__,
+                 mModeCount);
+    }
+
+    return (len > 0);
+}
+
+bool HDMIDisplay::openFrameBuffer()
+{
+    if (mFd == -1) {
+        char strDevPath[MAX_SYSFS_FILE_PATH];
+        snprintf(strDevPath, MAX_SYSFS_FILE_PATH, "/dev/graphics/fb%d", mFbNum);
+        mFd = open(strDevPath, O_RDWR);
+        if (mFd < 0)
+            ALOGE("%s: %s is not available", __FUNCTION__, strDevPath);
+    }
+    return (mFd > 0);
+}
+
+bool HDMIDisplay::closeFrameBuffer()
+{
+    int ret = 0;
+    if(mFd >= 0) {
+        ret = close(mFd);
+        mFd = -1;
+    }
+    return (ret == 0);
+}
+
+// clears the vinfo, edid, best modes
+void HDMIDisplay::resetInfo()
+{
+    memset(&mVInfo, 0, sizeof(mVInfo));
+    memset(mEDIDModes, 0, sizeof(mEDIDModes));
+    mModeCount = 0;
+    mCurrentMode = -1;
+    mUnderscanSupported = false;
+    mXres = 0;
+    mYres = 0;
+    mVsyncPeriod = 0;
+    mMDPScalingMode = false;
+    // Reset the underscan supported system property
+    const char* prop = "0";
+    property_set("hw.underscan_supported", prop);
+}
+
+int HDMIDisplay::getModeOrder(int mode)
+{
+    for (int dataIndex = 0; dataIndex < gEDIDCount; dataIndex++) {
+        if (gEDIDData[dataIndex].mMode == mode) {
+            return gEDIDData[dataIndex].mModeOrder;
+        }
+    }
+    ALOGE("%s Mode not found: %d", __FUNCTION__, mode);
+    return -1;
+}
+
+/// Returns the user mode set(if any) using adb shell
+int HDMIDisplay::getUserMode() {
+    /* Based on the property set the resolution */
+    char property_value[PROPERTY_VALUE_MAX];
+    property_get("hw.hdmi.resolution", property_value, "-1");
+    int mode = atoi(property_value);
+    // We dont support interlaced modes
+    if(isValidMode(mode) && !isInterlacedMode(mode)) {
+        ALOGD_IF(DEBUG, "%s: setting the HDMI mode = %d", __FUNCTION__, mode);
+        return mode;
+    }
+    return -1;
+}
+
+// Get the best mode for the current HD TV
+int HDMIDisplay::getBestMode() {
+    int bestOrder = 0;
+    int bestMode = HDMI_VFRMT_640x480p60_4_3;
+    // for all the edid read, get the best mode
+    for(int i = 0; i < mModeCount; i++) {
+        int mode = mEDIDModes[i];
+        int order = getModeOrder(mode);
+        if (order > bestOrder) {
+            bestOrder = order;
+            bestMode = mode;
+        }
+    }
+    return bestMode;
+}
+
+inline bool HDMIDisplay::isValidMode(int ID)
+{
+    bool valid = false;
+    for (int i = 0; i < mModeCount; i++) {
+        if(ID == mEDIDModes[i]) {
+            valid = true;
+            break;
+        }
+    }
+    return valid;
+}
+
+// returns true if the mode(ID) is interlaced mode format
+bool HDMIDisplay::isInterlacedMode(int ID) {
+    bool interlaced = false;
+    switch(ID) {
+        case HDMI_VFRMT_1440x480i60_4_3:
+        case HDMI_VFRMT_1440x480i60_16_9:
+        case HDMI_VFRMT_1440x576i50_4_3:
+        case HDMI_VFRMT_1440x576i50_16_9:
+        case HDMI_VFRMT_1920x1080i60_16_9:
+            interlaced = true;
+            break;
+        default:
+            interlaced = false;
+            break;
+    }
+    return interlaced;
+}
+
+// Does a put_vscreen info on the HDMI interface which will update
+// the configuration (resolution, timing info) to match mCurrentMode
+void HDMIDisplay::activateDisplay()
+{
+    int ret = 0;
+    ret = ioctl(mFd, FBIOGET_VSCREENINFO, &mVInfo);
+    if(ret < 0) {
+        ALOGD("In %s: FBIOGET_VSCREENINFO failed Err Str = %s", __FUNCTION__,
+                                                            strerror(errno));
+    }
+    ALOGD_IF(DEBUG, "%s: GET Info<ID=%d %dx%d (%d,%d,%d),"
+            "(%d,%d,%d) %dMHz>", __FUNCTION__,
+            mVInfo.reserved[3], mVInfo.xres, mVInfo.yres,
+            mVInfo.right_margin, mVInfo.hsync_len, mVInfo.left_margin,
+            mVInfo.lower_margin, mVInfo.vsync_len, mVInfo.upper_margin,
+            mVInfo.pixclock/1000/1000);
+
+    const struct msm_hdmi_mode_timing_info *mode =
+            &supported_video_mode_lut[0];
+    for (unsigned int i = 0; i < HDMI_VFRMT_MAX; ++i) {
+        const struct msm_hdmi_mode_timing_info *cur =
+                &supported_video_mode_lut[i];
+        if (cur->video_format == (uint32_t)mCurrentMode) {
+            mode = cur;
+            break;
+        }
+    }
+    setDisplayTiming(mVInfo, mode);
+    ALOGD_IF(DEBUG, "%s: SET Info<ID=%d => Info<ID=%d %dx %d"
+            "(%d,%d,%d), (%d,%d,%d) %dMHz>", __FUNCTION__, mCurrentMode,
+            mode->video_format, mVInfo.xres, mVInfo.yres,
+            mVInfo.right_margin, mVInfo.hsync_len, mVInfo.left_margin,
+            mVInfo.lower_margin, mVInfo.vsync_len, mVInfo.upper_margin,
+            mVInfo.pixclock/1000/1000);
+#ifdef FB_METADATA_VIDEO_INFO_CODE_SUPPORT
+    struct msmfb_metadata metadata;
+    memset(&metadata, 0 , sizeof(metadata));
+    metadata.op = metadata_op_vic;
+    metadata.data.video_info_code = mode->video_format;
+    if (ioctl(mFd, MSMFB_METADATA_SET, &metadata) == -1) {
+        ALOGD("In %s: MSMFB_METADATA_SET failed Err Str = %s",
+                __FUNCTION__, strerror(errno));
+    }
+#endif
+    mVInfo.activate = FB_ACTIVATE_NOW | FB_ACTIVATE_ALL | FB_ACTIVATE_FORCE;
+    ret = ioctl(mFd, FBIOPUT_VSCREENINFO, &mVInfo);
+    if(ret < 0) {
+        ALOGD("In %s: FBIOPUT_VSCREENINFO failed Err Str = %s",
+                __FUNCTION__, strerror(errno));
+    }
+}
+
+bool HDMIDisplay::writeHPDOption(int userOption) const
+{
+    bool ret = true;
+    if(mFbNum != -1) {
+        int hdmiHPDFile = openDeviceNode("hpd", O_RDWR);
+        if (hdmiHPDFile >= 0) {
+            ssize_t err = -1;
+            ALOGD_IF(DEBUG, "%s: option = %d",
+                    __FUNCTION__, userOption);
+            if(userOption)
+                err = write(hdmiHPDFile, "1", 2);
+            else
+                err = write(hdmiHPDFile, "0" , 2);
+            if (err <= 0) {
+                ALOGE("%s: file write failed 'hpd'", __FUNCTION__);
+                ret = false;
+            }
+            close(hdmiHPDFile);
+        }
+    }
+    return ret;
+}
+
+
+void HDMIDisplay::setAttributes() {
+    uint32_t fps = 0;
+    // Always set dpyAttr res to mVInfo res
+    getAttrForMode(mXres, mYres, fps);
+    mMDPScalingMode = false;
+
+    if(overlay::Overlay::getInstance()->isUIScalingOnExternalSupported()
+        && mMDPDownscaleEnabled) {
+        // if primary resolution is more than the hdmi resolution
+        // configure dpy attr to primary resolution and set MDP
+        // scaling mode
+        // Restrict this upto 1080p resolution max, if target does not
+        // support source split feature.
+        uint32_t primaryArea = mPrimaryWidth * mPrimaryHeight;
+        if(((primaryArea) > (mXres * mYres)) &&
+            (((primaryArea) <= SUPPORTED_DOWNSCALE_AREA) ||
+                qdutils::MDPVersion::getInstance().isSrcSplit())) {
+            // tmpW and tmpH will hold the primary dimensions before we
+            // update the aspect ratio if necessary.
+            int tmpW = mPrimaryWidth;
+            int tmpH = mPrimaryHeight;
+            // HDMI is always in landscape, so always assign the higher
+            // dimension to hdmi's xres
+            if(mPrimaryHeight > mPrimaryWidth) {
+                tmpW = mPrimaryHeight;
+                tmpH = mPrimaryWidth;
+            }
+            // The aspect ratios of the external and primary displays
+            // can be different. As a result, directly assigning primary
+            // resolution could lead to an incorrect final image.
+            // We get around this by calculating a new resolution by
+            // keeping aspect ratio intact.
+            hwc_rect r = {0, 0, 0, 0};
+            qdutils::getAspectRatioPosition(tmpW, tmpH, mXres, mYres, r);
+            uint32_t newExtW = r.right - r.left;
+            uint32_t newExtH = r.bottom - r.top;
+            uint32_t alignedExtW;
+            uint32_t alignedExtH;
+            // On 8994 and below targets MDP supports only 4X downscaling,
+            // Restricting selected external resolution to be exactly 4X
+            // greater resolution than actual external resolution
+            uint32_t maxMDPDownScale =
+                    qdutils::MDPVersion::getInstance().getMaxMDPDownscale();
+            if((mXres * mYres * maxMDPDownScale) < (newExtW * newExtH)) {
+                float upScaleFactor = (float)maxMDPDownScale / 2.0f;
+                newExtW = (int)((float)mXres * upScaleFactor);
+                newExtH = (int)((float)mYres * upScaleFactor);
+            }
+            // Align it down so that the new aligned resolution does not
+            // exceed the maxMDPDownscale factor
+            alignedExtW = overlay::utils::aligndown(newExtW, 4);
+            alignedExtH = overlay::utils::aligndown(newExtH, 4);
+            mXres = alignedExtW;
+            mYres = alignedExtH;
+            // Set External Display MDP Downscale mode indicator
+            mMDPScalingMode = true;
+        }
+    }
+    ALOGD_IF(DEBUG_MDPDOWNSCALE, "Selected external resolution [%d X %d] "
+            "maxMDPDownScale %d mMDPScalingMode %d srcSplitEnabled %d "
+            "MDPDownscale feature %d",
+            mXres, mYres,
+            qdutils::MDPVersion::getInstance().getMaxMDPDownscale(),
+            mMDPScalingMode, qdutils::MDPVersion::getInstance().isSrcSplit(),
+            mMDPDownscaleEnabled);
+    mVsyncPeriod = (int) 1000000000l / fps;
+    ALOGD_IF(DEBUG, "%s xres=%d, yres=%d", __FUNCTION__, mXres, mYres);
+}
+
+void HDMIDisplay::getAttrForMode(uint32_t& width, uint32_t& height,
+        uint32_t& fps) {
+    for (int dataIndex = 0; dataIndex < gEDIDCount; dataIndex++) {
+        if (gEDIDData[dataIndex].mMode == mCurrentMode) {
+            width = gEDIDData[dataIndex].mWidth;
+            height = gEDIDData[dataIndex].mHeight;
+            fps = gEDIDData[dataIndex].mFps;
+            return;
+        }
+    }
+    ALOGE("%s Unable to get attributes for %d", __FUNCTION__, mCurrentMode);
+}
+
+/* returns the fd related to the node specified*/
+int HDMIDisplay::openDeviceNode(const char* node, int fileMode) const {
+    char sysFsFilePath[MAX_SYSFS_FILE_PATH];
+    memset(sysFsFilePath, 0, sizeof(sysFsFilePath));
+    snprintf(sysFsFilePath , sizeof(sysFsFilePath),
+            "/sys/devices/virtual/graphics/fb%d/%s",
+            mFbNum, node);
+
+    int fd = open(sysFsFilePath, fileMode, 0);
+
+    if (fd < 0) {
+        ALOGE("%s: file '%s' not found : ret = %d err str: %s",
+                __FUNCTION__, sysFsFilePath, fd, strerror(errno));
+    }
+    return fd;
+}
+
+bool HDMIDisplay::isHDMIPrimaryDisplay() {
+    int hdmiNode = qdutils::getHDMINode();
+    return (hdmiNode == HWC_DISPLAY_PRIMARY);
+}
+
+int HDMIDisplay::getConnectedState() {
+    int ret = -1;
+    int mFbNum = qdutils::getHDMINode();
+    int connectedNode = openDeviceNode("connected", O_RDONLY);
+    if(connectedNode >= 0) {
+        char opStr[4];
+        ssize_t bytesRead = read(connectedNode, opStr, sizeof(opStr) - 1);
+        if(bytesRead > 0) {
+            opStr[bytesRead] = '\0';
+            ret = atoi(opStr);
+            ALOGD_IF(DEBUG, "%s: Read %d from connected", __FUNCTION__, ret);
+        } else if(bytesRead == 0) {
+            ALOGE("%s: HDMI connected node empty", __FUNCTION__);
+        } else {
+            ALOGE("%s: Read from HDMI connected node failed with error %s",
+                    __FUNCTION__, strerror(errno));
+        }
+        close(connectedNode);
+    } else {
+        ALOGD("%s: /sys/class/graphics/fb%d/connected could not be opened : %s",
+                __FUNCTION__, mFbNum, strerror(errno));
+    }
+    return ret;
+}
+
+void HDMIDisplay::setPrimaryAttributes(uint32_t primaryWidth,
+        uint32_t primaryHeight) {
+    mPrimaryHeight = primaryHeight;
+    mPrimaryWidth = primaryWidth;
+}
+
+};
diff --git a/msm8909/libhdmi/hdmi.h b/msm8909/libhdmi/hdmi.h
new file mode 100644
index 0000000..605d9be
--- /dev/null
+++ b/msm8909/libhdmi/hdmi.h
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ * Copyright (C) 2012-2014, The Linux Foundation. All rights reserved.
+ *
+ * Not a Contribution, Apache license notifications and license are
+ * retained for attribution purposes only.
+
+ * 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 HWC_HDMI_DISPLAY_H
+#define HWC_HDMI_DISPLAY_H
+
+#include <linux/fb.h>
+
+struct msm_hdmi_mode_timing_info;
+
+namespace qhwc {
+
+//Type of scanning of EDID(Video Capability Data Block)
+enum hdmi_scansupport_type {
+    HDMI_SCAN_NOT_SUPPORTED      = 0,
+    HDMI_SCAN_ALWAYS_OVERSCANED  = 1,
+    HDMI_SCAN_ALWAYS_UNDERSCANED = 2,
+    HDMI_SCAN_BOTH_SUPPORTED     = 3
+};
+
+// Structure to store EDID related data
+struct EDIDData {
+    int mMode, mWidth, mHeight, mFps;
+    // Predetermined ordering for each mode
+    int mModeOrder;
+    EDIDData(int mode, int width, int height, int fps, int order)
+    : mMode(mode), mWidth(width), mHeight(height), mFps(fps), mModeOrder(order)
+    { }
+};
+
+class HDMIDisplay
+{
+public:
+    HDMIDisplay();
+    ~HDMIDisplay();
+    void setHPD(uint32_t startEnd);
+    void setActionSafeDimension(int w, int h);
+    bool isCEUnderscanSupported() { return mUnderscanSupported; }
+    int configure();
+    void getAttributes(uint32_t& width, uint32_t& height);
+    int teardown();
+    uint32_t getWidth() const { return mXres; };
+    uint32_t getHeight() const { return mYres; };
+    uint32_t getVsyncPeriod() const { return mVsyncPeriod; };
+    int getFd() const { return mFd; };
+    bool getMDPScalingMode() const { return mMDPScalingMode; }
+    void activateDisplay();
+    /* Returns true if HDMI is the PRIMARY display device*/
+    bool isHDMIPrimaryDisplay();
+    int getConnectedState();
+    /* when HDMI is an EXTERNAL display, PRIMARY display attributes are needed
+       for scaling mode */
+    void setPrimaryAttributes(uint32_t primaryWidth, uint32_t primaryHeight);
+
+private:
+    int getModeCount() const;
+    void setSPDInfo(const char* node, const char* property);
+    void readCEUnderscanInfo();
+    bool readResolution();
+    int  parseResolution(char* edidMode);
+    bool openFrameBuffer();
+    bool closeFrameBuffer();
+    bool writeHPDOption(int userOption) const;
+    bool isValidMode(int mode);
+    int  getModeOrder(int mode);
+    int  getUserMode();
+    int  getBestMode();
+    bool isInterlacedMode(int mode);
+    void resetInfo();
+    void setAttributes();
+    void getAttrForMode(uint32_t& width, uint32_t& height, uint32_t& fps);
+    int openDeviceNode(const char* node, int fileMode) const;
+
+    int mFd;
+    int mFbNum;
+    int mCurrentMode;
+    int mEDIDModes[64];
+    int mModeCount;
+    fb_var_screeninfo mVInfo;
+    // Holds all the HDMI modes and timing info supported by driver
+    msm_hdmi_mode_timing_info* supported_video_mode_lut;
+    uint32_t mXres, mYres, mVsyncPeriod, mPrimaryWidth, mPrimaryHeight;
+    bool mMDPScalingMode;
+    bool mUnderscanSupported;
+    // Downscale feature switch, set via system property
+    // sys.hwc.mdp_downscale_enabled
+    bool mMDPDownscaleEnabled;
+    int mDisplayId;
+};
+
+}; //qhwc
+// ---------------------------------------------------------------------------
+#endif //HWC_HDMI_DISPLAY_H
diff --git a/msm8909/libhwcomposer/Android.mk b/msm8909/libhwcomposer/Android.mk
new file mode 100644
index 0000000..cb2c257
--- /dev/null
+++ b/msm8909/libhwcomposer/Android.mk
@@ -0,0 +1,66 @@
+LOCAL_PATH := $(call my-dir)
+include $(LOCAL_PATH)/../common.mk
+include $(CLEAR_VARS)
+
+LOCAL_MODULE                  := hwcomposer.$(TARGET_BOARD_PLATFORM)
+LOCAL_MODULE_RELATIVE_PATH    := hw
+LOCAL_MODULE_TAGS             := optional
+LOCAL_C_INCLUDES              := $(common_includes) $(kernel_includes) \
+                                 $(TOP)/external/skia/include/core \
+                                 $(TOP)/external/skia/include/images
+
+ifeq ($(strip $(TARGET_USES_QCOM_DISPLAY_PP)),true)
+LOCAL_C_INCLUDES              += $(TARGET_OUT_HEADERS)/qdcm/inc \
+                                 $(TARGET_OUT_HEADERS)/common/inc \
+                                 $(TARGET_OUT_HEADERS)/pp/inc
+endif
+
+LOCAL_SHARED_LIBRARIES        := $(common_libs) libEGL liboverlay \
+                                 libhdmi libqdutils libhardware_legacy \
+                                 libdl libmemalloc libqservice libsync \
+                                 libbinder libmedia
+
+LOCAL_CFLAGS                  := $(common_flags) -DLOG_TAG=\"qdhwcomposer\"
+ifeq ($(TARGET_USES_QCOM_BSP),true)
+LOCAL_SHARED_LIBRARIES += libskia
+ifeq ($(GET_FRAMEBUFFER_FORMAT_FROM_HWC),true)
+    LOCAL_CFLAGS += -DGET_FRAMEBUFFER_FORMAT_FROM_HWC
+endif
+endif #TARGET_USES_QCOM_BSP
+
+#Enable Dynamic FPS if PHASE_OFFSET is not set
+ifeq ($(VSYNC_EVENT_PHASE_OFFSET_NS),)
+    LOCAL_CFLAGS += -DDYNAMIC_FPS
+endif
+
+LOCAL_ADDITIONAL_DEPENDENCIES := $(common_deps)
+LOCAL_SRC_FILES               := hwc.cpp          \
+                                 hwc_utils.cpp    \
+                                 hwc_uevents.cpp  \
+                                 hwc_vsync.cpp    \
+                                 hwc_fbupdate.cpp \
+                                 hwc_mdpcomp.cpp  \
+                                 hwc_copybit.cpp  \
+                                 hwc_qclient.cpp  \
+                                 hwc_dump_layers.cpp \
+                                 hwc_ad.cpp \
+                                 hwc_virtual.cpp
+
+TARGET_MIGRATE_QDCM_LIST := msm8909
+TARGET_MIGRATE_QDCM := $(call is-board-platform-in-list,$(TARGET_MIGRATE_QDCM_LIST))
+
+ifeq ($(TARGET_MIGRATE_QDCM), true)
+ifeq ($(strip $(TARGET_USES_QCOM_DISPLAY_PP)),true)
+LOCAL_SRC_FILES += hwc_qdcm.cpp
+else
+LOCAL_SRC_FILES += hwc_qdcm_legacy.cpp
+endif
+else
+LOCAL_SRC_FILES += hwc_qdcm_legacy.cpp
+endif
+
+ifeq ($(TARGET_SUPPORTS_ANDROID_WEAR), true)
+    LOCAL_CFLAGS += -DSUPPORT_BLIT_TO_FB
+endif
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/msm8909/libhwcomposer/hwc.cpp b/msm8909/libhwcomposer/hwc.cpp
new file mode 100644
index 0000000..30ff9b3
--- /dev/null
+++ b/msm8909/libhwcomposer/hwc.cpp
@@ -0,0 +1,978 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ * Copyright (C) 2012-2015, The Linux Foundation. All rights reserved.
+ *
+ * Not a Contribution, Apache license notifications and license are retained
+ * for attribution purposes only.
+ *
+ * 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 ATRACE_TAG (ATRACE_TAG_GRAPHICS | ATRACE_TAG_HAL)
+#include <fcntl.h>
+#include <errno.h>
+
+#include <cutils/log.h>
+#include <cutils/atomic.h>
+#include <EGL/egl.h>
+#include <utils/Trace.h>
+#include <sys/ioctl.h>
+#include <overlay.h>
+#include <overlayRotator.h>
+#include <overlayWriteback.h>
+#include <mdp_version.h>
+#include "hwc_utils.h"
+#include "hwc_fbupdate.h"
+#include "hwc_mdpcomp.h"
+#include "hwc_dump_layers.h"
+#include "hdmi.h"
+#include "hwc_copybit.h"
+#include "hwc_ad.h"
+#include "profiler.h"
+#include "hwc_virtual.h"
+#include "hwc_qdcm.h"
+
+using namespace qhwc;
+using namespace overlay;
+using namespace qQdcm;
+
+#define VSYNC_DEBUG 0
+#define POWER_MODE_DEBUG 1
+
+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
+};
+
+static void reset_panel(struct hwc_composer_device_1* dev);
+
+hwc_module_t HAL_MODULE_INFO_SYM = {
+    common: {
+        tag: HARDWARE_MODULE_TAG,
+        version_major: 2,
+        version_minor: 0,
+        id: HWC_HARDWARE_MODULE_ID,
+        name: "Qualcomm Hardware Composer Module",
+        author: "CodeAurora Forum",
+        methods: &hwc_module_methods,
+        dso: 0,
+        reserved: {0},
+    }
+};
+
+/*
+ * Save callback functions registered to HWC
+ */
+static void hwc_registerProcs(struct hwc_composer_device_1* dev,
+                              hwc_procs_t const* procs)
+{
+    ALOGI("%s", __FUNCTION__);
+    hwc_context_t* ctx = (hwc_context_t*)(dev);
+    if(!ctx) {
+        ALOGE("%s: Invalid context", __FUNCTION__);
+        return;
+    }
+    ctx->proc = procs;
+
+    // Now that we have the functions needed, kick off
+    // the uevent & vsync threads
+    init_uevent_thread(ctx);
+    init_vsync_thread(ctx);
+}
+
+static void setPaddingRound(hwc_context_t *ctx, int numDisplays,
+                            hwc_display_contents_1_t** displays) {
+    ctx->isPaddingRound = false;
+    for(int i = 0; i < numDisplays; i++) {
+        hwc_display_contents_1_t *list = displays[i];
+        if (LIKELY(list && list->numHwLayers > 0)) {
+            if((ctx->mPrevHwLayerCount[i] == 1 or
+                ctx->mPrevHwLayerCount[i] == 0) and
+               (list->numHwLayers > 1)) {
+                /* If the previous cycle for dpy 'i' has 0 AppLayers and the
+                 * current cycle has atleast 1 AppLayer, padding round needs
+                 * to be invoked in current cycle on all the active displays
+                 * to free up the resources.
+                 */
+                ctx->isPaddingRound = true;
+            }
+            ctx->mPrevHwLayerCount[i] = (int)list->numHwLayers;
+        } else {
+            ctx->mPrevHwLayerCount[i] = 0;
+        }
+    }
+}
+
+/* Based on certain conditions, isPaddingRound will be set
+ * to make this function self-contained */
+static void setDMAState(hwc_context_t *ctx, int numDisplays,
+                        hwc_display_contents_1_t** displays) {
+
+    if(ctx->mRotMgr->getNumActiveSessions() == 0)
+        Overlay::setDMAMode(Overlay::DMA_LINE_MODE);
+
+    for(int dpy = 0; dpy < numDisplays; dpy++) {
+        hwc_display_contents_1_t *list = displays[dpy];
+        if (LIKELY(list && list->numHwLayers > 0)) {
+            for(size_t layerIndex = 0; layerIndex < list->numHwLayers;
+                                                  layerIndex++) {
+                if(list->hwLayers[layerIndex].compositionType !=
+                                            HWC_FRAMEBUFFER_TARGET)
+                {
+                    hwc_layer_1_t const* layer = &list->hwLayers[layerIndex];
+                    private_handle_t *hnd = (private_handle_t *)layer->handle;
+
+                    /* If a layer requires rotation, set the DMA state
+                     * to BLOCK_MODE */
+
+                    if (canUseRotator(ctx, dpy) &&
+                        (has90Transform(layer) || getRotDownscale(ctx, layer))
+                        && isRotationDoable(ctx, hnd)) {
+                        if(not (ctx->mOverlay->isDMAMultiplexingSupported() &&
+                                          dpy)) {
+                            if(ctx->mOverlay->isPipeTypeAttached(
+                                             overlay::utils::OV_MDP_PIPE_DMA))
+                                ctx->isPaddingRound = true;
+                        }
+                        Overlay::setDMAMode(Overlay::DMA_BLOCK_MODE);
+                    }
+                }
+            }
+            if(dpy) {
+                /* Uncomment the below code for testing purpose.
+                   Assuming the orientation value is in terms of HAL_TRANSFORM,
+                   this needs mapping to HAL, if its in different convention */
+
+                /* char value[PROPERTY_VALUE_MAX];
+                   property_get("sys.ext_orientation", value, "0");
+                   ctx->mExtOrientation = atoi(value);*/
+
+                if(ctx->mExtOrientation || ctx->mBufferMirrorMode) {
+                    if(ctx->mOverlay->isPipeTypeAttached(
+                                         overlay::utils::OV_MDP_PIPE_DMA)) {
+                        ctx->isPaddingRound = true;
+                    }
+                    Overlay::setDMAMode(Overlay::DMA_BLOCK_MODE);
+                }
+            }
+        }
+    }
+}
+
+static void setNumActiveDisplays(hwc_context_t *ctx, int numDisplays,
+                            hwc_display_contents_1_t** displays) {
+
+    ctx->numActiveDisplays = 0;
+    for(int i = 0; i < numDisplays; i++) {
+        hwc_display_contents_1_t *list = displays[i];
+        if (LIKELY(list && list->numHwLayers > 0)) {
+            /* For display devices like SSD and screenrecord, we cannot
+             * rely on isActive and connected attributes of dpyAttr to
+             * determine if the displaydevice is active. Hence in case if
+             * the layer-list is non-null and numHwLayers > 0, we assume
+             * the display device to be active.
+             */
+            ctx->numActiveDisplays += 1;
+        }
+    }
+}
+
+static bool validDisplay(int disp) {
+    switch(disp) {
+        case HWC_DISPLAY_PRIMARY:
+        case HWC_DISPLAY_EXTERNAL:
+        case HWC_DISPLAY_VIRTUAL:
+            return true;
+            break;
+        default:
+            return false;
+    }
+}
+
+static void reset(hwc_context_t *ctx, int numDisplays,
+                  hwc_display_contents_1_t** displays) {
+
+
+    for(int i = 0; i < numDisplays; i++) {
+        hwc_display_contents_1_t *list = displays[i];
+        // XXX:SurfaceFlinger no longer guarantees that this
+        // value is reset on every prepare. However, for the layer
+        // cache we need to reset it.
+        // We can probably rethink that later on
+        if (LIKELY(list && list->numHwLayers > 0)) {
+            for(size_t j = 0; j < list->numHwLayers; j++) {
+                if(list->hwLayers[j].compositionType != HWC_FRAMEBUFFER_TARGET)
+                    list->hwLayers[j].compositionType = HWC_FRAMEBUFFER;
+            }
+
+        }
+
+        if(ctx->mMDPComp[i])
+            ctx->mMDPComp[i]->reset();
+        if(ctx->mFBUpdate[i])
+            ctx->mFBUpdate[i]->reset();
+        if(ctx->mCopyBit[i])
+            ctx->mCopyBit[i]->reset();
+        if(ctx->mLayerRotMap[i])
+            ctx->mLayerRotMap[i]->reset();
+    }
+
+    ctx->mAD->reset();
+
+}
+
+static void scaleDisplayFrame(hwc_context_t *ctx, int dpy,
+                            hwc_display_contents_1_t *list) {
+    uint32_t origXres = ctx->dpyAttr[dpy].xres;
+    uint32_t origYres = ctx->dpyAttr[dpy].yres;
+    uint32_t newXres = ctx->dpyAttr[dpy].xres_new;
+    uint32_t newYres = ctx->dpyAttr[dpy].yres_new;
+    float xresRatio = (float)origXres / (float)newXres;
+    float yresRatio = (float)origYres / (float)newYres;
+    for (size_t i = 0; i < list->numHwLayers; i++) {
+        hwc_layer_1_t *layer = &list->hwLayers[i];
+        hwc_rect_t& displayFrame = layer->displayFrame;
+        hwc_rect_t sourceCrop = integerizeSourceCrop(layer->sourceCropf);
+        uint32_t layerWidth = displayFrame.right - displayFrame.left;
+        uint32_t layerHeight = displayFrame.bottom - displayFrame.top;
+        displayFrame.left = (int)(xresRatio * (float)displayFrame.left);
+        displayFrame.top = (int)(yresRatio * (float)displayFrame.top);
+        displayFrame.right = (int)((float)displayFrame.left +
+                                   (float)layerWidth * xresRatio);
+        displayFrame.bottom = (int)((float)displayFrame.top +
+                                    (float)layerHeight * yresRatio);
+    }
+}
+
+static int hwc_prepare_primary(hwc_composer_device_1 *dev,
+        hwc_display_contents_1_t *list) {
+    ATRACE_CALL();
+    hwc_context_t* ctx = (hwc_context_t*)(dev);
+    const int dpy = HWC_DISPLAY_PRIMARY;
+    bool fbComp = false;
+    static int compStart = false;
+    if (!ctx->mBootAnimCompleted)
+        processBootAnimCompleted(ctx);
+
+    if (LIKELY(list && (list->numHwLayers > 1 ||
+                    (ctx->mMDP.version < qdutils::MDP_V4_0 && compStart))) &&
+            (ctx->dpyAttr[dpy].isActive ||
+             ctx->mHDMIDisplay->isHDMIPrimaryDisplay())
+            && !ctx->dpyAttr[dpy].isPause) {
+        compStart = true;
+
+        // When HDMI is primary we should rely on the first valid
+        // draw call in order to activate the display
+        if (!ctx->dpyAttr[dpy].isActive) {
+            // If the cable is connected after HWC initialization and before
+            // the UEvent thread is initialized then we will miss the ONLINE
+            // event. We need to update the display appropriately when we get
+            // the first valid frame.
+            int cableConnected = ctx->mHDMIDisplay->getConnectedState();
+            if ((cableConnected == 1) && !ctx->dpyAttr[dpy].connected) {
+                qhwc::handle_online(ctx, dpy);
+            }
+            ctx->mHDMIDisplay->activateDisplay();
+            ctx->dpyAttr[dpy].isActive = true;
+        }
+
+        if (ctx->dpyAttr[dpy].customFBSize &&
+                list->flags & HWC_GEOMETRY_CHANGED)
+            scaleDisplayFrame(ctx, dpy, list);
+
+        reset_layer_prop(ctx, dpy, (int)list->numHwLayers - 1);
+        setListStats(ctx, list, dpy);
+
+        fbComp = (ctx->mMDPComp[dpy]->prepare(ctx, list) < 0);
+
+        if (fbComp) {
+            const int fbZ = 0;
+            if(not ctx->mFBUpdate[dpy]->prepareAndValidate(ctx, list, fbZ)) {
+                ctx->mOverlay->clear(dpy);
+                ctx->mLayerRotMap[dpy]->clear();
+            }
+        }
+
+        if (ctx->mMDP.version < qdutils::MDP_V4_0) {
+            if(ctx->mCopyBit[dpy])
+                ctx->mCopyBit[dpy]->prepare(ctx, list, dpy);
+        }
+        setGPUHint(ctx, list);
+    }
+    return 0;
+}
+
+static int hwc_prepare_external(hwc_composer_device_1 *dev,
+        hwc_display_contents_1_t *list) {
+    ATRACE_CALL();
+    hwc_context_t* ctx = (hwc_context_t*)(dev);
+    const int dpy = HWC_DISPLAY_EXTERNAL;
+
+    if (LIKELY(list && list->numHwLayers > 1) &&
+            ctx->dpyAttr[dpy].isActive &&
+            ctx->dpyAttr[dpy].connected) {
+        reset_layer_prop(ctx, dpy, (int)list->numHwLayers - 1);
+        if(!ctx->dpyAttr[dpy].isPause) {
+            ctx->dpyAttr[dpy].isConfiguring = false;
+            setListStats(ctx, list, dpy);
+            if(ctx->mMDPComp[dpy]->prepare(ctx, list) < 0) {
+                const int fbZ = 0;
+                if(not ctx->mFBUpdate[dpy]->prepareAndValidate(ctx, list, fbZ))
+                {
+                    ctx->mOverlay->clear(dpy);
+                    ctx->mLayerRotMap[dpy]->clear();
+                }
+            }
+        } else {
+            /* External Display is in Pause state.
+             * Mark all application layers as OVERLAY so that
+             * GPU will not compose.
+             */
+            for(size_t i = 0 ;i < (size_t)(list->numHwLayers - 1); i++) {
+                hwc_layer_1_t *layer = &list->hwLayers[i];
+                layer->compositionType = HWC_OVERLAY;
+            }
+        }
+    }
+    return 0;
+}
+
+static int hwc_prepare(hwc_composer_device_1 *dev, size_t numDisplays,
+                       hwc_display_contents_1_t** displays)
+{
+    int ret = 0;
+    hwc_context_t* ctx = (hwc_context_t*)(dev);
+
+    if (ctx->mPanelResetStatus) {
+        ALOGW("%s: panel is in bad state. reset the panel", __FUNCTION__);
+        reset_panel(dev);
+    }
+
+    //Will be unlocked at the end of set
+    ctx->mDrawLock.lock();
+    setPaddingRound(ctx, (int)numDisplays, displays);
+    setDMAState(ctx, (int)numDisplays, displays);
+    setNumActiveDisplays(ctx, (int)numDisplays, displays);
+    reset(ctx, (int)numDisplays, displays);
+
+    ctx->mOverlay->configBegin();
+    ctx->mRotMgr->configBegin();
+    overlay::Writeback::configBegin();
+
+    for (int32_t dpy = ((int32_t)numDisplays-1); dpy >=0 ; dpy--) {
+        hwc_display_contents_1_t *list = displays[dpy];
+        resetROI(ctx, dpy);
+        switch(dpy) {
+            case HWC_DISPLAY_PRIMARY:
+                ret = hwc_prepare_primary(dev, list);
+                break;
+            case HWC_DISPLAY_EXTERNAL:
+                ret = hwc_prepare_external(dev, list);
+                break;
+            case HWC_DISPLAY_VIRTUAL:
+                if(ctx->mHWCVirtual)
+                    ret = ctx->mHWCVirtual->prepare(dev, list);
+                break;
+            default:
+                ret = -EINVAL;
+        }
+    }
+
+    ctx->mOverlay->configDone();
+    ctx->mRotMgr->configDone();
+    overlay::Writeback::configDone();
+    // If VD list is deleted, mdp overlay pipe objects and writeback object
+    // are deleted as part of configDone functions.
+    // Proceed with HWCVirtualVDS object deletion.
+    if(ctx->mHWCVirtual)
+        ctx->mHWCVirtual->destroy(ctx, numDisplays, displays);
+
+    return ret;
+}
+
+static int hwc_eventControl(struct hwc_composer_device_1* dev, int dpy,
+                             int event, int enable)
+{
+    ATRACE_CALL();
+    int ret = 0;
+    hwc_context_t* ctx = (hwc_context_t*)(dev);
+    if(!validDisplay(dpy)) {
+        return -EINVAL;
+    }
+
+    switch(event) {
+        case HWC_EVENT_VSYNC:
+            if (ctx->vstate.enable == enable)
+                break;
+            ret = hwc_vsync_control(ctx, dpy, enable);
+            if(ret == 0)
+                ctx->vstate.enable = !!enable;
+            ALOGD_IF (VSYNC_DEBUG, "VSYNC state changed to %s",
+                      (enable)?"ENABLED":"DISABLED");
+            break;
+#ifdef QTI_BSP
+        case  HWC_EVENT_ORIENTATION:
+            if(dpy == HWC_DISPLAY_PRIMARY) {
+                Locker::Autolock _l(ctx->mDrawLock);
+                // store the primary display orientation
+                ctx->deviceOrientation = enable;
+            }
+            break;
+#endif
+        default:
+            ret = -EINVAL;
+    }
+    return ret;
+}
+
+static int hwc_setPowerMode(struct hwc_composer_device_1* dev, int dpy,
+        int mode)
+{
+    ATRACE_CALL();
+    hwc_context_t* ctx = (hwc_context_t*)(dev);
+    int ret = 0, value = 0;
+
+    Locker::Autolock _l(ctx->mDrawLock);
+
+    if(!validDisplay(dpy)) {
+        return -EINVAL;
+    }
+
+    ALOGD_IF(POWER_MODE_DEBUG, "%s: Setting mode %d on display: %d",
+            __FUNCTION__, mode, dpy);
+
+    switch(mode) {
+        case HWC_POWER_MODE_OFF:
+            // free up all the overlay pipes in use
+            // when we get a blank for either display
+            // makes sure that all pipes are freed
+            ctx->mOverlay->configBegin();
+            ctx->mOverlay->configDone();
+            ctx->mRotMgr->clear();
+            // If VDS is connected, do not clear WB object as it
+            // will end up detaching IOMMU. This is required
+            // to send black frame to WFD sink on power suspend.
+            // Note: With this change, we keep the WriteBack object
+            // alive on power suspend for AD use case.
+            value = FB_BLANK_POWERDOWN;
+            break;
+        case HWC_POWER_MODE_DOZE:
+        case HWC_POWER_MODE_DOZE_SUSPEND:
+            value = FB_BLANK_VSYNC_SUSPEND;
+            break;
+        case HWC_POWER_MODE_NORMAL:
+            value = FB_BLANK_UNBLANK;
+            break;
+    }
+
+    switch(dpy) {
+    case HWC_DISPLAY_PRIMARY:
+        if(ctx->mHDMIDisplay->isHDMIPrimaryDisplay()) {
+            if(ctx->dpyAttr[dpy].connected) {
+                // When HDMI is connected as primary we clean up resources
+                // and call commit to generate a black frame on the interface.
+                // However, we do not call blank since we need the timing
+                // generator and HDMI core to remain turned on.
+                if((mode == HWC_POWER_MODE_OFF) &&
+                        (!Overlay::displayCommit(ctx->dpyAttr[dpy].fd))) {
+                    ALOGE("%s: display commit fail for %d", __FUNCTION__, dpy);
+                    ret = -1;
+                }
+            }
+        } else {
+            if(ioctl(ctx->dpyAttr[dpy].fd, FBIOBLANK, value) < 0 ) {
+                ALOGE("%s: ioctl FBIOBLANK failed for Primary with error %s"
+                        " value %d", __FUNCTION__, strerror(errno), value);
+                return -errno;
+            }
+
+            if(mode == HWC_POWER_MODE_NORMAL) {
+                // Enable HPD here, as during bootup POWER_MODE_NORMAL is set
+                // when SF is completely initialized
+                ctx->mHDMIDisplay->setHPD(1);
+            }
+
+            ctx->dpyAttr[dpy].isActive = not(mode == HWC_POWER_MODE_OFF);
+        }
+        //Deliberate fall through since there is no explicit power mode for
+        //virtual displays.
+    case HWC_DISPLAY_VIRTUAL:
+        if(ctx->dpyAttr[HWC_DISPLAY_VIRTUAL].connected) {
+            const int dpy = HWC_DISPLAY_VIRTUAL;
+            if(mode == HWC_POWER_MODE_OFF and
+                    (not ctx->dpyAttr[dpy].isPause)) {
+                if(!Overlay::displayCommit(ctx->dpyAttr[dpy].fd)) {
+                    ALOGE("%s: displayCommit failed for virtual", __FUNCTION__);
+                    ret = -1;
+                }
+            }
+            ctx->dpyAttr[dpy].isActive = not(mode == HWC_POWER_MODE_OFF);
+        }
+        break;
+    case HWC_DISPLAY_EXTERNAL:
+        if(mode == HWC_POWER_MODE_OFF) {
+            if(!Overlay::displayCommit(ctx->dpyAttr[dpy].fd)) {
+                ALOGE("%s: displayCommit failed for external", __FUNCTION__);
+                ret = -1;
+            }
+        }
+        ctx->dpyAttr[dpy].isActive = not(mode == HWC_POWER_MODE_OFF);
+        break;
+    default:
+        return -EINVAL;
+    }
+
+    ALOGD_IF(POWER_MODE_DEBUG, "%s: Done setting mode %d on display %d",
+            __FUNCTION__, mode, dpy);
+    return ret;
+}
+
+static void reset_panel(struct hwc_composer_device_1* dev)
+{
+    int ret = 0;
+    hwc_context_t* ctx = (hwc_context_t*)(dev);
+
+    if (!ctx->dpyAttr[HWC_DISPLAY_PRIMARY].isActive) {
+        ALOGD ("%s : Display OFF - Skip BLANK & UNBLANK", __FUNCTION__);
+        ctx->mPanelResetStatus = false;
+        return;
+    }
+
+    ALOGD("%s: setting power mode off", __FUNCTION__);
+    ret = hwc_setPowerMode(dev, HWC_DISPLAY_PRIMARY, HWC_POWER_MODE_OFF);
+    if (ret < 0) {
+        ALOGE("%s: FBIOBLANK failed to BLANK:  %s", __FUNCTION__,
+                strerror(errno));
+    }
+
+    ALOGD("%s: setting power mode normal and enabling vsync", __FUNCTION__);
+    ret = hwc_setPowerMode(dev, HWC_DISPLAY_PRIMARY, HWC_POWER_MODE_NORMAL);
+    if (ret < 0) {
+        ALOGE("%s: FBIOBLANK failed to UNBLANK : %s", __FUNCTION__,
+                strerror(errno));
+    }
+    hwc_vsync_control(ctx, HWC_DISPLAY_PRIMARY, 1);
+
+    ctx->mPanelResetStatus = false;
+}
+
+
+static int hwc_query(struct hwc_composer_device_1* dev,
+                     int param, int* value)
+{
+    hwc_context_t* ctx = (hwc_context_t*)(dev);
+    int supported = HWC_DISPLAY_PRIMARY_BIT;
+
+    switch (param) {
+    case HWC_BACKGROUND_LAYER_SUPPORTED:
+        // Not supported for now
+        value[0] = 0;
+        break;
+    case HWC_DISPLAY_TYPES_SUPPORTED:
+        if(ctx->mMDP.hasOverlay) {
+            supported |= HWC_DISPLAY_VIRTUAL_BIT;
+            if(!(qdutils::MDPVersion::getInstance().is8x26() ||
+                        qdutils::MDPVersion::getInstance().is8x16() ||
+                        qdutils::MDPVersion::getInstance().is8x39()))
+                supported |= HWC_DISPLAY_EXTERNAL_BIT;
+        }
+        value[0] = supported;
+        break;
+    case HWC_FORMAT_RB_SWAP:
+        value[0] = 1;
+        break;
+    case HWC_COLOR_FILL:
+        value[0] = 1;
+        break;
+    default:
+        return -EINVAL;
+    }
+    return 0;
+
+}
+
+
+static int hwc_set_primary(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
+    ATRACE_CALL();
+    int ret = 0;
+    const int dpy = HWC_DISPLAY_PRIMARY;
+    if (LIKELY(list) && ctx->dpyAttr[dpy].isActive
+            && !ctx->dpyAttr[dpy].isPause) {
+        size_t last = list->numHwLayers - 1;
+        hwc_layer_1_t *fbLayer = &list->hwLayers[last];
+        int fd = -1; //FenceFD from the Copybit(valid in async mode)
+        bool copybitDone = false;
+
+        if (ctx->mCopyBit[dpy]) {
+            if (ctx->mMDP.version < qdutils::MDP_V4_0)
+                copybitDone = ctx->mCopyBit[dpy]->draw(ctx, list, dpy, &fd);
+            else
+                fd = ctx->mMDPComp[dpy]->drawOverlap(ctx, list);
+        }
+
+        if(list->numHwLayers > 1)
+            hwc_sync(ctx, list, dpy, fd);
+
+        // Dump the layers for primary
+        if(ctx->mHwcDebug[dpy])
+            ctx->mHwcDebug[dpy]->dumpLayers(list);
+
+        if (!ctx->mMDPComp[dpy]->draw(ctx, list)) {
+            ALOGE("%s: MDPComp draw failed", __FUNCTION__);
+            ret = -1;
+        }
+
+        //TODO We dont check for SKIP flag on this layer because we need PAN
+        //always. Last layer is always FB
+        private_handle_t *hnd = (private_handle_t *)fbLayer->handle;
+        if(copybitDone && ((ctx->mMDP.version >= qdutils::MDP_V4_0)
+#ifdef SUPPORT_BLIT_TO_FB
+                            || (ctx->mMDP.version == qdutils::MDP_V3_0_5)
+#endif
+        )) {
+            hnd = ctx->mCopyBit[dpy]->getCurrentRenderBuffer();
+        }
+
+        if(isAbcInUse(ctx) == true) {
+            int index = ctx->listStats[dpy].renderBufIndexforABC;
+            hwc_layer_1_t *tempLayer = &list->hwLayers[index];
+            hnd = (private_handle_t *)tempLayer->handle;
+        }
+
+        if(hnd) {
+            if (!ctx->mFBUpdate[dpy]->draw(ctx, hnd)) {
+                ALOGE("%s: FBUpdate draw failed", __FUNCTION__);
+                ret = -1;
+            }
+        }
+
+        int lSplit = getLeftSplit(ctx, dpy);
+        qhwc::ovutils::Dim lRoi = qhwc::ovutils::Dim(
+            ctx->listStats[dpy].lRoi.left,
+            ctx->listStats[dpy].lRoi.top,
+            ctx->listStats[dpy].lRoi.right - ctx->listStats[dpy].lRoi.left,
+            ctx->listStats[dpy].lRoi.bottom - ctx->listStats[dpy].lRoi.top);
+
+        qhwc::ovutils::Dim rRoi = qhwc::ovutils::Dim(
+            ctx->listStats[dpy].rRoi.left - lSplit,
+            ctx->listStats[dpy].rRoi.top,
+            ctx->listStats[dpy].rRoi.right - ctx->listStats[dpy].rRoi.left,
+            ctx->listStats[dpy].rRoi.bottom - ctx->listStats[dpy].rRoi.top);
+
+        if(!Overlay::displayCommit(ctx->dpyAttr[dpy].fd, lRoi, rRoi)) {
+            ALOGE("%s: display commit fail for %d dpy!", __FUNCTION__, dpy);
+            ret = -1;
+        }
+
+    }
+
+    closeAcquireFds(list);
+    return ret;
+}
+
+static int hwc_set_external(hwc_context_t *ctx,
+                            hwc_display_contents_1_t* list)
+{
+    ATRACE_CALL();
+    int ret = 0;
+
+    const int dpy = HWC_DISPLAY_EXTERNAL;
+
+    if (LIKELY(list) && ctx->dpyAttr[dpy].isActive &&
+        ctx->dpyAttr[dpy].connected &&
+        !ctx->dpyAttr[dpy].isPause) {
+        size_t last = list->numHwLayers - 1;
+        hwc_layer_1_t *fbLayer = &list->hwLayers[last];
+        int fd = -1; //FenceFD from the Copybit(valid in async mode)
+        bool copybitDone = false;
+        if(ctx->mCopyBit[dpy])
+            copybitDone = ctx->mCopyBit[dpy]->draw(ctx, list, dpy, &fd);
+
+        if(list->numHwLayers > 1)
+            hwc_sync(ctx, list, dpy, fd);
+
+        // Dump the layers for external
+        if(ctx->mHwcDebug[dpy])
+            ctx->mHwcDebug[dpy]->dumpLayers(list);
+
+        if (!ctx->mMDPComp[dpy]->draw(ctx, list)) {
+            ALOGE("%s: MDPComp draw failed", __FUNCTION__);
+            ret = -1;
+        }
+
+        private_handle_t *hnd = (private_handle_t *)fbLayer->handle;
+        if(copybitDone) {
+            hnd = ctx->mCopyBit[dpy]->getCurrentRenderBuffer();
+        }
+
+        if(hnd) {
+            if (!ctx->mFBUpdate[dpy]->draw(ctx, hnd)) {
+                ALOGE("%s: FBUpdate::draw fail!", __FUNCTION__);
+                ret = -1;
+            }
+        }
+
+        if(!Overlay::displayCommit(ctx->dpyAttr[dpy].fd)) {
+            ALOGE("%s: display commit fail for %d dpy!", __FUNCTION__, dpy);
+            ret = -1;
+        }
+    }
+
+    closeAcquireFds(list);
+    return ret;
+}
+
+static int hwc_set(hwc_composer_device_1 *dev,
+                   size_t numDisplays,
+                   hwc_display_contents_1_t** displays)
+{
+    int ret = 0;
+    hwc_context_t* ctx = (hwc_context_t*)(dev);
+    for (int dpy = 0; dpy < (int)numDisplays; dpy++) {
+        hwc_display_contents_1_t* list = displays[dpy];
+        switch(dpy) {
+            case HWC_DISPLAY_PRIMARY:
+                ret = hwc_set_primary(ctx, list);
+                break;
+            case HWC_DISPLAY_EXTERNAL:
+                ret = hwc_set_external(ctx, list);
+                break;
+            case HWC_DISPLAY_VIRTUAL:
+                if(ctx->mHWCVirtual)
+                    ret = ctx->mHWCVirtual->set(ctx, list);
+                break;
+            default:
+                ret = -EINVAL;
+        }
+    }
+    // This is only indicative of how many times SurfaceFlinger posts
+    // frames to the display.
+    CALC_FPS();
+    MDPComp::resetIdleFallBack();
+    ctx->mVideoTransFlag = false;
+    //Was locked at the beginning of prepare
+    ctx->mDrawLock.unlock();
+    return ret;
+}
+
+int hwc_getDisplayConfigs(struct hwc_composer_device_1* dev, int disp,
+        uint32_t* configs, size_t* numConfigs) {
+    int ret = 0;
+    hwc_context_t* ctx = (hwc_context_t*)(dev);
+
+    Locker::Autolock _l(ctx->mDrawLock);
+
+    if(!validDisplay(disp)) {
+        return -EINVAL;
+    }
+    //Currently we allow only 1 config, reported as config id # 0
+    //This config is passed in to getDisplayAttributes. Ignored for now.
+
+    switch(disp) {
+        case HWC_DISPLAY_PRIMARY:
+            if(*numConfigs > 0) {
+                configs[0] = 0;
+                *numConfigs = 1;
+            }
+            ret = 0; //NO_ERROR
+            break;
+        case HWC_DISPLAY_EXTERNAL:
+        case HWC_DISPLAY_VIRTUAL:
+            ret = -1; //Not connected
+            if(ctx->dpyAttr[disp].connected) {
+                ret = 0; //NO_ERROR
+                if(*numConfigs > 0) {
+                    configs[0] = 0;
+                    *numConfigs = 1;
+                }
+            }
+            break;
+    }
+    return ret;
+}
+
+int hwc_getDisplayAttributes(struct hwc_composer_device_1* dev, int disp,
+        uint32_t /*config*/, const uint32_t* attributes, int32_t* values) {
+
+    hwc_context_t* ctx = (hwc_context_t*)(dev);
+
+    Locker::Autolock _l(ctx->mDrawLock);
+
+    if(!validDisplay(disp)) {
+        return -EINVAL;
+    }
+    //If hotpluggable displays(i.e, HDMI, WFD) are inactive return error
+    if( (disp != HWC_DISPLAY_PRIMARY) && !ctx->dpyAttr[disp].connected) {
+        return -1;
+    }
+
+    //From HWComposer
+    static const uint32_t DISPLAY_ATTRIBUTES[] = {
+        HWC_DISPLAY_VSYNC_PERIOD,
+        HWC_DISPLAY_WIDTH,
+        HWC_DISPLAY_HEIGHT,
+        HWC_DISPLAY_DPI_X,
+        HWC_DISPLAY_DPI_Y,
+#ifdef GET_FRAMEBUFFER_FORMAT_FROM_HWC
+        HWC_DISPLAY_FBFORMAT,
+#endif
+        HWC_DISPLAY_NO_ATTRIBUTE,
+    };
+
+    const size_t NUM_DISPLAY_ATTRIBUTES = (sizeof(DISPLAY_ATTRIBUTES) /
+            sizeof(DISPLAY_ATTRIBUTES)[0]);
+
+    for (size_t i = 0; i < NUM_DISPLAY_ATTRIBUTES - 1; i++) {
+        switch (attributes[i]) {
+        case HWC_DISPLAY_VSYNC_PERIOD:
+            values[i] = ctx->dpyAttr[disp].vsync_period;
+            break;
+        case HWC_DISPLAY_WIDTH:
+            if (ctx->dpyAttr[disp].customFBSize)
+                values[i] = ctx->dpyAttr[disp].xres_new;
+            else
+                values[i] = ctx->dpyAttr[disp].xres;
+
+            ALOGD("%s disp = %d, width = %d",__FUNCTION__, disp,
+                    values[i]);
+            break;
+        case HWC_DISPLAY_HEIGHT:
+            if (ctx->dpyAttr[disp].customFBSize)
+                values[i] = ctx->dpyAttr[disp].yres_new;
+            else
+                values[i] = ctx->dpyAttr[disp].yres;
+            ALOGD("%s disp = %d, height = %d",__FUNCTION__, disp,
+                    values[i]);
+            break;
+        case HWC_DISPLAY_DPI_X:
+            values[i] = (int32_t) (ctx->dpyAttr[disp].xdpi*1000.0);
+            break;
+        case HWC_DISPLAY_DPI_Y:
+            values[i] = (int32_t) (ctx->dpyAttr[disp].ydpi*1000.0);
+            break;
+#ifdef GET_FRAMEBUFFER_FORMAT_FROM_HWC
+        case HWC_DISPLAY_FBFORMAT:
+            values[i] = ctx->dpyAttr[disp].fbformat;
+            break;
+#endif
+        default:
+            ALOGE("Unknown display attribute %d",
+                    attributes[i]);
+            return -EINVAL;
+        }
+    }
+    return 0;
+}
+
+void hwc_dump(struct hwc_composer_device_1* dev, char *buff, int buff_len)
+{
+    hwc_context_t* ctx = (hwc_context_t*)(dev);
+    Locker::Autolock _l(ctx->mDrawLock);
+    android::String8 aBuf("");
+    dumpsys_log(aBuf, "Qualcomm HWC state:\n");
+    dumpsys_log(aBuf, "  MDPVersion=%d\n", ctx->mMDP.version);
+    dumpsys_log(aBuf, "  DisplayPanel=%c\n", ctx->mMDP.panel);
+    dumpsys_log(aBuf, "  DynRefreshRate=%d\n",
+                ctx->dpyAttr[HWC_DISPLAY_PRIMARY].dynRefreshRate);
+    for(int dpy = 0; dpy < HWC_NUM_DISPLAY_TYPES; dpy++) {
+        if(ctx->mMDPComp[dpy])
+            ctx->mMDPComp[dpy]->dump(aBuf, ctx);
+    }
+    char ovDump[2048] = {'\0'};
+    ctx->mOverlay->getDump(ovDump, 2048);
+    dumpsys_log(aBuf, ovDump);
+    ovDump[0] = '\0';
+    ctx->mRotMgr->getDump(ovDump, 1024);
+    dumpsys_log(aBuf, ovDump);
+    ovDump[0] = '\0';
+    if(Writeback::getDump(ovDump, 1024)) {
+        dumpsys_log(aBuf, ovDump);
+        ovDump[0] = '\0';
+    }
+    dumpsys_log(aBuf, "Copybit::isAbcInUse=%d\n\n",isAbcInUse(ctx) ? 1 : 0);
+    strlcpy(buff, aBuf.string(), buff_len);
+}
+
+int hwc_getActiveConfig(struct hwc_composer_device_1* dev, int disp) {
+    hwc_context_t* ctx = (hwc_context_t*)(dev);
+    Locker::Autolock _l(ctx->mDrawLock);
+    if(!validDisplay(disp)) {
+        return -EINVAL;
+    }
+
+    //Supports only the default config (0th index) for now
+    return 0;
+}
+
+int hwc_setActiveConfig(struct hwc_composer_device_1* dev, int disp,
+        int index) {
+    hwc_context_t* ctx = (hwc_context_t*)(dev);
+    Locker::Autolock _l(ctx->mDrawLock);
+    if(!validDisplay(disp)) {
+        return -EINVAL;
+    }
+
+    //Supports only the default config (0th index) for now
+    return (index == 0) ? index : -EINVAL;
+}
+
+static int hwc_device_close(struct hw_device_t *dev)
+{
+    if(!dev) {
+        ALOGE("%s: NULL device pointer", __FUNCTION__);
+        return -1;
+    }
+    closeContext((hwc_context_t*)dev);
+    free(dev);
+
+    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)) {
+        struct hwc_context_t *dev;
+        dev = (hwc_context_t*)malloc(sizeof(*dev));
+        if(dev == NULL)
+            return status;
+        memset(dev, 0, sizeof(*dev));
+
+        //Initialize hwc context
+        initContext(dev);
+
+        //Setup HWC methods
+        dev->device.common.tag          = HARDWARE_DEVICE_TAG;
+        dev->device.common.version      = HWC_DEVICE_API_VERSION_1_5;
+        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.eventControl        = hwc_eventControl;
+        dev->device.setPowerMode        = hwc_setPowerMode;
+        dev->device.query               = hwc_query;
+        dev->device.registerProcs       = hwc_registerProcs;
+        dev->device.dump                = hwc_dump;
+        dev->device.getDisplayConfigs   = hwc_getDisplayConfigs;
+        dev->device.getDisplayAttributes = hwc_getDisplayAttributes;
+        dev->device.getActiveConfig     = hwc_getActiveConfig;
+        dev->device.setActiveConfig     = hwc_setActiveConfig;
+        *device = &dev->device.common;
+        status = 0;
+    }
+    return status;
+}
diff --git a/msm8909/libhwcomposer/hwc_ad.cpp b/msm8909/libhwcomposer/hwc_ad.cpp
new file mode 100644
index 0000000..7e96d97
--- /dev/null
+++ b/msm8909/libhwcomposer/hwc_ad.cpp
@@ -0,0 +1,278 @@
+/*
+* Copyright (c) 2013-2014 The Linux Foundation. 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 The Linux Foundation. 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.
+*/
+
+#include <unistd.h>
+#include <overlay.h>
+#include <overlayUtils.h>
+#include <overlayWriteback.h>
+#include <mdp_version.h>
+#include "hwc_ad.h"
+#include "hwc_utils.h"
+
+#define DEBUG 0
+using namespace overlay;
+using namespace overlay::utils;
+namespace qhwc {
+
+//Helper to write data to ad node
+static void adWrite(const int& value) {
+    const int wbFbNum = Overlay::getFbForDpy(Overlay::DPY_WRITEBACK);
+    char wbFbPath[256];
+    snprintf (wbFbPath, sizeof(wbFbPath),
+            "/sys/class/graphics/fb%d/ad", wbFbNum);
+    int adFd = open(wbFbPath, O_WRONLY);
+    if(adFd >= 0) {
+        char opStr[4] = "";
+        snprintf(opStr, sizeof(opStr), "%d", value);
+        ssize_t ret = write(adFd, opStr, strlen(opStr));
+        if(ret < 0) {
+            ALOGE("%s: Failed to write %d with error %s",
+                    __func__, value, strerror(errno));
+        } else if (ret == 0){
+            ALOGE("%s Nothing written to ad", __func__);
+        } else {
+            ALOGD_IF(DEBUG, "%s: Wrote %d to ad", __func__, value);
+        }
+        close(adFd);
+    } else {
+        ALOGE("%s: Failed to open /sys/class/graphics/fb%d/ad with error %s",
+                __func__, wbFbNum, strerror(errno));
+    }
+}
+
+//Helper to read data from ad node
+static int adRead() {
+    const int wbFbNum = Overlay::getFbForDpy(Overlay::DPY_WRITEBACK);
+    int ret = -1;
+    char wbFbPath[256];
+    snprintf (wbFbPath, sizeof(wbFbPath),
+            "/sys/class/graphics/fb%d/ad", wbFbNum);
+    int adFd = open(wbFbPath, O_RDONLY);
+    if(adFd >= 0) {
+        char opStr[4];
+        ssize_t bytesRead = read(adFd, opStr, sizeof(opStr) - 1);
+        if(bytesRead > 0) {
+            opStr[bytesRead] = '\0';
+            //Should return -1, 0 or 1
+            ret = atoi(opStr);
+            ALOGD_IF(DEBUG, "%s: Read %d from ad", __func__, ret);
+        } else if(bytesRead == 0) {
+            ALOGE("%s: ad node empty", __func__);
+        } else {
+            ALOGE("%s: Read from ad node failed with error %s", __func__,
+                    strerror(errno));
+        }
+        close(adFd);
+    } else {
+        ALOGD("%s: /sys/class/graphics/fb%d/ad could not be opened : %s",
+                __func__, wbFbNum, strerror(errno));
+    }
+    return ret;
+}
+
+AssertiveDisplay::AssertiveDisplay(hwc_context_t *ctx) :
+     mTurnedOff(true), mFeatureEnabled(false),
+     mDest(overlay::utils::OV_INVALID)
+{
+    //Values in ad node:
+    //-1 means feature is disabled on device
+    // 0 means feature exists but turned off, will be turned on by hwc
+    // 1 means feature is turned on by hwc
+    // Plus, we do this feature only on split primary displays.
+    // Plus, we do this feature only if ro.qcom.ad=2
+
+    char property[PROPERTY_VALUE_MAX];
+    const int ENABLED = 2;
+    int val = 0;
+
+    if(property_get("ro.qcom.ad", property, "0") > 0) {
+        val = atoi(property);
+    }
+
+    if(adRead() >= 0 && isDisplaySplit(ctx, HWC_DISPLAY_PRIMARY) &&
+            val == ENABLED) {
+        ALOGD_IF(DEBUG, "Assertive display feature supported");
+        mFeatureEnabled = true;
+        // If feature exists but is turned off, set mTurnedOff to true
+        mTurnedOff = adRead() > 0 ? false : true;
+    }
+}
+
+void AssertiveDisplay::markDoable(hwc_context_t *ctx,
+        const hwc_display_contents_1_t* list) {
+    mDoable = false;
+    if(mFeatureEnabled &&
+        !isSecondaryConnected(ctx) &&
+        ctx->listStats[HWC_DISPLAY_PRIMARY].yuvCount == 1) {
+        int nYuvIndex = ctx->listStats[HWC_DISPLAY_PRIMARY].yuvIndices[0];
+        const hwc_layer_1_t* layer = &list->hwLayers[nYuvIndex];
+        private_handle_t *hnd = (private_handle_t *)layer->handle;
+        qdutils::MDPVersion& mdpHw =  qdutils::MDPVersion::getInstance();
+        if(hnd && hnd->width <= (int) mdpHw.getMaxMixerWidth()) {
+            mDoable = true;
+        }
+    }
+}
+
+void AssertiveDisplay::turnOffAD() {
+    if(mFeatureEnabled) {
+        if(!mTurnedOff) {
+            const int off = 0;
+            adWrite(off);
+            mTurnedOff = true;
+        }
+    }
+    mDoable = false;
+}
+
+bool AssertiveDisplay::prepare(hwc_context_t *ctx,
+        const hwc_rect_t& crop,
+        const Whf& whf,
+        const private_handle_t *hnd) {
+    if(!isDoable()) {
+        //Cleanup one time during this switch
+        turnOffAD();
+        return false;
+    }
+
+    Overlay::PipeSpecs pipeSpecs;
+    pipeSpecs.formatClass = Overlay::FORMAT_YUV;
+    pipeSpecs.dpy = overlay::Overlay::DPY_WRITEBACK;
+    pipeSpecs.fb = false;
+
+    ovutils::eDest dest = ctx->mOverlay->getPipe(pipeSpecs);
+    if(dest == OV_INVALID) {
+        ALOGE("%s failed: No VG pipe available", __func__);
+        mDoable = false;
+        return false;
+    }
+
+    overlay::Writeback *wb = overlay::Writeback::getInstance();
+
+    //Set Security flag on writeback
+    if(isSecureBuffer(hnd)) {
+        if(!wb->setSecure(isSecureBuffer(hnd))) {
+            ALOGE("Failure in setting WB secure flag for ad");
+            return false;
+        }
+    }
+
+    if(!wb->configureDpyInfo(hnd->width, hnd->height)) {
+        ALOGE("%s: config display failed", __func__);
+        mDoable = false;
+        return false;
+    }
+
+    int tmpW, tmpH;
+    size_t size;
+    int format = ovutils::getHALFormat(wb->getOutputFormat());
+    if(format < 0) {
+        ALOGE("%s invalid format %d", __func__, format);
+        mDoable = false;
+        return false;
+    }
+
+    size = getBufferSizeAndDimensions(hnd->width, hnd->height,
+                format, tmpW, tmpH);
+
+    if(!wb->configureMemory((uint32_t)size)) {
+        ALOGE("%s: config memory failed", __func__);
+        mDoable = false;
+        return false;
+    }
+
+    eMdpFlags mdpFlags = OV_MDP_FLAGS_NONE;
+    if(isSecureBuffer(hnd)) {
+        ovutils::setMdpFlags(mdpFlags,
+                ovutils::OV_MDP_SECURE_OVERLAY_SESSION);
+    }
+
+    PipeArgs parg(mdpFlags, whf, ZORDER_0,
+            ROT_FLAGS_NONE);
+    hwc_rect_t dst = crop; //input same as output
+
+    if(configMdp(ctx->mOverlay, parg, OVERLAY_TRANSFORM_0, crop, dst, NULL,
+                dest) < 0) {
+        ALOGE("%s: configMdp failed", __func__);
+        mDoable = false;
+        return false;
+    }
+
+    mDest = dest;
+    int wbFd = wb->getFbFd();
+    if(mFeatureEnabled && wbFd >= 0 &&
+        !ctx->mOverlay->validateAndSet(overlay::Overlay::DPY_WRITEBACK, wbFd))
+    {
+        ALOGE("%s: Failed to validate and set overlay for dpy %d"
+                ,__FUNCTION__, overlay::Overlay::DPY_WRITEBACK);
+        turnOffAD();
+        return false;
+    }
+
+    // Only turn on AD if there are no errors during configuration stage
+    // and if it was previously in OFF state.
+    if(mFeatureEnabled && mTurnedOff) {
+        //write to sysfs, one time during this switch
+        const int on = 1;
+        adWrite(on);
+        mTurnedOff = false;
+    }
+
+    return true;
+}
+
+bool AssertiveDisplay::draw(hwc_context_t *ctx, int fd, uint32_t offset) {
+    if(!isDoable()) {
+        return false;
+    }
+
+    if (!ctx->mOverlay->queueBuffer(fd, offset, mDest)) {
+        ALOGE("%s: queueBuffer failed", __func__);
+        return false;
+    }
+
+    overlay::Writeback *wb = overlay::Writeback::getInstance();
+    if(!wb->writeSync()) {
+        return false;
+    }
+
+    return true;
+}
+
+int AssertiveDisplay::getDstFd() const {
+    overlay::Writeback *wb = overlay::Writeback::getInstance();
+    return wb->getDstFd();
+}
+
+uint32_t AssertiveDisplay::getDstOffset() const {
+    overlay::Writeback *wb = overlay::Writeback::getInstance();
+    return wb->getOffset();
+}
+
+}
diff --git a/msm8909/libhwcomposer/hwc_ad.h b/msm8909/libhwcomposer/hwc_ad.h
new file mode 100644
index 0000000..0be5f5d
--- /dev/null
+++ b/msm8909/libhwcomposer/hwc_ad.h
@@ -0,0 +1,66 @@
+/*
+* Copyright (c) 2013 The Linux Foundation. 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 The Linux Foundation. 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 HWC_AD_H
+#define HWC_AD_H
+
+#include <overlayUtils.h>
+#include <hwc_utils.h>
+
+struct hwc_context_t;
+
+namespace qhwc {
+
+class AssertiveDisplay {
+public:
+    AssertiveDisplay(hwc_context_t *ctx);
+    void markDoable(hwc_context_t *ctx, const hwc_display_contents_1_t* list);
+    bool prepare(hwc_context_t *ctx, const hwc_rect_t& crop,
+            const overlay::utils::Whf& whf,
+            const private_handle_t *hnd);
+    bool draw(hwc_context_t *ctx, int fd, uint32_t offset);
+    //Resets a few members on each draw round
+    void reset() { mDoable = false;
+            mDest = overlay::utils::OV_INVALID;
+    }
+    bool isDoable() const { return mDoable; }
+    int getDstFd() const;
+    uint32_t getDstOffset() const;
+
+private:
+    bool mDoable;
+    bool mTurnedOff;
+    //State of feature existence on certain devices and configs.
+    bool mFeatureEnabled;
+    overlay::utils::eDest mDest;
+    void turnOffAD();
+};
+
+}
+#endif
diff --git a/msm8909/libhwcomposer/hwc_copybit.cpp b/msm8909/libhwcomposer/hwc_copybit.cpp
new file mode 100644
index 0000000..8c1914f
--- /dev/null
+++ b/msm8909/libhwcomposer/hwc_copybit.cpp
@@ -0,0 +1,1374 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ * Copyright (C) 2012-2015, The Linux Foundation. All rights reserved.
+ *
+ * Not a Contribution.
+ *
+ * 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 DEBUG_COPYBIT 0
+#include <copybit.h>
+#include <utils/Timers.h>
+#include <mdp_version.h>
+#include "hwc_copybit.h"
+#include "comptype.h"
+#include "gr.h"
+#include "cb_utils.h"
+#include "cb_swap_rect.h"
+#include "math.h"
+#include "sync/sync.h"
+
+using namespace qdutils;
+namespace qhwc {
+
+struct range {
+    int current;
+    int end;
+};
+struct region_iterator : public copybit_region_t {
+
+    region_iterator(hwc_region_t region) {
+        mRegion = region;
+        r.end = (int)region.numRects;
+        r.current = 0;
+        this->next = iterate;
+    }
+
+private:
+    static int iterate(copybit_region_t const * self, copybit_rect_t* rect){
+        if (!self || !rect) {
+            ALOGE("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;
+};
+
+void CopyBit::reset() {
+    mIsModeOn = false;
+    mCopyBitDraw = false;
+}
+
+bool CopyBit::canUseCopybitForYUV(hwc_context_t *ctx) {
+    // return true for non-overlay targets
+    if(ctx->mMDP.hasOverlay && ctx->mMDP.version >= qdutils::MDP_V4_0) {
+       return false;
+    }
+    return true;
+}
+
+bool CopyBit::isSmartBlitPossible(const hwc_display_contents_1_t *list){
+    if(list->numHwLayers > 2) {
+        hwc_rect_t displayFrame0 = {0, 0, 0, 0};
+        hwc_rect_t displayFrame1 = {0, 0, 0, 0};
+        int layer0_transform     = 0;
+        int layer1_transform     = 0;
+        int isYuvLayer0          = 0;
+        int isYuvLayer1          = 0;
+        for (unsigned int i=0; i<list->numHwLayers -1; i++) {
+            hwc_rect_t displayFrame = list->hwLayers[i].displayFrame;
+            if (mSwapRect)
+               displayFrame = getIntersection(mDirtyRect,
+                                                list->hwLayers[i].displayFrame);
+            if (isValidRect(displayFrame) && !isValidRect(displayFrame0)) {
+                displayFrame0 = displayFrame;
+                private_handle_t *hnd =(private_handle_t *)list->hwLayers[i].handle;
+                isYuvLayer0 = isYuvBuffer(hnd);
+                layer0_transform = list->hwLayers[i].transform;
+            } else if(isValidRect(displayFrame)) {
+                displayFrame1 = displayFrame;
+                layer1_transform = list->hwLayers[i].transform;
+                private_handle_t *hnd =(private_handle_t *)list->hwLayers[i].handle;
+                isYuvLayer1 = isYuvBuffer(hnd);
+                break;
+            }
+        }
+        /*
+         *  smart blit enable only if
+         *  1. Both layers should have same ROI.
+         *  2. Both layers can't be video layer.
+         *  3. Should not be any rotation for base RGB layer.
+         *  4. In case of base layer as video, next above RGB layer
+         *     should not contains any rotation.
+         */
+        if((displayFrame0 == displayFrame1) && not (isYuvLayer1 && isYuvLayer0)) {
+            if (isYuvLayer0) {
+                if (not layer1_transform) {
+                    ALOGD_IF(DEBUG_COPYBIT,"%s:Smart Bilt Possible",__FUNCTION__);
+                    return true;
+                }
+            } else if (not layer0_transform) {
+                    ALOGD_IF(DEBUG_COPYBIT,"%s:Smart Bilt Possible",__FUNCTION__);
+                    return true;
+            }
+        }
+    }
+    return false;
+}
+
+bool CopyBit::canUseCopybitForRGB(hwc_context_t *ctx,
+                                        hwc_display_contents_1_t *list,
+                                        int dpy) {
+    int compositionType = qdutils::QCCompositionType::
+                                    getInstance().getCompositionType();
+
+    if (compositionType & qdutils::COMPOSITION_TYPE_DYN) {
+        // DYN Composition:
+        // use copybit, if (TotalRGBRenderArea < threashold * FB Area)
+        // this is done based on perf inputs in ICS
+        // TODO: Above condition needs to be re-evaluated in JB
+        int fbWidth =  ctx->dpyAttr[dpy].xres;
+        int fbHeight =  ctx->dpyAttr[dpy].yres;
+        unsigned int fbArea = (fbWidth * fbHeight);
+        unsigned int renderArea = getRGBRenderingArea(ctx, list);
+            ALOGD_IF (DEBUG_COPYBIT, "%s:renderArea %u, fbArea %u",
+                                  __FUNCTION__, renderArea, fbArea);
+        double dynThreshold = mDynThreshold;
+        if(not isSmartBlitPossible(list))
+            dynThreshold -= 1;
+
+        if (renderArea < (dynThreshold * fbArea)) {
+            return true;
+        }
+    } else if ((compositionType & qdutils::COMPOSITION_TYPE_MDP)) {
+      // MDP composition, use COPYBIT always
+      return true;
+    } else if ((compositionType & qdutils::COMPOSITION_TYPE_C2D)) {
+      // C2D composition, use COPYBIT
+      return true;
+    }
+    return false;
+}
+
+unsigned int CopyBit::getRGBRenderingArea (const hwc_context_t *ctx,
+                                     const hwc_display_contents_1_t *list) {
+    //Calculates total rendering area for RGB layers
+    unsigned int renderArea = 0;
+    unsigned int w=0, h=0;
+    // Skipping last layer since FrameBuffer layer should not affect
+    // which composition to choose
+    for (unsigned int i=0; i<list->numHwLayers -1; i++) {
+         private_handle_t *hnd = (private_handle_t *)list->hwLayers[i].handle;
+         if (hnd) {
+             if (BUFFER_TYPE_UI == hnd->bufferType && !ctx->copybitDrop[i]) {
+                 getLayerResolution(&list->hwLayers[i], w, h);
+                 renderArea += (w*h);
+             }
+         }
+    }
+    return renderArea;
+}
+
+bool CopyBit::isLayerChanging(hwc_context_t *ctx,
+                                 hwc_display_contents_1_t *list, int k) {
+    if((mLayerCache.hnd[k] != list->hwLayers[k].handle) ||
+            (mLayerCache.drop[k] != ctx->copybitDrop[k]) ||
+            (mLayerCache.displayFrame[k].left !=
+                         list->hwLayers[k].displayFrame.left) ||
+            (mLayerCache.displayFrame[k].top !=
+                         list->hwLayers[k].displayFrame.top) ||
+            (mLayerCache.displayFrame[k].right !=
+                         list->hwLayers[k].displayFrame.right) ||
+            (mLayerCache.displayFrame[k].bottom !=
+                         list->hwLayers[k].displayFrame.bottom)) {
+        return 1;
+    }
+    return 0;
+}
+
+bool CopyBit::prepareSwapRect(hwc_context_t *ctx,
+                           hwc_display_contents_1_t *list,
+                           int dpy) {
+   bool canUseSwapRect = 0;
+   hwc_rect_t dirtyRect = {0, 0, 0, 0};
+   hwc_rect_t displayRect = {0, 0, 0, 0};
+   hwc_rect fullFrame = (struct hwc_rect) {0, 0,(int)ctx->dpyAttr[dpy].xres,
+                                                (int)ctx->dpyAttr[dpy].yres};
+   if((mLayerCache.layerCount != ctx->listStats[dpy].numAppLayers) ||
+         list->flags & HWC_GEOMETRY_CHANGED || not mSwapRectEnable) {
+        mLayerCache.reset();
+        mFbCache.reset();
+        mLayerCache.updateCounts(ctx,list,dpy);
+        mDirtyRect = displayRect;
+        return 0;
+    }
+
+    int updatingLayerCount = 0;
+    for (int k = ctx->listStats[dpy].numAppLayers-1; k >= 0 ; k--){
+       //swap rect will kick in only for single updating layer
+       if(isLayerChanging(ctx, list, k)) {
+           updatingLayerCount ++;
+           hwc_layer_1_t layer = list->hwLayers[k];
+           canUseSwapRect = 1;
+#ifdef QTI_BSP
+           dirtyRect = getUnion(dirtyRect, calculateDirtyRect(&layer,fullFrame));
+#endif
+           displayRect = getUnion(displayRect, layer.displayFrame);
+       }
+    }
+    //since we are using more than one framebuffers,we have to
+    //kick in swap rect only if we are getting continuous same
+    //dirty rect for same layer at least equal of number of
+    //framebuffers
+
+      if (canUseSwapRect || updatingLayerCount == 0) {
+        if (updatingLayerCount == 0) {
+            dirtyRect.left = INVALID_DIMENSION;
+            dirtyRect.top = INVALID_DIMENSION;
+            dirtyRect.right = INVALID_DIMENSION;
+            dirtyRect.bottom = INVALID_DIMENSION;
+            canUseSwapRect = 1;
+        }
+
+       for (int k = ctx->listStats[dpy].numAppLayers-1; k >= 0 ; k--) {
+           //disable swap rect in case of scaling and video .
+           private_handle_t *hnd =(private_handle_t *)list->hwLayers[k].handle;
+           if(needsScaling(&list->hwLayers[k])||( hnd && isYuvBuffer(hnd)) ||
+                   (list->hwLayers[k].transform & HAL_TRANSFORM_ROT_90)) {
+               mFbCache.reset();
+               displayRect.bottom = 0;
+               displayRect.top = 0;
+               displayRect.right = 0;
+               displayRect.bottom = 0;
+               mDirtyRect = displayRect;
+               return 0;
+           }
+       }
+
+       if(mFbCache.getUnchangedFbDRCount(dirtyRect, displayRect) <
+                                             NUM_RENDER_BUFFERS) {
+              mFbCache.insertAndUpdateFbCache(dirtyRect, displayRect);
+              canUseSwapRect =  0;
+              displayRect.bottom = 0;
+              displayRect.top = 0;
+              displayRect.right = 0;
+              displayRect.bottom = 0;
+       }
+    } else {
+       mFbCache.reset();
+       canUseSwapRect =  0;
+       displayRect.bottom = 0;
+       displayRect.top = 0;
+       displayRect.right = 0;
+       displayRect.bottom = 0;
+
+    }
+    mDirtyRect = displayRect;
+    mLayerCache.updateCounts(ctx,list,dpy);
+    return canUseSwapRect;
+}
+
+bool CopyBit::prepareOverlap(hwc_context_t *ctx,
+                             hwc_display_contents_1_t *list) {
+
+    if (ctx->mMDP.version < qdutils::MDP_V4_0) {
+        ALOGE("%s: Invalid request", __FUNCTION__);
+        return false;
+    }
+
+    if (mEngine == NULL || !(validateParams(ctx, list))) {
+        ALOGE("%s: Invalid Params", __FUNCTION__);
+        return false;
+    }
+    PtorInfo* ptorInfo = &(ctx->mPtorInfo);
+
+    // Allocate render buffers if they're not allocated
+    int alignW = 0, alignH = 0;
+    int finalW = 0, finalH = 0;
+    for (int i = 0; i < ptorInfo->count; i++) {
+        int ovlapIndex = ptorInfo->layerIndex[i];
+        hwc_rect_t overlap = list->hwLayers[ovlapIndex].displayFrame;
+        // render buffer width will be the max of two layers
+        // Align Widht and height to 32, Mdp would be configured
+        // with Aligned overlap w/h
+        finalW = max(finalW, ALIGN((overlap.right - overlap.left), 32));
+        finalH += ALIGN((overlap.bottom - overlap.top), 32);
+        if(finalH > ALIGN((overlap.bottom - overlap.top), 32)) {
+            // Calculate the dest top, left will always be zero
+            ptorInfo->displayFrame[i].top = (finalH -
+                                (ALIGN((overlap.bottom - overlap.top), 32)));
+        }
+        // calculate the right and bottom values
+        ptorInfo->displayFrame[i].right =  ptorInfo->displayFrame[i].left +
+                                            (overlap.right - overlap.left);
+        ptorInfo->displayFrame[i].bottom = ptorInfo->displayFrame[i].top +
+                                            (overlap.bottom - overlap.top);
+    }
+
+    getBufferSizeAndDimensions(finalW, finalH, HAL_PIXEL_FORMAT_RGBA_8888,
+                               alignW, alignH);
+
+    if ((mAlignedWidth != alignW) || (mAlignedHeight != alignH)) {
+        // Overlap rect has changed, so free render buffers
+        freeRenderBuffers();
+    }
+
+    int ret = allocRenderBuffers(alignW, alignH, HAL_PIXEL_FORMAT_RGBA_8888);
+
+    if (ret < 0) {
+        ALOGE("%s: Render buffer allocation failed", __FUNCTION__);
+        return false;
+    }
+
+    mAlignedWidth = alignW;
+    mAlignedHeight = alignH;
+    mCurRenderBufferIndex = (mCurRenderBufferIndex + 1) % NUM_RENDER_BUFFERS;
+    return true;
+}
+
+bool CopyBit::prepare(hwc_context_t *ctx, hwc_display_contents_1_t *list,
+                                                            int dpy) {
+
+    if(mEngine == NULL) {
+        // No copybit device found - cannot use copybit
+        return false;
+    }
+
+    if(ctx->mThermalBurstMode) {
+        ALOGD_IF (DEBUG_COPYBIT, "%s:Copybit failed,"
+                "Running in Thermal Burst mode",__FUNCTION__);
+        return false;
+    }
+
+    int compositionType = qdutils::QCCompositionType::
+                                    getInstance().getCompositionType();
+
+    if ((compositionType == qdutils::COMPOSITION_TYPE_GPU) ||
+        (compositionType == qdutils::COMPOSITION_TYPE_CPU))   {
+        //GPU/CPU composition, don't change layer composition type
+        return true;
+    }
+
+    if(!(validateParams(ctx, list))) {
+        ALOGE("%s:Invalid Params", __FUNCTION__);
+        return false;
+    }
+
+    if(ctx->listStats[dpy].skipCount) {
+        //GPU will be anyways used
+        return false;
+    }
+
+    if (ctx->listStats[dpy].numAppLayers > MAX_NUM_APP_LAYERS) {
+        // Reached max layers supported by HWC.
+        return false;
+    }
+
+    int last = (uint32_t)list->numHwLayers - 1;
+    mDirtyRect = list->hwLayers[last].displayFrame;
+    mSwapRect =  prepareSwapRect(ctx, list, dpy);
+    ALOGD_IF (DEBUG_COPYBIT, "%s: mSwapRect: %d mDirtyRect: [%d, %d, %d, %d]",
+                           __FUNCTION__, mSwapRect, mDirtyRect.left,
+                           mDirtyRect.top, mDirtyRect.right, mDirtyRect.bottom);
+
+    bool useCopybitForYUV = canUseCopybitForYUV(ctx);
+    bool useCopybitForRGB = canUseCopybitForRGB(ctx, list, dpy);
+    LayerProp *layerProp = ctx->layerProp[dpy];
+
+    // Following are MDP3 limitations for which we
+    // need to fallback to GPU composition:
+    // 1. Plane alpha is not supported by MDP3.
+    // 2. Scaling is within range
+    if (qdutils::MDPVersion::getInstance().getMDPVersion() < 400) {
+        for (int i = ctx->listStats[dpy].numAppLayers-1; i >= 0 ; i--) {
+            int dst_h, dst_w, src_h, src_w;
+            float dx, dy;
+            if(ctx->copybitDrop[i]) {
+                continue;
+            }
+            hwc_layer_1_t *layer = (hwc_layer_1_t *) &list->hwLayers[i];
+            if (layer->planeAlpha != 0xFF)
+                return true;
+            hwc_rect_t sourceCrop = integerizeSourceCrop(layer->sourceCropf);
+
+            if (has90Transform(layer)) {
+                src_h = sourceCrop.right - sourceCrop.left;
+                src_w = sourceCrop.bottom - sourceCrop.top;
+            } else {
+                src_h = sourceCrop.bottom - sourceCrop.top;
+                src_w = sourceCrop.right - sourceCrop.left;
+            }
+            dst_h = layer->displayFrame.bottom - layer->displayFrame.top;
+            dst_w = layer->displayFrame.right - layer->displayFrame.left;
+
+            if(src_w <=0 || src_h<=0 ||dst_w<=0 || dst_h<=0 ) {
+              ALOGE("%s: wrong params for display screen_w=%d \
+                         src_crop_width=%d screen_h=%d src_crop_height=%d",
+                         __FUNCTION__, dst_w,src_w,dst_h,src_h);
+              return false;
+            }
+            dx = (float)dst_w/(float)src_w;
+            dy = (float)dst_h/(float)src_h;
+
+            float scale_factor_max = MAX_SCALE_FACTOR;
+            float scale_factor_min = MIN_SCALE_FACTOR;
+
+            if (isAlphaPresent(layer)) {
+               scale_factor_max = MAX_SCALE_FACTOR/4;
+               scale_factor_min = MIN_SCALE_FACTOR*4;
+            }
+
+            if (dx > scale_factor_max || dx < scale_factor_min)
+                return false;
+
+            if (dy > scale_factor_max || dy < scale_factor_min)
+                return false;
+        }
+    }
+
+    //Allocate render buffers if they're not allocated
+    if ((ctx->mMDP.version != qdutils::MDP_V3_0_4 &&
+#ifdef SUPPORT_BLIT_TO_FB
+            ctx->mMDP.version == qdutils::MDP_V3_0_5
+#else
+            ctx->mMDP.version != qdutils::MDP_V3_0_5
+#endif
+            ) && (useCopybitForYUV || useCopybitForRGB)) {
+        int ret = allocRenderBuffers(mAlignedWidth,
+                                     mAlignedHeight,
+                                     HAL_PIXEL_FORMAT_RGBA_8888);
+        if (ret < 0) {
+            return false;
+        } else {
+            mCurRenderBufferIndex = (mCurRenderBufferIndex + 1) %
+                NUM_RENDER_BUFFERS;
+        }
+    }
+
+    // We cannot mix copybit layer with layers marked to be drawn on FB
+    if (!useCopybitForYUV && ctx->listStats[dpy].yuvCount)
+        return true;
+
+    mCopyBitDraw = false;
+    if (useCopybitForRGB &&
+        (useCopybitForYUV || !ctx->listStats[dpy].yuvCount)) {
+        mCopyBitDraw =  true;
+        // numAppLayers-1, as we iterate till 0th layer index
+        // Mark all layers to be drawn by copybit
+        for (int i = ctx->listStats[dpy].numAppLayers-1; i >= 0 ; i--) {
+            layerProp[i].mFlags |= HWC_COPYBIT;
+#ifdef QTI_BSP
+            if (ctx->mMDP.version == qdutils::MDP_V3_0_4 ||
+               ctx->mMDP.version == qdutils::MDP_V3_0_5)
+                list->hwLayers[i].compositionType = HWC_BLIT;
+            else
+#endif
+                list->hwLayers[i].compositionType = HWC_OVERLAY;
+        }
+    }
+
+    return true;
+}
+
+int CopyBit::clear (private_handle_t* hnd, hwc_rect_t& rect)
+{
+    int ret = 0;
+    copybit_rect_t clear_rect = {rect.left, rect.top,
+        rect.right,
+        rect.bottom};
+
+    copybit_image_t buf;
+    buf.w = ALIGN(getWidth(hnd),32);
+    buf.h = getHeight(hnd);
+    buf.format = hnd->format;
+    buf.base = (void *)hnd->base;
+    buf.handle = (native_handle_t *)hnd;
+
+    copybit_device_t *copybit = mEngine;
+    ret = copybit->clear(copybit, &buf, &clear_rect);
+    return ret;
+}
+
+bool CopyBit::drawUsingAppBufferComposition(hwc_context_t *ctx,
+                                      hwc_display_contents_1_t *list,
+                                      int dpy, int *copybitFd) {
+     int layerCount = 0;
+     uint32_t last = (uint32_t)list->numHwLayers - 1;
+     hwc_layer_1_t *fbLayer = &list->hwLayers[last];
+     private_handle_t *fbhnd = (private_handle_t *)fbLayer->handle;
+
+    if(ctx->enableABC == false)
+       return false;
+
+    if(ctx->listStats[dpy].numAppLayers > MAX_LAYERS_FOR_ABC )
+       return false;
+
+    layerCount = ctx->listStats[dpy].numAppLayers;
+    //bottom most layer should
+    //equal to FB
+    hwc_layer_1_t *tmpLayer = &list->hwLayers[0];
+    private_handle_t *hnd = (private_handle_t *)tmpLayer->handle;
+    if(hnd && fbhnd && (hnd->size == fbhnd->size) &&
+    (hnd->width == fbhnd->width) && (hnd->height == fbhnd->height)){
+       if(tmpLayer->transform  ||
+        (list->flags & HWC_GEOMETRY_CHANGED) ||
+       (!(hnd->format == HAL_PIXEL_FORMAT_RGBA_8888 ||
+       hnd->format == HAL_PIXEL_FORMAT_RGBX_8888))  ||
+                   (needsScaling(tmpLayer) == true)) {
+          return false;
+       }else {
+          ctx->listStats[dpy].renderBufIndexforABC = 0;
+       }
+    }
+
+    if(ctx->listStats[dpy].renderBufIndexforABC == 0) {
+       if(layerCount == 1)
+          return true;
+
+       if(layerCount ==  MAX_LAYERS_FOR_ABC) {
+          int abcRenderBufIdx = ctx->listStats[dpy].renderBufIndexforABC;
+          //enable ABC only for non intersecting layers.
+          hwc_rect_t displayFrame =
+                  list->hwLayers[abcRenderBufIdx].displayFrame;
+          for (int i = abcRenderBufIdx + 1; i < layerCount; i++) {
+             hwc_rect_t tmpDisplayFrame = list->hwLayers[i].displayFrame;
+             hwc_rect_t result = getIntersection(displayFrame,tmpDisplayFrame);
+             if (isValidRect(result)) {
+                ctx->listStats[dpy].renderBufIndexforABC = -1;
+                return false;
+             }
+          }
+          // Pass the Acquire Fence FD to driver for base layer
+          private_handle_t *renderBuffer =
+          (private_handle_t *)list->hwLayers[abcRenderBufIdx].handle;
+          copybit_device_t *copybit = getCopyBitDevice();
+          if(list->hwLayers[abcRenderBufIdx].acquireFenceFd >=0){
+             copybit->set_sync(copybit,
+             list->hwLayers[abcRenderBufIdx].acquireFenceFd);
+          }
+          for(int i = abcRenderBufIdx + 1; i < layerCount; i++){
+             mSwapRect = 0;
+             int retVal = drawLayerUsingCopybit(ctx,
+               &(list->hwLayers[i]),renderBuffer, 0);
+             if(retVal < 0) {
+                ALOGE("%s : Copybit failed", __FUNCTION__);
+             }
+          }
+          // Get Release Fence FD of copybit for the App layer(s)
+          copybit->flush_get_fence(copybit, copybitFd);
+          close(list->hwLayers[last].acquireFenceFd);
+          list->hwLayers[last].acquireFenceFd = -1;
+          return true;
+       }
+    }
+    return false;
+}
+
+bool  CopyBit::draw(hwc_context_t *ctx, hwc_display_contents_1_t *list,
+                                                          int dpy, int32_t *fd) {
+    // draw layers marked for COPYBIT
+    int retVal = true;
+    int copybitLayerCount = 0;
+    uint32_t last = 0;
+    LayerProp *layerProp = ctx->layerProp[dpy];
+    private_handle_t *renderBuffer;
+
+    if(mCopyBitDraw == false){
+       mFbCache.reset(); // there is no layer marked for copybit
+       return false ;
+    }
+
+    if(drawUsingAppBufferComposition(ctx, list, dpy, fd)) {
+       mFbCache.reset();
+       return true;
+    }
+    //render buffer
+    if (ctx->mMDP.version == qdutils::MDP_V3_0_4 ||
+#ifdef SUPPORT_BLIT_TO_FB
+        ctx->mMDP.version != qdutils::MDP_V3_0_5
+#else
+        ctx->mMDP.version == qdutils::MDP_V3_0_5
+#endif
+       ) {
+        last = (uint32_t)list->numHwLayers - 1;
+        renderBuffer = (private_handle_t *)list->hwLayers[last].handle;
+    } else {
+        renderBuffer = getCurrentRenderBuffer();
+    }
+    if (!renderBuffer) {
+        ALOGE("%s: Render buffer layer handle is NULL", __FUNCTION__);
+        return false;
+    }
+
+    if ((ctx->mMDP.version >= qdutils::MDP_V4_0)
+#ifdef SUPPORT_BLIT_TO_FB
+        || (ctx->mMDP.version == qdutils::MDP_V3_0_5)
+#endif
+       ) {
+        //Wait for the previous frame to complete before rendering onto it
+        if(mRelFd[mCurRenderBufferIndex] >=0) {
+            sync_wait(mRelFd[mCurRenderBufferIndex], 1000);
+            close(mRelFd[mCurRenderBufferIndex]);
+            mRelFd[mCurRenderBufferIndex] = -1;
+        }
+    } else {
+        if(list->hwLayers[last].acquireFenceFd >=0) {
+            copybit_device_t *copybit = getCopyBitDevice();
+            copybit->set_sync(copybit, list->hwLayers[last].acquireFenceFd);
+        }
+    }
+
+    //if swap rect on and not getting valid dirtyRect
+    //means calling only commit without any draw. Hence avoid
+    //clear call as well.
+    if (not mSwapRect || isValidRect(mDirtyRect)) {
+       if (not CBUtils::uiClearRegion(list, ctx->mMDP.version, layerProp,
+                                      mDirtyRect, mEngine, renderBuffer)){
+           mSwapRect = 0;
+       }
+    }
+
+    // numAppLayers-1, as we iterate from 0th layer index with HWC_COPYBIT flag
+    for (int i = 0; i <= (ctx->listStats[dpy].numAppLayers-1); i++) {
+        if(!(layerProp[i].mFlags & HWC_COPYBIT)) {
+            ALOGD_IF(DEBUG_COPYBIT, "%s: Not Marked for copybit", __FUNCTION__);
+            continue;
+        }
+        if(ctx->copybitDrop[i]) {
+            continue;
+        }
+        int ret = -1;
+        if (list->hwLayers[i].acquireFenceFd != -1
+                && ctx->mMDP.version >= qdutils::MDP_V4_0) {
+            // Wait for acquire Fence on the App buffers.
+            ret = sync_wait(list->hwLayers[i].acquireFenceFd, 1000);
+            if(ret < 0) {
+                ALOGE("%s: sync_wait error!! error no = %d err str = %s",
+                                    __FUNCTION__, errno, strerror(errno));
+            }
+            close(list->hwLayers[i].acquireFenceFd);
+            list->hwLayers[i].acquireFenceFd = -1;
+        }
+        retVal = drawLayerUsingCopybit(ctx, &(list->hwLayers[i]),
+                                          renderBuffer, !i);
+        copybitLayerCount++;
+        if(retVal < 0) {
+            ALOGE("%s : drawLayerUsingCopybit failed", __FUNCTION__);
+        }
+    }
+
+    if (copybitLayerCount) {
+        copybit_device_t *copybit = getCopyBitDevice();
+        // Async mode
+        copybit->flush_get_fence(copybit, fd);
+        if((ctx->mMDP.version == qdutils::MDP_V3_0_4 ||
+#ifdef SUPPORT_BLIT_TO_FB
+           ctx->mMDP.version != qdutils::MDP_V3_0_5
+#else
+           ctx->mMDP.version == qdutils::MDP_V3_0_5
+#endif
+                ) && list->hwLayers[last].acquireFenceFd >= 0) {
+            close(list->hwLayers[last].acquireFenceFd);
+            list->hwLayers[last].acquireFenceFd = -1;
+        }
+    }
+    return true;
+}
+
+int CopyBit::drawOverlap(hwc_context_t *ctx, hwc_display_contents_1_t *list) {
+    int fd = -1;
+    PtorInfo* ptorInfo = &(ctx->mPtorInfo);
+
+    if (ctx->mMDP.version < qdutils::MDP_V4_0) {
+        ALOGE("%s: Invalid request", __FUNCTION__);
+        return fd;
+    }
+
+    private_handle_t *renderBuffer = getCurrentRenderBuffer();
+
+    if (!renderBuffer) {
+        ALOGE("%s: Render buffer layer handle is NULL", __FUNCTION__);
+        return fd;
+    }
+
+    //Clear the transparent or left out region on the render buffer
+    LayerProp *layerProp = ctx->layerProp[0];
+    hwc_rect_t clearRegion = {0, 0, 0, 0};
+    CBUtils::uiClearRegion(list, ctx->mMDP.version, layerProp, clearRegion,
+                                                    mEngine, renderBuffer);
+
+    int copybitLayerCount = 0;
+    for(int j = 0; j < ptorInfo->count; j++) {
+        int ovlapIndex = ptorInfo->layerIndex[j];
+        hwc_rect_t overlap = list->hwLayers[ovlapIndex].displayFrame;
+        if(j) {
+            /**
+             * It's possible that 2 PTOR layers might have overlapping.
+             * In such case, remove the intersection(again if peripheral)
+             * from the lower PTOR layer to avoid overlapping.
+             * If intersection is not on peripheral then compromise
+             * by reducing number of PTOR layers.
+             **/
+            int prevOvlapIndex = ptorInfo->layerIndex[0];
+            hwc_rect_t prevOvlap = list->hwLayers[prevOvlapIndex].displayFrame;
+            hwc_rect_t commonRect = getIntersection(prevOvlap, overlap);
+            if(isValidRect(commonRect)) {
+                overlap = deductRect(overlap, commonRect);
+            }
+        }
+
+        // Draw overlapped content of layers on render buffer
+        for (int i = 0; i <= ovlapIndex; i++) {
+            hwc_layer_1_t *layer = &list->hwLayers[i];
+            if(!isValidRect(getIntersection(layer->displayFrame,
+                                               overlap))) {
+                continue;
+            }
+            if ((list->hwLayers[i].acquireFenceFd != -1)) {
+                // Wait for acquire fence on the App buffers.
+                if(sync_wait(list->hwLayers[i].acquireFenceFd, 1000) < 0) {
+                    ALOGE("%s: sync_wait error!! error no = %d err str = %s",
+                          __FUNCTION__, errno, strerror(errno));
+                }
+                close(list->hwLayers[i].acquireFenceFd);
+                list->hwLayers[i].acquireFenceFd = -1;
+            }
+            /*
+             * Find the intersection of layer display frame with PTOR layer
+             * with respect to screen co-ordinates
+             *
+             * Calculated the destination rect by transforming the overlapping
+             * region of layer display frame with respect to PTOR display frame
+             *
+             * Transform the destination rect on to render buffer
+             * */
+            hwc_rect_t destRect = getIntersection(overlap, layer->displayFrame);
+            destRect.left = destRect.left - overlap.left +
+                                            ptorInfo->displayFrame[j].left;
+            destRect.right = destRect.right- overlap.left +
+                                            ptorInfo->displayFrame[j].left;
+            destRect.top = destRect.top - overlap.top +
+                                            ptorInfo->displayFrame[j].top;
+            destRect.bottom = destRect.bottom - overlap.top +
+                                            ptorInfo->displayFrame[j].top;
+
+            int retVal = drawRectUsingCopybit(ctx, layer, renderBuffer,
+                                                          overlap, destRect);
+            copybitLayerCount++;
+            if(retVal < 0) {
+                ALOGE("%s: drawRectUsingCopybit failed", __FUNCTION__);
+                copybitLayerCount = 0;
+            }
+        }
+    }
+
+    if (copybitLayerCount) {
+        copybit_device_t *copybit = getCopyBitDevice();
+        copybit->flush_get_fence(copybit, &fd);
+    }
+
+    ALOGD_IF(DEBUG_COPYBIT, "%s: done! copybitLayerCount = %d", __FUNCTION__,
+             copybitLayerCount);
+    return fd;
+}
+
+int CopyBit::drawRectUsingCopybit(hwc_context_t *dev, hwc_layer_1_t *layer,
+                        private_handle_t *renderBuffer, hwc_rect_t overlap,
+                        hwc_rect_t destRect)
+{
+    hwc_context_t* ctx = (hwc_context_t*)(dev);
+    if (!ctx) {
+        ALOGE("%s: null context ", __FUNCTION__);
+        return -1;
+    }
+
+    private_handle_t *hnd = (private_handle_t *)layer->handle;
+    if (!hnd) {
+        ALOGE("%s: invalid handle", __FUNCTION__);
+        return -1;
+    }
+
+    private_handle_t *dstHandle = (private_handle_t *)renderBuffer;
+    if (!dstHandle) {
+        ALOGE("%s: RenderBuffer handle is NULL", __FUNCTION__);
+        return -1;
+    }
+
+    // Set the Copybit Source
+    copybit_image_t src;
+    src.handle = (native_handle_t *)layer->handle;
+    src.w = hnd->width;
+    src.h = hnd->height;
+    src.base = (void *)hnd->base;
+    src.format = hnd->format;
+    src.horiz_padding = 0;
+    src.vert_padding = 0;
+
+
+    hwc_rect_t dispFrame = layer->displayFrame;
+    hwc_rect_t iRect = getIntersection(dispFrame, overlap);
+    hwc_rect_t crop = integerizeSourceCrop(layer->sourceCropf);
+    qhwc::calculate_crop_rects(crop, dispFrame, iRect,
+                               layer->transform);
+
+    // Copybit source rect
+    copybit_rect_t srcRect = {crop.left, crop.top, crop.right,
+        crop.bottom};
+
+    // Copybit destination rect
+    copybit_rect_t dstRect = {destRect.left, destRect.top, destRect.right,
+        destRect.bottom};
+
+    // Copybit dst
+    copybit_image_t dst;
+    dst.handle = (native_handle_t *)dstHandle;
+    dst.w = ALIGN(dstHandle->width, 32);
+    dst.h = dstHandle->height;
+    dst.base = (void *)dstHandle->base;
+    dst.format = dstHandle->format;
+
+    copybit_device_t *copybit = mEngine;
+
+    // Copybit region is the destRect
+    hwc_rect_t regRect = {dstRect.l,dstRect.t, dstRect.r, dstRect.b};
+    hwc_region_t region;
+    region.numRects = 1;
+    region.rects  = &regRect;
+    region_iterator copybitRegion(region);
+    int acquireFd = layer->acquireFenceFd;
+
+    copybit->set_parameter(copybit, COPYBIT_FRAMEBUFFER_WIDTH,
+                           renderBuffer->width);
+    copybit->set_parameter(copybit, COPYBIT_FRAMEBUFFER_HEIGHT,
+                           renderBuffer->height);
+    copybit->set_parameter(copybit, COPYBIT_TRANSFORM, layer->transform);
+    copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, layer->planeAlpha);
+    copybit->set_parameter(copybit, COPYBIT_BLEND_MODE, layer->blending);
+    copybit->set_parameter(copybit, COPYBIT_DITHER,
+        (dst.format == HAL_PIXEL_FORMAT_RGB_565) ? COPYBIT_ENABLE :
+        COPYBIT_DISABLE);
+    copybit->set_sync(copybit, acquireFd);
+    int err = copybit->stretch(copybit, &dst, &src, &dstRect, &srcRect,
+                               &copybitRegion);
+
+    if (err < 0)
+        ALOGE("%s: copybit stretch failed",__FUNCTION__);
+
+    return err;
+}
+
+int  CopyBit::drawLayerUsingCopybit(hwc_context_t *dev, hwc_layer_1_t *layer,
+                          private_handle_t *renderBuffer, bool isFG)
+{
+    hwc_context_t* ctx = (hwc_context_t*)(dev);
+    int err = 0, acquireFd;
+    if(!ctx) {
+         ALOGE("%s: null context ", __FUNCTION__);
+         return -1;
+    }
+
+    private_handle_t *hnd = (private_handle_t *)layer->handle;
+    if(!hnd) {
+        if (layer->flags & HWC_COLOR_FILL) { // Color layer
+            return fillColorUsingCopybit(layer, renderBuffer);
+        }
+        ALOGE("%s: invalid handle", __FUNCTION__);
+        return -1;
+    }
+
+    private_handle_t *fbHandle = (private_handle_t *)renderBuffer;
+    if(!fbHandle) {
+        ALOGE("%s: Framebuffer handle is NULL", __FUNCTION__);
+        return -1;
+    }
+    uint32_t dynamic_fps = 0;
+#ifdef DYNAMIC_FPS
+    MetaData_t *mdata = hnd ? (MetaData_t *)hnd->base_metadata : NULL;
+    if (mdata && (mdata->operation & UPDATE_REFRESH_RATE)) {
+       dynamic_fps  = roundOff(mdata->refreshrate);
+    }
+#endif
+    // Set the copybit source:
+    copybit_image_t src;
+    src.w = getWidth(hnd);
+    src.h = getHeight(hnd);
+    src.format = hnd->format;
+
+    // Handle R/B swap
+    if ((layer->flags & HWC_FORMAT_RB_SWAP)) {
+        if (src.format == HAL_PIXEL_FORMAT_RGBA_8888) {
+            src.format = HAL_PIXEL_FORMAT_BGRA_8888;
+        } else if (src.format == HAL_PIXEL_FORMAT_RGBX_8888) {
+            src.format = HAL_PIXEL_FORMAT_BGRX_8888;
+        }
+    }
+
+    src.base = (void *)hnd->base;
+    src.handle = (native_handle_t *)layer->handle;
+    src.horiz_padding = src.w - getWidth(hnd);
+    // Initialize vertical padding to zero for now,
+    // this needs to change to accomodate vertical stride
+    // if needed in the future
+    src.vert_padding = 0;
+
+    int layerTransform = layer->transform ;
+    // When flip and rotation(90) are present alter the flip,
+    // as GPU is doing the flip and rotation in opposite order
+    // to that of MDP3.0
+    // For 270 degrees, we get 90 + (H+V) which is same as doing
+    // flip first and then rotation (H+V) + 90
+    if (qdutils::MDPVersion::getInstance().getMDPVersion() < 400) {
+                if (((layer->transform& HAL_TRANSFORM_FLIP_H) ||
+                (layer->transform & HAL_TRANSFORM_FLIP_V)) &&
+                (layer->transform &  HAL_TRANSFORM_ROT_90) &&
+                !(layer->transform ==  HAL_TRANSFORM_ROT_270)){
+                      if(layer->transform & HAL_TRANSFORM_FLIP_H){
+                                 layerTransform ^= HAL_TRANSFORM_FLIP_H;
+                                 layerTransform |= HAL_TRANSFORM_FLIP_V;
+                      }
+                      if(layer->transform & HAL_TRANSFORM_FLIP_V){
+                                 layerTransform ^= HAL_TRANSFORM_FLIP_V;
+                                 layerTransform |= HAL_TRANSFORM_FLIP_H;
+                      }
+               }
+    }
+    // Copybit source rect
+    hwc_rect_t sourceCrop = integerizeSourceCrop(layer->sourceCropf);
+    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};
+#ifdef QTI_BSP
+    //change src and dst with dirtyRect
+    if(mSwapRect) {
+      hwc_rect_t result = getIntersection(displayFrame, mDirtyRect);
+      if(!isValidRect(result))
+             return true;
+      dstRect.l = result.left;
+      dstRect.t = result.top;
+      dstRect.r = result.right;
+      dstRect.b = result.bottom;
+
+      srcRect.l += (result.left - displayFrame.left);
+      srcRect.t += (result.top - displayFrame.top);
+      srcRect.r -= (displayFrame.right - result.right);
+      srcRect.b -= (displayFrame.bottom - result.bottom);
+    }
+#endif
+    // Copybit dst
+    copybit_image_t dst;
+    dst.w = ALIGN(fbHandle->width,32);
+    dst.h = fbHandle->height;
+    dst.format = fbHandle->format;
+    dst.base = (void *)fbHandle->base;
+    dst.handle = (native_handle_t *)fbHandle;
+
+    copybit_device_t *copybit = mEngine;
+
+    int32_t screen_w        = displayFrame.right - displayFrame.left;
+    int32_t screen_h        = displayFrame.bottom - displayFrame.top;
+    int32_t src_crop_width  = sourceCrop.right - sourceCrop.left;
+    int32_t src_crop_height = sourceCrop.bottom -sourceCrop.top;
+
+    // Copybit dst
+    float copybitsMaxScale =
+                      (float)copybit->get(copybit,COPYBIT_MAGNIFICATION_LIMIT);
+    float copybitsMinScale =
+                       (float)copybit->get(copybit,COPYBIT_MINIFICATION_LIMIT);
+
+    if (layer->transform & HWC_TRANSFORM_ROT_90) {
+        //swap screen width and height
+        int tmp = screen_w;
+        screen_w  = screen_h;
+        screen_h = tmp;
+    }
+    private_handle_t *tmpHnd = NULL;
+
+    if(screen_w <=0 || screen_h<=0 ||src_crop_width<=0 || src_crop_height<=0 ) {
+        ALOGE("%s: wrong params for display screen_w=%d src_crop_width=%d \
+        screen_h=%d src_crop_height=%d", __FUNCTION__, screen_w,
+                                src_crop_width,screen_h,src_crop_height);
+        return -1;
+    }
+
+    float dsdx = (float)screen_w/(float)src_crop_width;
+    float dtdy = (float)screen_h/(float)src_crop_height;
+
+    float scaleLimitMax = copybitsMaxScale * copybitsMaxScale;
+    float scaleLimitMin = copybitsMinScale * copybitsMinScale;
+    if(dsdx > scaleLimitMax ||
+        dtdy > scaleLimitMax ||
+        dsdx < 1/scaleLimitMin ||
+        dtdy < 1/scaleLimitMin) {
+        ALOGW("%s: greater than max supported size dsdx=%f dtdy=%f \
+              scaleLimitMax=%f scaleLimitMin=%f", __FUNCTION__,dsdx,dtdy,
+                                          scaleLimitMax,1/scaleLimitMin);
+        return -1;
+    }
+    acquireFd = layer->acquireFenceFd;
+    if(dsdx > copybitsMaxScale ||
+        dtdy > copybitsMaxScale ||
+        dsdx < 1/copybitsMinScale ||
+        dtdy < 1/copybitsMinScale){
+        // The requested scale is out of the range the hardware
+        // can support.
+       ALOGD("%s:%d::Need to scale twice dsdx=%f, dtdy=%f,copybitsMaxScale=%f,\
+                                 copybitsMinScale=%f,screen_w=%d,screen_h=%d \
+                  src_crop_width=%d src_crop_height=%d",__FUNCTION__,__LINE__,
+              dsdx,dtdy,copybitsMaxScale,1/copybitsMinScale,screen_w,screen_h,
+                                              src_crop_width,src_crop_height);
+
+
+       int tmp_w =  src_crop_width;
+       int tmp_h =  src_crop_height;
+
+       if (dsdx > copybitsMaxScale)
+         tmp_w = (int)((float)src_crop_width*copybitsMaxScale);
+       if (dtdy > copybitsMaxScale)
+         tmp_h = (int)((float)src_crop_height*copybitsMaxScale);
+       // ceil the tmp_w and tmp_h value to maintain proper ratio
+       // b/w src and dst (should not cross the desired scale limit
+       // due to float -> int )
+       if (dsdx < 1/copybitsMinScale)
+         tmp_w = (int)ceil((float)src_crop_width/copybitsMinScale);
+       if (dtdy < 1/copybitsMinScale)
+         tmp_h = (int)ceil((float)src_crop_height/copybitsMinScale);
+
+       ALOGD("%s:%d::tmp_w = %d,tmp_h = %d",__FUNCTION__,__LINE__,tmp_w,tmp_h);
+
+       int usage = GRALLOC_USAGE_PRIVATE_IOMMU_HEAP;
+       int format = fbHandle->format;
+
+       // We do not want copybit to generate alpha values from nothing
+       if (format == HAL_PIXEL_FORMAT_RGBA_8888 &&
+               src.format != HAL_PIXEL_FORMAT_RGBA_8888) {
+           format = HAL_PIXEL_FORMAT_RGBX_8888;
+       }
+       if (0 == alloc_buffer(&tmpHnd, tmp_w, tmp_h, format, usage) && tmpHnd) {
+            copybit_image_t tmp_dst;
+            copybit_rect_t tmp_rect;
+            tmp_dst.w = tmp_w;
+            tmp_dst.h = tmp_h;
+            tmp_dst.format = tmpHnd->format;
+            tmp_dst.handle = tmpHnd;
+            tmp_dst.horiz_padding = src.horiz_padding;
+            tmp_dst.vert_padding = src.vert_padding;
+            tmp_rect.l = 0;
+            tmp_rect.t = 0;
+            tmp_rect.r = tmp_dst.w;
+            tmp_rect.b = tmp_dst.h;
+            //create one clip region
+            hwc_rect tmp_hwc_rect = {0,0,tmp_rect.r,tmp_rect.b};
+            hwc_region_t tmp_hwc_reg = {1,(hwc_rect_t const*)&tmp_hwc_rect};
+            region_iterator tmp_it(tmp_hwc_reg);
+            copybit->set_parameter(copybit,COPYBIT_TRANSFORM,0);
+            //TODO: once, we are able to read layer alpha, update this
+            copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, 255);
+            copybit->set_sync(copybit, acquireFd);
+            err = copybit->stretch(copybit,&tmp_dst, &src, &tmp_rect,
+                                                           &srcRect, &tmp_it);
+            if(err < 0){
+                ALOGE("%s:%d::tmp copybit stretch failed",__FUNCTION__,
+                                                             __LINE__);
+                if(tmpHnd)
+                    free_buffer(tmpHnd);
+                return err;
+            }
+            // use release fence as aquire fd for next stretch
+            if (ctx->mMDP.version < qdutils::MDP_V4_0) {
+                copybit->flush_get_fence(copybit, &acquireFd);
+                close(acquireFd);
+                acquireFd = -1;
+            }
+            // copy new src and src rect crop
+            src = tmp_dst;
+            srcRect = tmp_rect;
+      }
+    }
+    // Copybit region
+    hwc_region_t region = layer->visibleRegionScreen;
+    //Do not use visible regions in case of scaling
+    if (region.numRects > 1) {
+        if (needsScaling(layer)) {
+            region.numRects = 1;
+            region.rects = &layer->displayFrame;
+        }
+    }
+
+    region_iterator copybitRegion(region);
+
+    copybit->set_parameter(copybit, COPYBIT_FRAMEBUFFER_WIDTH,
+                                          renderBuffer->width);
+    copybit->set_parameter(copybit, COPYBIT_FRAMEBUFFER_HEIGHT,
+                                          renderBuffer->height);
+    copybit->set_parameter(copybit, COPYBIT_TRANSFORM,
+                                              layerTransform);
+    //TODO: once, we are able to read layer alpha, update this
+    copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, 255);
+    copybit->set_parameter(copybit, COPYBIT_DYNAMIC_FPS, dynamic_fps);
+    copybit->set_parameter(copybit, COPYBIT_BLEND_MODE,
+                                              layer->blending);
+    copybit->set_parameter(copybit, COPYBIT_DITHER,
+                             (dst.format == HAL_PIXEL_FORMAT_RGB_565)?
+                                             COPYBIT_ENABLE : COPYBIT_DISABLE);
+    copybit->set_parameter(copybit, COPYBIT_FG_LAYER,
+                           (layer->blending == HWC_BLENDING_NONE || isFG ) ?
+                                             COPYBIT_ENABLE : COPYBIT_DISABLE);
+
+    copybit->set_parameter(copybit, COPYBIT_BLIT_TO_FRAMEBUFFER,
+                                                COPYBIT_ENABLE);
+    copybit->set_sync(copybit, acquireFd);
+    err = copybit->stretch(copybit, &dst, &src, &dstRect, &srcRect,
+                                                   &copybitRegion);
+    copybit->set_parameter(copybit, COPYBIT_BLIT_TO_FRAMEBUFFER,
+                                               COPYBIT_DISABLE);
+
+    if(tmpHnd) {
+        if (ctx->mMDP.version < qdutils::MDP_V4_0){
+            int ret = -1, releaseFd;
+            // we need to wait for the buffer before freeing
+            copybit->flush_get_fence(copybit, &releaseFd);
+            ret = sync_wait(releaseFd, 1000);
+            if(ret < 0) {
+                ALOGE("%s: sync_wait error!! error no = %d err str = %s",
+                    __FUNCTION__, errno, strerror(errno));
+            }
+            close(releaseFd);
+        }
+        free_buffer(tmpHnd);
+    }
+
+    if(err < 0)
+        ALOGE("%s: copybit stretch failed",__FUNCTION__);
+    return err;
+}
+
+int CopyBit::fillColorUsingCopybit(hwc_layer_1_t *layer,
+                          private_handle_t *renderBuffer)
+{
+    if (!renderBuffer) {
+        ALOGE("%s: Render Buffer is NULL", __FUNCTION__);
+        return -1;
+    }
+
+    // Copybit dst
+    copybit_image_t dst;
+    dst.w = ALIGN(renderBuffer->width, 32);
+    dst.h = renderBuffer->height;
+    dst.format = renderBuffer->format;
+    dst.base = (void *)renderBuffer->base;
+    dst.handle = (native_handle_t *)renderBuffer;
+
+    // Copybit dst rect
+    hwc_rect_t displayFrame = layer->displayFrame;
+    copybit_rect_t dstRect = {displayFrame.left, displayFrame.top,
+                              displayFrame.right, displayFrame.bottom};
+
+    uint32_t color = layer->transform;
+    copybit_device_t *copybit = mEngine;
+    copybit->set_parameter(copybit, COPYBIT_FRAMEBUFFER_WIDTH,
+                           renderBuffer->width);
+    copybit->set_parameter(copybit, COPYBIT_FRAMEBUFFER_HEIGHT,
+                           renderBuffer->height);
+    copybit->set_parameter(copybit, COPYBIT_DITHER,
+                           (dst.format == HAL_PIXEL_FORMAT_RGB_565) ?
+                           COPYBIT_ENABLE : COPYBIT_DISABLE);
+    copybit->set_parameter(copybit, COPYBIT_TRANSFORM, 0);
+    copybit->set_parameter(copybit, COPYBIT_BLEND_MODE, layer->blending);
+    copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, layer->planeAlpha);
+    copybit->set_parameter(copybit, COPYBIT_BLIT_TO_FRAMEBUFFER,COPYBIT_ENABLE);
+    int res = copybit->fill_color(copybit, &dst, &dstRect, color);
+    copybit->set_parameter(copybit,COPYBIT_BLIT_TO_FRAMEBUFFER,COPYBIT_DISABLE);
+    return res;
+}
+
+void CopyBit::getLayerResolution(const hwc_layer_1_t* layer,
+                                 unsigned int& width, unsigned int& height)
+{
+    hwc_rect_t result  = layer->displayFrame;
+    if (mSwapRect)
+       result = getIntersection(mDirtyRect, result);
+
+    width = result.right - result.left;
+    height = result.bottom - result.top;
+}
+
+bool CopyBit::validateParams(hwc_context_t *ctx,
+                                        const hwc_display_contents_1_t *list) {
+    //Validate parameters
+    if (!ctx) {
+        ALOGE("%s:Invalid HWC context", __FUNCTION__);
+        return false;
+    } else if (!list) {
+        ALOGE("%s:Invalid HWC layer list", __FUNCTION__);
+        return false;
+    }
+    return true;
+}
+
+
+int CopyBit::allocRenderBuffers(int w, int h, int f)
+{
+    int ret = 0;
+    for (int i = 0; i < NUM_RENDER_BUFFERS; i++) {
+        if (mRenderBuffer[i] == NULL) {
+            ret = alloc_buffer(&mRenderBuffer[i],
+                               w, h, f,
+                               GRALLOC_USAGE_PRIVATE_IOMMU_HEAP);
+        }
+        if(ret < 0) {
+            freeRenderBuffers();
+            break;
+        }
+    }
+    return ret;
+}
+
+void CopyBit::freeRenderBuffers()
+{
+    for (int i = 0; i < NUM_RENDER_BUFFERS; i++) {
+        if(mRenderBuffer[i]) {
+            //Since we are freeing buffer close the fence if it has a valid one.
+            if(mRelFd[i] >= 0) {
+                close(mRelFd[i]);
+                mRelFd[i] = -1;
+            }
+            free_buffer(mRenderBuffer[i]);
+            mRenderBuffer[i] = NULL;
+        }
+    }
+}
+
+private_handle_t * CopyBit::getCurrentRenderBuffer() {
+    return mRenderBuffer[mCurRenderBufferIndex];
+}
+
+void CopyBit::setReleaseFd(int fd) {
+    if(mRelFd[mCurRenderBufferIndex] >=0)
+        close(mRelFd[mCurRenderBufferIndex]);
+    mRelFd[mCurRenderBufferIndex] = dup(fd);
+}
+
+void CopyBit::setReleaseFdSync(int fd) {
+    if (mRelFd[mCurRenderBufferIndex] >=0) {
+        int ret = -1;
+        ret = sync_wait(mRelFd[mCurRenderBufferIndex], 1000);
+        if (ret < 0)
+            ALOGE("%s: sync_wait error! errno = %d, err str = %s",
+                  __FUNCTION__, errno, strerror(errno));
+        close(mRelFd[mCurRenderBufferIndex]);
+    }
+    mRelFd[mCurRenderBufferIndex] = dup(fd);
+}
+
+struct copybit_device_t* CopyBit::getCopyBitDevice() {
+    return mEngine;
+}
+
+CopyBit::CopyBit(hwc_context_t *ctx, const int& dpy) :  mEngine(0),
+    mIsModeOn(false), mCopyBitDraw(false), mCurRenderBufferIndex(0) {
+
+    getBufferSizeAndDimensions(ctx->dpyAttr[dpy].xres,
+            ctx->dpyAttr[dpy].yres,
+            HAL_PIXEL_FORMAT_RGBA_8888,
+            mAlignedWidth,
+            mAlignedHeight);
+
+    hw_module_t const *module;
+    for (int i = 0; i < NUM_RENDER_BUFFERS; i++) {
+        mRenderBuffer[i] = NULL;
+        mRelFd[i] = -1;
+    }
+
+    char value[PROPERTY_VALUE_MAX];
+    property_get("debug.hwc.dynThreshold", value, "2");
+    mDynThreshold = atof(value);
+
+    property_get("debug.sf.swaprect", value, "0");
+    mSwapRectEnable = atoi(value) ? true:false ;
+    mSwapRect = 0;
+    if (hw_get_module(COPYBIT_HARDWARE_MODULE_ID, &module) == 0) {
+        if(copybit_open(module, &mEngine) < 0) {
+            ALOGE("FATAL ERROR: copybit open failed.");
+        }
+    } else {
+        ALOGE("FATAL ERROR: copybit hw module not found");
+    }
+}
+
+CopyBit::~CopyBit()
+{
+    freeRenderBuffers();
+    if(mEngine)
+    {
+        copybit_close(mEngine);
+        mEngine = NULL;
+    }
+}
+CopyBit::LayerCache::LayerCache() {
+    reset();
+}
+void CopyBit::LayerCache::reset() {
+    memset(&hnd, 0, sizeof(hnd));
+    layerCount = 0;
+}
+void CopyBit::LayerCache::updateCounts(hwc_context_t *ctx,
+              hwc_display_contents_1_t *list, int dpy)
+{
+   layerCount = ctx->listStats[dpy].numAppLayers;
+   for (int i=0; i<ctx->listStats[dpy].numAppLayers; i++){
+      hnd[i] = list->hwLayers[i].handle;
+      displayFrame[i] = list->hwLayers[i].displayFrame;
+      drop[i] = ctx->copybitDrop[i];
+   }
+}
+
+CopyBit::FbCache::FbCache() {
+     reset();
+}
+void CopyBit::FbCache::reset() {
+     memset(&FbdirtyRect, 0, sizeof(FbdirtyRect));
+     memset(&FbdisplayRect, 0, sizeof(FbdisplayRect));
+     FbIndex =0;
+}
+
+void CopyBit::FbCache::insertAndUpdateFbCache(hwc_rect_t dirtyRect,
+                                             hwc_rect_t displayRect) {
+   FbIndex =  FbIndex % NUM_RENDER_BUFFERS;
+   FbdirtyRect[FbIndex] = dirtyRect;
+   FbdisplayRect[FbIndex] = displayRect;
+   FbIndex++;
+}
+
+int CopyBit::FbCache::getUnchangedFbDRCount(hwc_rect_t dirtyRect,
+                                          hwc_rect_t displayRect){
+    int sameDirtyCount = 0;
+    for (int i = 0 ; i < NUM_RENDER_BUFFERS ; i++ ){
+      if( FbdirtyRect[i] == dirtyRect &&
+          FbdisplayRect[i] == displayRect)
+           sameDirtyCount++;
+   }
+   return sameDirtyCount;
+}
+
+}; //namespace qhwc
diff --git a/msm8909/libhwcomposer/hwc_copybit.h b/msm8909/libhwcomposer/hwc_copybit.h
new file mode 100644
index 0000000..c527a4e
--- /dev/null
+++ b/msm8909/libhwcomposer/hwc_copybit.h
@@ -0,0 +1,149 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ * Copyright (C) 2012-2014, The Linux Foundation. All rights reserved.
+ *
+ * Not a Contribution, Apache license notifications and license are retained
+ * for attribution purposes only.
+ *
+ * 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 HWC_COPYBIT_H
+#define HWC_COPYBIT_H
+#include "hwc_utils.h"
+
+#define NUM_RENDER_BUFFERS 3
+//These scaling factors are specific for MDP3. Normally scaling factor
+//is only 4, but copybit will create temp buffer to let it run through
+//twice
+#define MAX_SCALE_FACTOR 16
+#define MIN_SCALE_FACTOR 0.0625
+#define MAX_LAYERS_FOR_ABC 2
+#define INVALID_DIMENSION -1
+#define NO_UPDATING_LAYER -2
+namespace qhwc {
+
+class CopyBit {
+public:
+    CopyBit(hwc_context_t *ctx, const int& dpy);
+    ~CopyBit();
+    // API to get copybit engine(non static)
+    struct copybit_device_t *getCopyBitDevice();
+    //Sets up members and prepares copybit if conditions are met
+    bool prepare(hwc_context_t *ctx, hwc_display_contents_1_t *list,
+                                                                   int dpy);
+    //Draws layer if the layer is set for copybit in prepare
+    bool draw(hwc_context_t *ctx, hwc_display_contents_1_t *list,
+                                                        int dpy, int* fd);
+    // resets the values
+    void reset();
+
+    private_handle_t * getCurrentRenderBuffer();
+
+    void setReleaseFd(int fd);
+
+    void setReleaseFdSync(int fd);
+
+    bool prepareOverlap(hwc_context_t *ctx, hwc_display_contents_1_t *list);
+
+    int drawOverlap(hwc_context_t *ctx, hwc_display_contents_1_t *list);
+
+private:
+    /* cached data */
+    struct LayerCache {
+      int layerCount;
+      buffer_handle_t hnd[MAX_NUM_APP_LAYERS];
+      hwc_rect_t displayFrame[MAX_NUM_APP_LAYERS];
+      bool drop[MAX_NUM_APP_LAYERS];
+      /* c'tor */
+      LayerCache();
+      /* clear caching info*/
+      void reset();
+      void updateCounts(hwc_context_t *ctx, hwc_display_contents_1_t *list,
+              int dpy);
+    };
+    /* framebuffer cache*/
+    struct FbCache {
+      hwc_rect_t  FbdirtyRect[NUM_RENDER_BUFFERS];
+      hwc_rect_t  FbdisplayRect[NUM_RENDER_BUFFERS];
+      int FbIndex;
+      FbCache();
+      void reset();
+      void insertAndUpdateFbCache(hwc_rect_t dirtyRect,
+                               hwc_rect_t displayRect);
+      int getUnchangedFbDRCount(hwc_rect_t dirtyRect,
+                             hwc_rect_t displayRect);
+    };
+
+    // holds the copybit device
+    struct copybit_device_t *mEngine;
+    bool drawUsingAppBufferComposition(hwc_context_t *ctx,
+                                hwc_display_contents_1_t *list,
+                                int dpy, int *fd);
+    // Helper functions for copybit composition
+    int  drawLayerUsingCopybit(hwc_context_t *dev, hwc_layer_1_t *layer,
+                          private_handle_t *renderBuffer, bool isFG);
+    // Helper function to draw copybit layer for PTOR comp
+    int drawRectUsingCopybit(hwc_context_t *dev, hwc_layer_1_t *layer,
+                          private_handle_t *renderBuffer, hwc_rect_t overlap,
+                          hwc_rect_t destRect);
+    int fillColorUsingCopybit(hwc_layer_1_t *layer,
+                          private_handle_t *renderBuffer);
+    bool canUseCopybitForYUV (hwc_context_t *ctx);
+    bool canUseCopybitForRGB (hwc_context_t *ctx,
+                                     hwc_display_contents_1_t *list, int dpy);
+    bool validateParams (hwc_context_t *ctx,
+                                const hwc_display_contents_1_t *list);
+    //Flags if this feature is on.
+    bool mIsModeOn;
+    // flag that indicates whether CopyBit composition is enabled for this cycle
+    bool mCopyBitDraw;
+
+    unsigned int getRGBRenderingArea (const hwc_context_t *ctx,
+                                         const hwc_display_contents_1_t *list);
+
+    void getLayerResolution(const hwc_layer_1_t* layer,
+                                   unsigned int &width, unsigned int& height);
+
+    int allocRenderBuffers(int w, int h, int f);
+
+    void freeRenderBuffers();
+
+    int clear (private_handle_t* hnd, hwc_rect_t& rect);
+
+    private_handle_t* mRenderBuffer[NUM_RENDER_BUFFERS];
+
+    // Index of the current intermediate render buffer
+    int mCurRenderBufferIndex;
+
+    // Release FDs of the intermediate render buffer
+    int mRelFd[NUM_RENDER_BUFFERS];
+
+    //Dynamic composition threshold for deciding copybit usage.
+    double mDynThreshold;
+    bool mSwapRectEnable;
+    int mAlignedWidth;
+    int mAlignedHeight;
+    int mSwapRect;
+    LayerCache mLayerCache;
+    FbCache mFbCache;
+    hwc_rect_t mDirtyRect;
+    bool prepareSwapRect(hwc_context_t *ctx, hwc_display_contents_1_t *list,
+                  int dpy);
+    bool isLayerChanging(hwc_context_t *ctx,
+                            hwc_display_contents_1_t *list, int k);
+    bool isSmartBlitPossible(const hwc_display_contents_1_t *list);
+};
+
+}; //namespace qhwc
+
+#endif //HWC_COPYBIT_H
diff --git a/msm8909/libhwcomposer/hwc_dump_layers.cpp b/msm8909/libhwcomposer/hwc_dump_layers.cpp
new file mode 100644
index 0000000..8ebd23c
--- /dev/null
+++ b/msm8909/libhwcomposer/hwc_dump_layers.cpp
@@ -0,0 +1,452 @@
+/*
+ * Copyright (c) 2012-2014, Linux Foundation. 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 Linux Foundation 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 LOG_TAG
+#define LOG_TAG "qsfdump"
+#endif
+#define LOG_NDEBUG 0
+#include <hwc_utils.h>
+#include <hwc_dump_layers.h>
+#include <cutils/log.h>
+#include <sys/stat.h>
+#include <comptype.h>
+#ifdef QTI_BSP
+// Ignore W(float)conversion errors for external headers
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wconversion"
+#pragma GCC diagnostic ignored "-Wfloat-conversion"
+#include <SkBitmap.h>
+#include <SkImageEncoder.h>
+#pragma GCC diagnostic pop
+#endif
+#ifdef STDC_FORMAT_MACROS
+#include <inttypes.h>
+#endif
+
+namespace qhwc {
+
+// MAX_ALLOWED_FRAMEDUMPS must be capped to (LONG_MAX - 1)
+// 60fps => 216000 frames per hour
+// Below setting of 216000 * 24 * 7 => 1 week or 168 hours of capture.
+  enum {
+    MAX_ALLOWED_FRAMEDUMPS = (216000 * 24 * 7)
+  };
+
+bool HwcDebug::sDumpEnable = false;
+
+HwcDebug::HwcDebug(uint32_t dpy):
+  mDumpCntLimRaw(0),
+  mDumpCntrRaw(1),
+  mDumpCntLimPng(0),
+  mDumpCntrPng(1),
+  mDpy(dpy) {
+    char dumpPropStr[PROPERTY_VALUE_MAX];
+    if(mDpy) {
+        strlcpy(mDisplayName, "external", sizeof(mDisplayName));
+    } else {
+        strlcpy(mDisplayName, "primary", sizeof(mDisplayName));
+    }
+    snprintf(mDumpPropKeyDisplayType, sizeof(mDumpPropKeyDisplayType),
+             "debug.sf.dump.%s", (char *)mDisplayName);
+
+    if ((property_get("debug.sf.dump.enable", dumpPropStr, NULL) > 0)) {
+        if(!strncmp(dumpPropStr, "true", strlen("true"))) {
+            sDumpEnable = true;
+        }
+    }
+}
+
+void HwcDebug::dumpLayers(hwc_display_contents_1_t* list)
+{
+    // Check need for dumping layers for debugging.
+    if (UNLIKELY(sDumpEnable) && UNLIKELY(needToDumpLayers()) && LIKELY(list)) {
+        logHwcProps(list->flags);
+        for (size_t i = 0; i < list->numHwLayers; i++) {
+            logLayer(i, list->hwLayers);
+            dumpLayer(i, list->hwLayers);
+        }
+    }
+}
+
+bool HwcDebug::needToDumpLayers()
+{
+    bool bDumpLayer = false;
+    char dumpPropStr[PROPERTY_VALUE_MAX];
+    // Enable primary dump and disable external dump by default.
+    bool bDumpEnable = !mDpy;
+    time_t timeNow;
+    tm dumpTime;
+
+    // Override the bDumpEnable based on the property value, if the property
+    // is present in the build.prop file.
+    if ((property_get(mDumpPropKeyDisplayType, dumpPropStr, NULL) > 0)) {
+        if(!strncmp(dumpPropStr, "true", strlen("true")))
+            bDumpEnable = true;
+        else
+            bDumpEnable = false;
+    }
+
+    if (false == bDumpEnable)
+        return false;
+
+    time(&timeNow);
+    localtime_r(&timeNow, &dumpTime);
+
+    if ((property_get("debug.sf.dump.png", dumpPropStr, NULL) > 0) &&
+            (strncmp(dumpPropStr, mDumpPropStrPng, PROPERTY_VALUE_MAX - 1))) {
+        // Strings exist & not equal implies it has changed, so trigger a dump
+        strlcpy(mDumpPropStrPng, dumpPropStr, sizeof(mDumpPropStrPng));
+        mDumpCntLimPng = atoi(dumpPropStr);
+        if (mDumpCntLimPng > MAX_ALLOWED_FRAMEDUMPS) {
+            ALOGW("Warning: Using debug.sf.dump.png %d (= max)",
+                MAX_ALLOWED_FRAMEDUMPS);
+            mDumpCntLimPng = MAX_ALLOWED_FRAMEDUMPS;
+        }
+        mDumpCntLimPng = (mDumpCntLimPng < 0) ? 0: mDumpCntLimPng;
+        if (mDumpCntLimPng) {
+            snprintf(mDumpDirPng, sizeof(mDumpDirPng),
+                    "/data/sfdump.png.%04d.%02d.%02d.%02d.%02d.%02d",
+                    dumpTime.tm_year + 1900, dumpTime.tm_mon + 1,
+                    dumpTime.tm_mday, dumpTime.tm_hour,
+                    dumpTime.tm_min, dumpTime.tm_sec);
+            if (0 == mkdir(mDumpDirPng, 0777))
+                mDumpCntrPng = 0;
+            else {
+                ALOGE("Error: %s. Failed to create sfdump directory: %s",
+                    strerror(errno), mDumpDirPng);
+                mDumpCntrPng = mDumpCntLimPng + 1;
+            }
+        }
+    }
+
+    if (mDumpCntrPng <= mDumpCntLimPng)
+        mDumpCntrPng++;
+
+    if ((property_get("debug.sf.dump", dumpPropStr, NULL) > 0) &&
+            (strncmp(dumpPropStr, mDumpPropStrRaw, PROPERTY_VALUE_MAX - 1))) {
+        // Strings exist & not equal implies it has changed, so trigger a dump
+        strlcpy(mDumpPropStrRaw, dumpPropStr, sizeof(mDumpPropStrRaw));
+        mDumpCntLimRaw = atoi(dumpPropStr);
+        if (mDumpCntLimRaw > MAX_ALLOWED_FRAMEDUMPS) {
+            ALOGW("Warning: Using debug.sf.dump %d (= max)",
+                MAX_ALLOWED_FRAMEDUMPS);
+            mDumpCntLimRaw = MAX_ALLOWED_FRAMEDUMPS;
+        }
+        mDumpCntLimRaw = (mDumpCntLimRaw < 0) ? 0: mDumpCntLimRaw;
+        if (mDumpCntLimRaw) {
+            snprintf(mDumpDirRaw, sizeof(mDumpDirRaw),
+                    "/data/sfdump.raw.%04d.%02d.%02d.%02d.%02d.%02d",
+                    dumpTime.tm_year + 1900, dumpTime.tm_mon + 1,
+                    dumpTime.tm_mday, dumpTime.tm_hour,
+                    dumpTime.tm_min, dumpTime.tm_sec);
+            if (0 == mkdir(mDumpDirRaw, 0777))
+                mDumpCntrRaw = 0;
+            else {
+                ALOGE("Error: %s. Failed to create sfdump directory: %s",
+                    strerror(errno), mDumpDirRaw);
+                mDumpCntrRaw = mDumpCntLimRaw + 1;
+            }
+        }
+    }
+
+    if (mDumpCntrRaw <= mDumpCntLimRaw)
+        mDumpCntrRaw++;
+
+    bDumpLayer = (mDumpCntLimPng || mDumpCntLimRaw)? true : false;
+    return bDumpLayer;
+}
+
+void HwcDebug::logHwcProps(uint32_t listFlags)
+{
+    static int hwcModuleCompType = -1;
+    static int sMdpCompMaxLayers = 0;
+    static String8 hwcModuleCompTypeLog("");
+    if (-1 == hwcModuleCompType) {
+        // One time stuff
+        char mdpCompPropStr[PROPERTY_VALUE_MAX];
+        if (property_get("debug.mdpcomp.maxlayer", mdpCompPropStr, NULL) > 0) {
+            sMdpCompMaxLayers = atoi(mdpCompPropStr);
+        }
+        hwcModuleCompType =
+            qdutils::QCCompositionType::getInstance().getCompositionType();
+        hwcModuleCompTypeLog.appendFormat("%s%s%s%s%s%s",
+            // Is hwc module composition type now a bit-field?!
+            (hwcModuleCompType == qdutils::COMPOSITION_TYPE_GPU)?
+                "[GPU]": "",
+            (hwcModuleCompType & qdutils::COMPOSITION_TYPE_MDP)?
+                "[MDP]": "",
+            (hwcModuleCompType & qdutils::COMPOSITION_TYPE_C2D)?
+                "[C2D]": "",
+            (hwcModuleCompType & qdutils::COMPOSITION_TYPE_CPU)?
+                "[CPU]": "",
+            (hwcModuleCompType & qdutils::COMPOSITION_TYPE_DYN)?
+                "[DYN]": "",
+            (hwcModuleCompType >= (qdutils::COMPOSITION_TYPE_DYN << 1))?
+                "[???]": "");
+    }
+    ALOGI("Display[%s] Layer[*] %s-HwcModuleCompType, %d-layer MdpComp %s",
+         mDisplayName, hwcModuleCompTypeLog.string(), sMdpCompMaxLayers,
+        (listFlags & HWC_GEOMETRY_CHANGED)? "[HwcList Geometry Changed]": "");
+}
+
+void HwcDebug::logLayer(size_t layerIndex, hwc_layer_1_t hwLayers[])
+{
+    if (NULL == hwLayers) {
+        ALOGE("Display[%s] Layer[%zu] Error. No hwc layers to log.",
+            mDisplayName, layerIndex);
+        return;
+    }
+
+    hwc_layer_1_t *layer = &hwLayers[layerIndex];
+    hwc_rect_t sourceCrop = integerizeSourceCrop(layer->sourceCropf);
+    hwc_rect_t displayFrame = layer->displayFrame;
+    size_t numHwcRects = layer->visibleRegionScreen.numRects;
+    hwc_rect_t const *hwcRects = layer->visibleRegionScreen.rects;
+    private_handle_t *hnd = (private_handle_t *)layer->handle;
+
+    char pixFormatStr[32] = "None";
+    String8 hwcVisRegsScrLog("[None]");
+
+    for (size_t i = 0 ; (hwcRects && (i < numHwcRects)); i++) {
+        if (0 == i)
+            hwcVisRegsScrLog.clear();
+        hwcVisRegsScrLog.appendFormat("[%dl, %dt, %dr, %db]",
+                                        hwcRects[i].left, hwcRects[i].top,
+                                        hwcRects[i].right, hwcRects[i].bottom);
+    }
+
+    if (hnd)
+        getHalPixelFormatStr(hnd->format, pixFormatStr);
+
+    // Log Line 1
+    ALOGI("Display[%s] Layer[%zu] SrcBuff[%dx%d] SrcCrop[%dl, %dt, %dr, %db] "
+        "DispFrame[%dl, %dt, %dr, %db] VisRegsScr%s", mDisplayName, layerIndex,
+        (hnd)? getWidth(hnd) : -1, (hnd)? getHeight(hnd) : -1,
+        sourceCrop.left, sourceCrop.top,
+        sourceCrop.right, sourceCrop.bottom,
+        displayFrame.left, displayFrame.top,
+        displayFrame.right, displayFrame.bottom,
+        hwcVisRegsScrLog.string());
+    // Log Line 2
+    ALOGI("Display[%s] Layer[%zu] LayerCompType = %s, Format = %s, "
+        "Orientation = %s, Flags = %s%s%s, Hints = %s%s%s, "
+        "Blending = %s%s%s", mDisplayName, layerIndex,
+        (layer->compositionType == HWC_FRAMEBUFFER)? "Framebuffer(GPU)":
+            (layer->compositionType == HWC_OVERLAY)? "Overlay":
+            (layer->compositionType == HWC_BACKGROUND)? "Background":"???",
+         pixFormatStr,
+         (layer->transform == 0)? "ROT_0":
+             (layer->transform == HWC_TRANSFORM_FLIP_H)? "FLIP_H":
+             (layer->transform == HWC_TRANSFORM_FLIP_V)? "FLIP_V":
+             (layer->transform == HWC_TRANSFORM_ROT_90)? "ROT_90":
+                                                        "ROT_INVALID",
+         (layer->flags)? "": "[None]",
+         (layer->flags & HWC_SKIP_LAYER)? "[Skip layer]":"",
+         (layer->flags & qhwc::HWC_MDPCOMP)? "[MDP Comp]":"",
+         (layer->hints)? "":"[None]",
+         (layer->hints & HWC_HINT_TRIPLE_BUFFER)? "[Triple Buffer]":"",
+         (layer->hints & HWC_HINT_CLEAR_FB)? "[Clear FB]":"",
+         (layer->blending == HWC_BLENDING_NONE)? "[None]":"",
+         (layer->blending == HWC_BLENDING_PREMULT)? "[PreMult]":"",
+         (layer->blending == HWC_BLENDING_COVERAGE)? "[Coverage]":"");
+}
+
+void HwcDebug::dumpLayer(size_t layerIndex, hwc_layer_1_t hwLayers[])
+{
+    char dumpLogStrPng[128] = "";
+    char dumpLogStrRaw[128] = "";
+    bool needDumpPng = (mDumpCntrPng <= mDumpCntLimPng)? true:false;
+    bool needDumpRaw = (mDumpCntrRaw <= mDumpCntLimRaw)? true:false;
+
+    if (needDumpPng) {
+        snprintf(dumpLogStrPng, sizeof(dumpLogStrPng),
+            "[png-dump-frame: %03d of %03d]", mDumpCntrPng,
+            mDumpCntLimPng);
+    }
+    if (needDumpRaw) {
+        snprintf(dumpLogStrRaw, sizeof(dumpLogStrRaw),
+            "[raw-dump-frame: %03d of %03d]", mDumpCntrRaw,
+            mDumpCntLimRaw);
+    }
+
+    if (!(needDumpPng || needDumpRaw))
+        return;
+
+    if (NULL == hwLayers) {
+        ALOGE("Display[%s] Layer[%zu] %s%s Error: No hwc layers to dump.",
+            mDisplayName, layerIndex, dumpLogStrRaw, dumpLogStrPng);
+        return;
+    }
+
+    hwc_layer_1_t *layer = &hwLayers[layerIndex];
+    private_handle_t *hnd = (private_handle_t *)layer->handle;
+    char pixFormatStr[32] = "None";
+
+    if (NULL == hnd) {
+        ALOGI("Display[%s] Layer[%zu] %s%s Skipping dump: Bufferless layer.",
+            mDisplayName, layerIndex, dumpLogStrRaw, dumpLogStrPng);
+        return;
+    }
+
+    getHalPixelFormatStr(hnd->format, pixFormatStr);
+#ifdef QTI_BSP
+    if (needDumpPng && hnd->base) {
+        bool bResult = false;
+        char dumpFilename[PATH_MAX];
+        SkBitmap *tempSkBmp = new SkBitmap();
+        SkColorType tempSkBmpColor = kUnknown_SkColorType;
+        snprintf(dumpFilename, sizeof(dumpFilename),
+            "%s/sfdump%03d.layer%zu.%s.png", mDumpDirPng,
+            mDumpCntrPng, layerIndex, mDisplayName);
+
+        switch (hnd->format) {
+            case HAL_PIXEL_FORMAT_RGBA_8888:
+            case HAL_PIXEL_FORMAT_RGBX_8888:
+                tempSkBmpColor = kRGBA_8888_SkColorType;
+                break;
+            case HAL_PIXEL_FORMAT_BGRA_8888:
+                tempSkBmpColor = kBGRA_8888_SkColorType;
+                break;
+            case HAL_PIXEL_FORMAT_RGB_565:
+                tempSkBmpColor = kRGB_565_SkColorType;
+                break;
+            case HAL_PIXEL_FORMAT_RGB_888:
+            default:
+                tempSkBmpColor = kUnknown_SkColorType;
+                break;
+        }
+        if (kUnknown_SkColorType != tempSkBmpColor) {
+            tempSkBmp->setInfo(SkImageInfo::Make(getWidth(hnd), getHeight(hnd),
+                    tempSkBmpColor, kUnknown_SkAlphaType), 0);
+            tempSkBmp->setPixels((void*)hnd->base);
+            bResult = SkImageEncoder::EncodeFile(dumpFilename,
+                                    *tempSkBmp, SkImageEncoder::kPNG_Type, 100);
+            ALOGI("Display[%s] Layer[%zu] %s Dump to %s: %s",
+                mDisplayName, layerIndex, dumpLogStrPng,
+                dumpFilename, bResult ? "Success" : "Fail");
+        } else {
+            ALOGI("Display[%s] Layer[%zu] %s Skipping dump: Unsupported layer"
+                " format %s for png encoder",
+                mDisplayName, layerIndex, dumpLogStrPng, pixFormatStr);
+        }
+        delete tempSkBmp; // Calls SkBitmap::freePixels() internally.
+    }
+#endif
+    if (needDumpRaw && hnd->base) {
+        char dumpFilename[PATH_MAX];
+        bool bResult = false;
+        snprintf(dumpFilename, sizeof(dumpFilename),
+            "%s/sfdump%03d.layer%zu.%dx%d.%s.%s.raw",
+            mDumpDirRaw, mDumpCntrRaw,
+            layerIndex, getWidth(hnd), getHeight(hnd),
+            pixFormatStr, mDisplayName);
+        FILE* fp = fopen(dumpFilename, "w+");
+        if (NULL != fp) {
+            bResult = (bool) fwrite((void*)hnd->base, hnd->size, 1, fp);
+            fclose(fp);
+        }
+        ALOGI("Display[%s] Layer[%zu] %s Dump to %s: %s",
+            mDisplayName, layerIndex, dumpLogStrRaw,
+            dumpFilename, bResult ? "Success" : "Fail");
+    }
+}
+
+void HwcDebug::getHalPixelFormatStr(int format, char pixFormatStr[])
+{
+    if (!pixFormatStr)
+        return;
+
+    switch(format) {
+        case HAL_PIXEL_FORMAT_RGBA_8888:
+            strlcpy(pixFormatStr, "RGBA_8888", sizeof(pixFormatStr));
+            break;
+        case HAL_PIXEL_FORMAT_RGBX_8888:
+            strlcpy(pixFormatStr, "RGBX_8888", sizeof(pixFormatStr));
+            break;
+        case HAL_PIXEL_FORMAT_RGB_888:
+            strlcpy(pixFormatStr, "RGB_888", sizeof(pixFormatStr));
+            break;
+        case HAL_PIXEL_FORMAT_RGB_565:
+            strlcpy(pixFormatStr, "RGB_565", sizeof(pixFormatStr));
+            break;
+        case HAL_PIXEL_FORMAT_BGRA_8888:
+            strlcpy(pixFormatStr, "BGRA_8888", sizeof(pixFormatStr));
+            break;
+        case HAL_PIXEL_FORMAT_YV12:
+            strlcpy(pixFormatStr, "YV12", sizeof(pixFormatStr));
+            break;
+        case HAL_PIXEL_FORMAT_YCbCr_422_SP:
+            strlcpy(pixFormatStr, "YCbCr_422_SP_NV16", sizeof(pixFormatStr));
+            break;
+        case HAL_PIXEL_FORMAT_YCrCb_420_SP:
+            strlcpy(pixFormatStr, "YCrCb_420_SP_NV21", sizeof(pixFormatStr));
+            break;
+        case HAL_PIXEL_FORMAT_YCbCr_422_I:
+            strlcpy(pixFormatStr, "YCbCr_422_I_YUY2", sizeof(pixFormatStr));
+            break;
+        case HAL_PIXEL_FORMAT_YCrCb_422_I:
+            strlcpy(pixFormatStr, "YCrCb_422_I_YVYU", sizeof(pixFormatStr));
+            break;
+        case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:
+            strlcpy(pixFormatStr, "NV12_ENCODEABLE", sizeof(pixFormatStr));
+            break;
+        case HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED:
+            strlcpy(pixFormatStr, "YCbCr_420_SP_TILED_TILE_4x2",
+                   sizeof(pixFormatStr));
+            break;
+        case HAL_PIXEL_FORMAT_YCbCr_420_SP:
+            strlcpy(pixFormatStr, "YCbCr_420_SP", sizeof(pixFormatStr));
+            break;
+        case HAL_PIXEL_FORMAT_YCrCb_420_SP_ADRENO:
+            strlcpy(pixFormatStr, "YCrCb_420_SP_ADRENO", sizeof(pixFormatStr));
+            break;
+        case HAL_PIXEL_FORMAT_YCrCb_422_SP:
+            strlcpy(pixFormatStr, "YCrCb_422_SP", sizeof(pixFormatStr));
+            break;
+        case HAL_PIXEL_FORMAT_R_8:
+            strlcpy(pixFormatStr, "R_8", sizeof(pixFormatStr));
+            break;
+        case HAL_PIXEL_FORMAT_RG_88:
+            strlcpy(pixFormatStr, "RG_88", sizeof(pixFormatStr));
+            break;
+        case HAL_PIXEL_FORMAT_INTERLACE:
+            strlcpy(pixFormatStr, "INTERLACE", sizeof(pixFormatStr));
+            break;
+        case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS:
+            strlcpy(pixFormatStr, "YCbCr_420_SP_VENUS", sizeof(pixFormatStr));
+            break;
+        default:
+            size_t len = sizeof(pixFormatStr);
+            snprintf(pixFormatStr, len, "Unknown0x%X", format);
+            break;
+    }
+}
+
+} // namespace qhwc
+
diff --git a/msm8909/libhwcomposer/hwc_dump_layers.h b/msm8909/libhwcomposer/hwc_dump_layers.h
new file mode 100644
index 0000000..f0d654f
--- /dev/null
+++ b/msm8909/libhwcomposer/hwc_dump_layers.h
@@ -0,0 +1,138 @@
+/*
+ * Copyright (c) 2012-2013, Linux Foundation. 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 Linux Foundation 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 HWC_DUMP_LAYERS_H
+#define HWC_DUMP_LAYERS_H
+
+#include <gralloc_priv.h>
+#include <comptype.h>
+#include <ui/Region.h>
+#include <hardware/hwcomposer.h>
+#include <utils/String8.h>
+
+namespace qhwc {
+
+class HwcDebug {
+private:
+
+// Using static variables for layer dumping since "property_set("debug.sf.dump",
+// property)" does not work.
+  int mDumpCntLimRaw;
+  int mDumpCntrRaw;
+  char mDumpPropStrRaw[PROPERTY_VALUE_MAX];
+  char mDumpDirRaw[PATH_MAX];
+  int mDumpCntLimPng;
+  int mDumpCntrPng;
+  char mDumpPropStrPng[PROPERTY_VALUE_MAX];
+  char mDumpDirPng[PATH_MAX];
+  uint32_t mDpy;
+  char mDisplayName[PROPERTY_VALUE_MAX];
+  char mDumpPropKeyDisplayType[PROPERTY_KEY_MAX];
+  static bool sDumpEnable;
+
+public:
+    HwcDebug(uint32_t dpy);
+    ~HwcDebug() {};
+
+    /*
+     * Dump layers for debugging based on "debug.sf.dump*" system property.
+     * See needToDumpLayers() for usage.
+     *
+     * @param: list - The HWC layer-list to dump.
+     *
+     */
+    void dumpLayers(hwc_display_contents_1_t* list);
+
+/*
+ * Checks if layers need to be dumped based on system property "debug.sf.dump"
+ * for raw dumps and "debug.sf.dump.png" for png dumps.
+ *
+ * Note: Set "debug.sf.dump.primary" or "debug.sf.dump.external" as true
+ * in the device's /system/build.prop file to enable layer logging/capturing
+ * feature for primary or external respectively. The feature is disabled by
+ * default to avoid per-frame property_get() calls.
+ *
+ * To turn on layer dump, set "debug.sf.dump.enable" to true in build.prop.
+ * By default debug.sf.dump.primary will be set to true for user convenience.
+ *
+ * To turn on layer dump for primary, do,
+ *     adb shell setprop debug.sf.dump.primary true
+ *
+ * To turn on layer dump for external, do,
+ *     adb shell setprop debug.sf.dump.external true
+ *
+ * For example, to dump 25 frames in raw format, do,
+ *     adb shell setprop debug.sf.dump 25
+ * Layers are dumped in a time-stamped location: /data/sfdump*.
+ *
+ * To dump 10 frames in png format, do,
+ *     adb shell setprop debug.sf.dump.png 10
+ * To dump another 25 or so frames in raw format, do,
+ *     adb shell setprop debug.sf.dump 26
+ *
+ * To turn off logcat logging of layer-info, set both properties to 0,
+ *     adb shell setprop debug.sf.dump.png 0
+ *     adb shell setprop debug.sf.dump 0
+ *
+ * @return: true if layers need to be dumped (or logcat-ed).
+ */
+bool needToDumpLayers();
+
+/*
+ * Log a few per-frame hwc properties into logcat.
+ *
+ * @param: listFlags - Flags used in hwcomposer's list.
+ *
+ */
+void logHwcProps(uint32_t listFlags);
+
+/*
+ * Log a layer's info into logcat.
+ *
+ * @param: layerIndex - Index of layer being dumped.
+ * @param: hwLayers - Address of hwc_layer_1_t to log and dump.
+ *
+ */
+void logLayer(size_t layerIndex, hwc_layer_1_t hwLayers[]);
+
+/*
+ * Dumps a layer buffer into raw/png files.
+ *
+ * @param: layerIndex - Index of layer being dumped.
+ * @param: hwLayers - Address of hwc_layer_1_t to log and dump.
+ *
+ */
+void dumpLayer(size_t layerIndex, hwc_layer_1_t hwLayers[]);
+
+void getHalPixelFormatStr(int format, char pixelformatstr[]);
+};
+
+} // namespace qhwc
+
+#endif /* HWC_DUMP_LAYERS_H */
diff --git a/msm8909/libhwcomposer/hwc_fbupdate.cpp b/msm8909/libhwcomposer/hwc_fbupdate.cpp
new file mode 100644
index 0000000..b003266
--- /dev/null
+++ b/msm8909/libhwcomposer/hwc_fbupdate.cpp
@@ -0,0 +1,565 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ * Copyright (C) 2012-2014, The Linux Foundation. All rights reserved.
+ *
+ * Not a Contribution, Apache license notifications and license are
+ * retained for attribution purposes only.
+ *
+ * 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 DEBUG_FBUPDATE 0
+#include <cutils/properties.h>
+#include <gralloc_priv.h>
+#include <overlay.h>
+#include <overlayRotator.h>
+#include "hwc_fbupdate.h"
+#include "mdp_version.h"
+
+using namespace qdutils;
+using namespace overlay;
+using overlay::Rotator;
+using namespace overlay::utils;
+
+namespace qhwc {
+
+namespace ovutils = overlay::utils;
+
+IFBUpdate* IFBUpdate::getObject(hwc_context_t *ctx, const int& dpy) {
+    if(qdutils::MDPVersion::getInstance().isSrcSplit()) {
+        return new FBSrcSplit(ctx, dpy);
+    } else if(isDisplaySplit(ctx, dpy)) {
+        return new FBUpdateSplit(ctx, dpy);
+    }
+    return new FBUpdateNonSplit(ctx, dpy);
+}
+
+IFBUpdate::IFBUpdate(hwc_context_t *ctx, const int& dpy) : mDpy(dpy) {
+    unsigned int size = 0;
+    uint32_t xres = ctx->dpyAttr[mDpy].xres;
+    uint32_t yres = ctx->dpyAttr[mDpy].yres;
+    if (ctx->dpyAttr[dpy].customFBSize) {
+        //GPU will render and compose at new resolution
+        //So need to have FB at new resolution
+        xres = ctx->dpyAttr[mDpy].xres_new;
+        yres = ctx->dpyAttr[mDpy].yres_new;
+    }
+    getBufferAttributes((int)xres, (int)yres,
+            ctx->dpyAttr[mDpy].fbformat,
+            0,
+            mAlignedFBWidth,
+            mAlignedFBHeight,
+            mTileEnabled, size);
+}
+
+void IFBUpdate::reset() {
+    mModeOn = false;
+    mRot = NULL;
+}
+
+bool IFBUpdate::prepareAndValidate(hwc_context_t *ctx,
+            hwc_display_contents_1 *list, int fbZorder) {
+    hwc_layer_1_t *layer = &list->hwLayers[list->numHwLayers - 1];
+    mModeOn = prepare(ctx, list, layer->displayFrame, fbZorder) &&
+            ctx->mOverlay->validateAndSet(mDpy, ctx->dpyAttr[mDpy].fd);
+    return mModeOn;
+}
+
+//================= Low res====================================
+FBUpdateNonSplit::FBUpdateNonSplit(hwc_context_t *ctx, const int& dpy):
+        IFBUpdate(ctx, dpy) {}
+
+void FBUpdateNonSplit::reset() {
+    IFBUpdate::reset();
+    mDest = ovutils::OV_INVALID;
+}
+
+bool FBUpdateNonSplit::preRotateExtDisplay(hwc_context_t *ctx,
+                                            hwc_layer_1_t *layer,
+                                            ovutils::Whf &info,
+                                            hwc_rect_t& sourceCrop,
+                                            ovutils::eMdpFlags& mdpFlags,
+                                            int& rotFlags)
+{
+    int extOrient = getExtOrientation(ctx);
+    ovutils::eTransform orient = static_cast<ovutils::eTransform >(extOrient);
+    if(mDpy && (extOrient & HWC_TRANSFORM_ROT_90)) {
+        mRot = ctx->mRotMgr->getNext();
+        if(mRot == NULL) return false;
+        ctx->mLayerRotMap[mDpy]->add(layer, mRot);
+        // Composed FB content will have black bars, if the viewFrame of the
+        // external is different from {0, 0, fbWidth, fbHeight}, so intersect
+        // viewFrame with sourceCrop to avoid those black bars
+        sourceCrop = getIntersection(sourceCrop, ctx->mViewFrame[mDpy]);
+        //Configure rotator for pre-rotation
+        if(configRotator(mRot, info, sourceCrop, mdpFlags, orient, 0) < 0) {
+            ALOGE("%s: configRotator Failed!", __FUNCTION__);
+            mRot = NULL;
+            return false;
+        }
+        updateSource(orient, info, sourceCrop, mRot);
+        rotFlags |= ovutils::ROT_PREROTATED;
+    }
+    return true;
+}
+
+bool FBUpdateNonSplit::prepare(hwc_context_t *ctx, hwc_display_contents_1 *list,
+                             hwc_rect_t fbUpdatingRect, int fbZorder) {
+    if(!ctx->mMDP.hasOverlay) {
+        ALOGD_IF(DEBUG_FBUPDATE, "%s, this hw doesnt support overlays",
+                 __FUNCTION__);
+        return false;
+    }
+    mModeOn = configure(ctx, list, fbUpdatingRect, fbZorder);
+    return mModeOn;
+}
+
+// Configure
+bool FBUpdateNonSplit::configure(hwc_context_t *ctx, hwc_display_contents_1 *list,
+                               hwc_rect_t fbUpdatingRect, int fbZorder) {
+    bool ret = false;
+    hwc_layer_1_t *layer = &list->hwLayers[list->numHwLayers - 1];
+    if (LIKELY(ctx->mOverlay)) {
+        overlay::Overlay& ov = *(ctx->mOverlay);
+
+        ovutils::Whf info(mAlignedFBWidth, mAlignedFBHeight,
+                ovutils::getMdpFormat(ctx->dpyAttr[mDpy].fbformat,
+                    mTileEnabled));
+
+        Overlay::PipeSpecs pipeSpecs;
+        pipeSpecs.formatClass = Overlay::FORMAT_RGB;
+        pipeSpecs.needsScaling = qhwc::needsScaling(layer);
+        pipeSpecs.dpy = mDpy;
+        pipeSpecs.mixer = Overlay::MIXER_DEFAULT;
+        pipeSpecs.fb = true;
+
+        ovutils::eDest dest = ov.getPipe(pipeSpecs);
+        if(dest == ovutils::OV_INVALID) { //None available
+            ALOGE("%s: No pipes available to configure fb for dpy %d",
+                __FUNCTION__, mDpy);
+            return false;
+        }
+        mDest = dest;
+
+        if((mDpy && ctx->deviceOrientation) &&
+            ctx->listStats[mDpy].isDisplayAnimating) {
+            fbZorder = 0;
+        }
+
+        ovutils::eMdpFlags mdpFlags = ovutils::OV_MDP_BLEND_FG_PREMULT;
+        ovutils::eZorder zOrder = static_cast<ovutils::eZorder>(fbZorder);
+
+        hwc_rect_t sourceCrop = integerizeSourceCrop(layer->sourceCropf);
+        hwc_rect_t displayFrame = layer->displayFrame;
+
+        // No FB update optimization on (1) Custom FB resolution,
+        // (2) External Mirror mode, (3) External orientation
+        if(!ctx->dpyAttr[mDpy].customFBSize && !ctx->mBufferMirrorMode
+           && !ctx->mExtOrientation) {
+            sourceCrop = fbUpdatingRect;
+            displayFrame = fbUpdatingRect;
+        }
+
+        int transform = layer->transform;
+        int rotFlags = ovutils::ROT_FLAGS_NONE;
+
+        ovutils::eTransform orient =
+                    static_cast<ovutils::eTransform>(transform);
+        // use ext orientation if any
+        int extOrient = getExtOrientation(ctx);
+
+        // Do not use getNonWormholeRegion() function to calculate the
+        // sourceCrop during animation on external display and
+        // Dont do wormhole calculation when extorientation is set on External
+        // Dont do wormhole calculation when scaling mode is set on External
+        if(ctx->listStats[mDpy].isDisplayAnimating && mDpy) {
+            sourceCrop = layer->displayFrame;
+        } else if((mDpy && !extOrient
+                  && !ctx->dpyAttr[mDpy].mMDPScalingMode)) {
+            if(ctx->mOverlay->isUIScalingOnExternalSupported() &&
+                !ctx->dpyAttr[mDpy].customFBSize) {
+                getNonWormholeRegion(list, sourceCrop);
+                displayFrame = sourceCrop;
+            }
+        }
+        calcExtDisplayPosition(ctx, NULL, mDpy, sourceCrop, displayFrame,
+                                   transform, orient);
+        //Store the displayFrame, will be used in getDisplayViewFrame
+        ctx->dpyAttr[mDpy].mDstRect = displayFrame;
+        setMdpFlags(ctx, layer, mdpFlags, 0, transform);
+        // For External use rotator if there is a rotation value set
+        ret = preRotateExtDisplay(ctx, layer, info,
+                sourceCrop, mdpFlags, rotFlags);
+        if(!ret) {
+            ALOGE("%s: preRotate for external Failed!", __FUNCTION__);
+            return false;
+        }
+        //For the mdp, since either we are pre-rotating or MDP does flips
+        orient = ovutils::OVERLAY_TRANSFORM_0;
+        transform = 0;
+        ovutils::PipeArgs parg(mdpFlags, info, zOrder,
+                               static_cast<ovutils::eRotFlags>(rotFlags),
+                               ovutils::DEFAULT_PLANE_ALPHA,
+                               (ovutils::eBlending)
+                               getBlending(layer->blending));
+        ret = true;
+        if(configMdp(ctx->mOverlay, parg, orient, sourceCrop, displayFrame,
+                    NULL, mDest) < 0) {
+            ALOGE("%s: configMdp failed for dpy %d", __FUNCTION__, mDpy);
+            ret = false;
+        }
+    }
+    return ret;
+}
+
+bool FBUpdateNonSplit::draw(hwc_context_t *ctx, private_handle_t *hnd)
+{
+    if(!mModeOn) {
+        return true;
+    }
+    bool ret = true;
+    overlay::Overlay& ov = *(ctx->mOverlay);
+    ovutils::eDest dest = mDest;
+    int fd = hnd->fd;
+    uint32_t offset = (uint32_t)hnd->offset;
+    if(mRot) {
+        if(!mRot->queueBuffer(fd, offset))
+            return false;
+        fd = mRot->getDstMemId();
+        offset = mRot->getDstOffset();
+    }
+    if (!ov.queueBuffer(fd, offset, dest)) {
+        ALOGE("%s: queueBuffer failed for FBUpdate", __FUNCTION__);
+        ret = false;
+    }
+    return ret;
+}
+
+//================= High res====================================
+FBUpdateSplit::FBUpdateSplit(hwc_context_t *ctx, const int& dpy):
+        IFBUpdate(ctx, dpy) {}
+
+void FBUpdateSplit::reset() {
+    IFBUpdate::reset();
+    mDestLeft = ovutils::OV_INVALID;
+    mDestRight = ovutils::OV_INVALID;
+    mRot = NULL;
+}
+
+bool FBUpdateSplit::prepare(hwc_context_t *ctx, hwc_display_contents_1 *list,
+                              hwc_rect_t fbUpdatingRect, int fbZorder) {
+    if(!ctx->mMDP.hasOverlay) {
+        ALOGD_IF(DEBUG_FBUPDATE, "%s, this hw doesnt support overlays",
+                 __FUNCTION__);
+        return false;
+    }
+    mModeOn = configure(ctx, list, fbUpdatingRect, fbZorder);
+    ALOGD_IF(DEBUG_FBUPDATE, "%s, mModeOn = %d", __FUNCTION__, mModeOn);
+    return mModeOn;
+}
+
+// Configure
+bool FBUpdateSplit::configure(hwc_context_t *ctx,
+        hwc_display_contents_1 *list, hwc_rect_t fbUpdatingRect, int fbZorder) {
+    bool ret = false;
+    hwc_layer_1_t *layer = &list->hwLayers[list->numHwLayers - 1];
+    if (LIKELY(ctx->mOverlay)) {
+        ovutils::Whf info(mAlignedFBWidth, mAlignedFBHeight,
+                          ovutils::getMdpFormat(HAL_PIXEL_FORMAT_RGBA_8888,
+                                                mTileEnabled));
+
+        overlay::Overlay& ov = *(ctx->mOverlay);
+        ovutils::eMdpFlags mdpFlags = ovutils::OV_MDP_BLEND_FG_PREMULT;
+        ovutils::eZorder zOrder = static_cast<ovutils::eZorder>(fbZorder);
+        ovutils::eTransform orient =
+            static_cast<ovutils::eTransform>(layer->transform);
+        const int hw_w = ctx->dpyAttr[mDpy].xres;
+        const int hw_h = ctx->dpyAttr[mDpy].yres;
+        const int lSplit = getLeftSplit(ctx, mDpy);
+        mDestLeft = ovutils::OV_INVALID;
+        mDestRight = ovutils::OV_INVALID;
+        hwc_rect_t sourceCrop = integerizeSourceCrop(layer->sourceCropf);
+        hwc_rect_t displayFrame = layer->displayFrame;
+
+        // No FB update optimization on (1) Custom FB resolution,
+        // (2) External Mirror mode, (3) External orientation
+        if(!ctx->dpyAttr[mDpy].customFBSize && !ctx->mBufferMirrorMode
+           && !ctx->mExtOrientation) {
+            sourceCrop = fbUpdatingRect;
+            displayFrame = fbUpdatingRect;
+        }
+
+        int transform = layer->transform;
+        // use ext orientation if any
+        int extOrient = getExtOrientation(ctx);
+
+        // Do not use getNonWormholeRegion() function to calculate the
+        // sourceCrop during animation on external display and
+        // Dont do wormhole calculation when extorientation is set on External
+        // Dont do wormhole calculation when scaling mode is set on External
+        if(ctx->listStats[mDpy].isDisplayAnimating && mDpy) {
+            sourceCrop = layer->displayFrame;
+        } else if((mDpy && !extOrient
+                  && !ctx->dpyAttr[mDpy].mMDPScalingMode)) {
+            if(!qdutils::MDPVersion::getInstance().is8x26() &&
+                !ctx->dpyAttr[mDpy].customFBSize) {
+                getNonWormholeRegion(list, sourceCrop);
+                displayFrame = sourceCrop;
+            }
+        }
+
+        calcExtDisplayPosition(ctx, NULL, mDpy, sourceCrop, displayFrame,
+                                   transform, orient);
+
+        ret = true;
+        Overlay::PipeSpecs pipeSpecs;
+        pipeSpecs.formatClass = Overlay::FORMAT_RGB;
+        pipeSpecs.needsScaling = qhwc::needsScaling(layer);
+        pipeSpecs.dpy = mDpy;
+        pipeSpecs.fb = true;
+
+        /* Configure left pipe */
+        if(displayFrame.left < lSplit) {
+            pipeSpecs.mixer = Overlay::MIXER_LEFT;
+            ovutils::eDest destL = ov.getPipe(pipeSpecs);
+            if(destL == ovutils::OV_INVALID) { //None available
+                ALOGE("%s: No pipes available to configure fb for dpy %d's left"
+                      " mixer", __FUNCTION__, mDpy);
+                return false;
+            }
+
+            mDestLeft = destL;
+
+            //XXX: FB layer plane alpha is currently sent as zero from
+            //surfaceflinger
+            ovutils::PipeArgs pargL(mdpFlags,
+                                    info,
+                                    zOrder,
+                                    ovutils::ROT_FLAGS_NONE,
+                                    ovutils::DEFAULT_PLANE_ALPHA,
+                                    (ovutils::eBlending)
+                                    getBlending(layer->blending));
+            hwc_rect_t cropL = sourceCrop;
+            hwc_rect_t dstL = displayFrame;
+            hwc_rect_t scissorL = {0, 0, lSplit, hw_h };
+            qhwc::calculate_crop_rects(cropL, dstL, scissorL, 0);
+
+            if (configMdp(ctx->mOverlay, pargL, orient, cropL,
+                           dstL, NULL, destL)< 0) {
+                ALOGE("%s: configMdp fails for left FB", __FUNCTION__);
+                ret = false;
+            }
+        }
+
+        /* Configure right pipe */
+        if(displayFrame.right > lSplit) {
+            pipeSpecs.mixer = Overlay::MIXER_RIGHT;
+            ovutils::eDest destR = ov.getPipe(pipeSpecs);
+            if(destR == ovutils::OV_INVALID) { //None available
+                ALOGE("%s: No pipes available to configure fb for dpy %d's"
+                      " right mixer", __FUNCTION__, mDpy);
+                return false;
+            }
+
+            mDestRight = destR;
+            ovutils::eMdpFlags mdpFlagsR = mdpFlags;
+            ovutils::setMdpFlags(mdpFlagsR, ovutils::OV_MDSS_MDP_RIGHT_MIXER);
+
+            //XXX: FB layer plane alpha is currently sent as zero from
+            //surfaceflinger
+            ovutils::PipeArgs pargR(mdpFlagsR,
+                                    info,
+                                    zOrder,
+                                    ovutils::ROT_FLAGS_NONE,
+                                    ovutils::DEFAULT_PLANE_ALPHA,
+                                    (ovutils::eBlending)
+                                    getBlending(layer->blending));
+
+            hwc_rect_t cropR = sourceCrop;
+            hwc_rect_t dstR = displayFrame;
+            hwc_rect_t scissorR = {lSplit, 0, hw_w, hw_h };
+            qhwc::calculate_crop_rects(cropR, dstR, scissorR, 0);
+
+            dstR.left -= lSplit;
+            dstR.right -= lSplit;
+
+            if (configMdp(ctx->mOverlay, pargR, orient, cropR,
+                           dstR, NULL, destR) < 0) {
+                ALOGE("%s: configMdp fails for right FB", __FUNCTION__);
+                ret = false;
+            }
+        }
+    }
+    return ret;
+}
+
+bool FBUpdateSplit::draw(hwc_context_t *ctx, private_handle_t *hnd)
+{
+    if(!mModeOn) {
+        return true;
+    }
+    bool ret = true;
+    overlay::Overlay& ov = *(ctx->mOverlay);
+    if(mDestLeft != ovutils::OV_INVALID) {
+        if (!ov.queueBuffer(hnd->fd, (uint32_t)hnd->offset, mDestLeft)) {
+            ALOGE("%s: queue failed for left of dpy = %d",
+                  __FUNCTION__, mDpy);
+            ret = false;
+        }
+    }
+    if(mDestRight != ovutils::OV_INVALID) {
+        if (!ov.queueBuffer(hnd->fd, (uint32_t)hnd->offset, mDestRight)) {
+            ALOGE("%s: queue failed for right of dpy = %d",
+                  __FUNCTION__, mDpy);
+            ret = false;
+        }
+    }
+    return ret;
+}
+
+//=================FBSrcSplit====================================
+FBSrcSplit::FBSrcSplit(hwc_context_t *ctx, const int& dpy):
+        FBUpdateSplit(ctx, dpy) {}
+
+bool FBSrcSplit::configure(hwc_context_t *ctx, hwc_display_contents_1 *list,
+        hwc_rect_t fbUpdatingRect, int fbZorder) {
+    hwc_layer_1_t *layer = &list->hwLayers[list->numHwLayers - 1];
+    overlay::Overlay& ov = *(ctx->mOverlay);
+
+    ovutils::Whf info(mAlignedFBWidth,
+            mAlignedFBHeight,
+            ovutils::getMdpFormat(HAL_PIXEL_FORMAT_RGBA_8888,
+                mTileEnabled));
+
+    ovutils::eMdpFlags mdpFlags = OV_MDP_BLEND_FG_PREMULT;
+    ovutils::eZorder zOrder = static_cast<ovutils::eZorder>(fbZorder);
+
+    ovutils::PipeArgs parg(mdpFlags,
+            info,
+            zOrder,
+            ovutils::ROT_FLAGS_NONE,
+            ovutils::DEFAULT_PLANE_ALPHA,
+            (ovutils::eBlending)
+            getBlending(layer->blending));
+
+    hwc_rect_t sourceCrop = integerizeSourceCrop(layer->sourceCropf);
+    hwc_rect_t displayFrame = layer->displayFrame;
+
+    // No FB update optimization on (1) Custom FB resolution,
+    // (2) External Mirror mode, (3) External orientation
+    if(!ctx->dpyAttr[mDpy].customFBSize && !ctx->mBufferMirrorMode
+       && !ctx->mExtOrientation) {
+        sourceCrop = fbUpdatingRect;
+        displayFrame = fbUpdatingRect;
+    }
+    int transform = layer->transform;
+    ovutils::eTransform orient =
+            static_cast<ovutils::eTransform>(transform);
+
+    // use ext orientation if any
+    int extOrient = getExtOrientation(ctx);
+
+    // Do not use getNonWormholeRegion() function to calculate the
+    // sourceCrop during animation on external display and
+    // Dont do wormhole calculation when extorientation is set on External
+    // Dont do wormhole calculation when scaling mode is set on External
+    if(ctx->listStats[mDpy].isDisplayAnimating && mDpy) {
+        sourceCrop = layer->displayFrame;
+    } else if((mDpy && !extOrient
+              && !ctx->dpyAttr[mDpy].mMDPScalingMode)) {
+        if(!qdutils::MDPVersion::getInstance().is8x26() &&
+            !ctx->dpyAttr[mDpy].customFBSize) {
+            getNonWormholeRegion(list, sourceCrop);
+            displayFrame = sourceCrop;
+        }
+    }
+
+    calcExtDisplayPosition(ctx, NULL, mDpy, sourceCrop, displayFrame,
+                               transform, orient);
+    hwc_rect_t cropL = sourceCrop;
+    hwc_rect_t cropR = sourceCrop;
+    hwc_rect_t dstL = displayFrame;
+    hwc_rect_t dstR = displayFrame;
+
+    //Request left pipe (or 1 by default)
+    Overlay::PipeSpecs pipeSpecs;
+    pipeSpecs.formatClass = Overlay::FORMAT_RGB;
+    pipeSpecs.needsScaling = qhwc::needsScaling(layer);
+    pipeSpecs.dpy = mDpy;
+    pipeSpecs.mixer = Overlay::MIXER_DEFAULT;
+    pipeSpecs.fb = true;
+    ovutils::eDest destL = ov.getPipe(pipeSpecs);
+    if(destL == ovutils::OV_INVALID) {
+        ALOGE("%s: No pipes available to configure fb for dpy %d's left"
+                " mixer", __FUNCTION__, mDpy);
+        return false;
+    }
+
+    ovutils::eDest destR = ovutils::OV_INVALID;
+
+    /*  Use 2 pipes IF
+        a) FB's width is > Mixer width or
+        b) On primary, driver has indicated with caps to split always. This is
+           based on an empirically derived value of panel height.
+    */
+
+    const bool primarySplitAlways = (mDpy == HWC_DISPLAY_PRIMARY) and
+            qdutils::MDPVersion::getInstance().isSrcSplitAlways();
+    const uint32_t lSplit = getLeftSplit(ctx, mDpy);
+    const uint32_t cropWidth = sourceCrop.right - sourceCrop.left;
+
+    if((cropWidth > qdutils::MDPVersion::getInstance().getMaxMixerWidth()) or
+            (primarySplitAlways and cropWidth > lSplit)) {
+        destR = ov.getPipe(pipeSpecs);
+        if(destR == ovutils::OV_INVALID) {
+            ALOGE("%s: No pipes available to configure fb for dpy %d's right"
+                    " mixer", __FUNCTION__, mDpy);
+            return false;
+        }
+
+        if(ctx->mOverlay->comparePipePriority(destL, destR) == -1) {
+            qhwc::swap(destL, destR);
+        }
+
+        //Split crop equally when using 2 pipes
+        cropL.right = (sourceCrop.right + sourceCrop.left) / 2;
+        cropR.left = cropL.right;
+        dstL.right = (displayFrame.right + displayFrame.left) / 2;
+        dstR.left = dstL.right;
+    }
+
+    mDestLeft = destL;
+    mDestRight = destR;
+
+    if(destL != OV_INVALID) {
+        if(configMdp(ctx->mOverlay, parg, orient,
+                    cropL, dstL, NULL /*metadata*/, destL) < 0) {
+            ALOGE("%s: commit failed for left mixer config", __FUNCTION__);
+            return false;
+        }
+    }
+
+    //configure right pipe
+    if(destR != OV_INVALID) {
+        if(configMdp(ctx->mOverlay, parg, orient,
+                    cropR, dstR, NULL /*metadata*/, destR) < 0) {
+            ALOGE("%s: commit failed for right mixer config", __FUNCTION__);
+            return false;
+        }
+    }
+
+    return true;
+}
+
+//---------------------------------------------------------------------
+}; //namespace qhwc
diff --git a/msm8909/libhwcomposer/hwc_fbupdate.h b/msm8909/libhwcomposer/hwc_fbupdate.h
new file mode 100644
index 0000000..545f5bd
--- /dev/null
+++ b/msm8909/libhwcomposer/hwc_fbupdate.h
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ * Copyright (C) 2012, The Linux Foundation. All rights reserved.
+ *
+ * Not a Contribution, Apache license notifications and license are
+ * retained for attribution purposes only.
+ *
+ * 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 HWC_FBUPDATE_H
+#define HWC_FBUPDATE_H
+#include "hwc_utils.h"
+#include "overlay.h"
+
+#define LIKELY( exp )       (__builtin_expect( (exp) != 0, true  ))
+#define UNLIKELY( exp )     (__builtin_expect( (exp) != 0, false ))
+
+namespace overlay {
+    class Rotator;
+}
+
+namespace qhwc {
+namespace ovutils = overlay::utils;
+
+//Framebuffer update Interface
+class IFBUpdate {
+public:
+    explicit IFBUpdate(hwc_context_t *ctx, const int& dpy);
+    virtual ~IFBUpdate() {};
+    // Sets up members and prepares overlay if conditions are met
+    virtual bool prepare(hwc_context_t *ctx, hwc_display_contents_1 *list,
+            hwc_rect_t fbUpdatingRect, int fbZorder) = 0;
+    virtual bool prepareAndValidate(hwc_context_t *ctx,
+            hwc_display_contents_1 *list, int fbZorder);
+    // Draws layer
+    virtual bool draw(hwc_context_t *ctx, private_handle_t *hnd) = 0;
+    //Reset values
+    virtual void reset();
+    //Factory method that returns a low-res or high-res version
+    static IFBUpdate *getObject(hwc_context_t *ctx, const int& dpy);
+
+protected:
+    const int mDpy; // display to update
+    bool mModeOn; // if prepare happened
+    overlay::Rotator *mRot;
+    int mAlignedFBWidth;
+    int mAlignedFBHeight;
+    int mTileEnabled;
+};
+
+//Non-Split panel handler.
+class FBUpdateNonSplit : public IFBUpdate {
+public:
+    explicit FBUpdateNonSplit(hwc_context_t *ctx, const int& dpy);
+    virtual ~FBUpdateNonSplit() {};
+    bool prepare(hwc_context_t *ctx, hwc_display_contents_1 *list,
+            hwc_rect_t fbUpdatingRect, int fbZorder);
+    bool draw(hwc_context_t *ctx, private_handle_t *hnd);
+    void reset();
+private:
+    bool configure(hwc_context_t *ctx, hwc_display_contents_1 *list,
+            hwc_rect_t fbUpdatingRect, int fbZorder);
+    bool preRotateExtDisplay(hwc_context_t *ctx,
+                                 hwc_layer_1_t *layer,
+                                 ovutils::Whf &info,
+                                 hwc_rect_t& sourceCrop,
+                                 ovutils::eMdpFlags& mdpFlags,
+                                 int& rotFlags);
+    ovutils::eDest mDest; //pipe to draw on
+};
+
+//Split panel handler.
+class FBUpdateSplit : public IFBUpdate {
+public:
+    explicit FBUpdateSplit(hwc_context_t *ctx, const int& dpy);
+    virtual ~FBUpdateSplit() {};
+    bool prepare(hwc_context_t *ctx, hwc_display_contents_1 *list,
+            hwc_rect_t fbUpdatingRect, int fbZorder);
+    bool draw(hwc_context_t *ctx, private_handle_t *hnd);
+    void reset();
+
+protected:
+    virtual bool configure(hwc_context_t *ctx, hwc_display_contents_1 *list,
+            hwc_rect_t fbUpdatingRect, int fbZorder);
+    ovutils::eDest mDestLeft; //left pipe to draw on
+    ovutils::eDest mDestRight; //right pipe to draw on
+};
+
+//Source Split Handler
+class FBSrcSplit : public FBUpdateSplit {
+public:
+    explicit FBSrcSplit(hwc_context_t *ctx, const int& dpy);
+    virtual ~FBSrcSplit() {};
+private:
+    bool configure(hwc_context_t *ctx, hwc_display_contents_1 *list,
+            hwc_rect_t fbUpdatingRect, int fbZorder);
+};
+
+}; //namespace qhwc
+
+#endif //HWC_FBUPDATE_H
diff --git a/msm8909/libhwcomposer/hwc_mdpcomp.cpp b/msm8909/libhwcomposer/hwc_mdpcomp.cpp
new file mode 100644
index 0000000..9f44f32
--- /dev/null
+++ b/msm8909/libhwcomposer/hwc_mdpcomp.cpp
@@ -0,0 +1,2830 @@
+/*
+ * Copyright (C) 2012-2015, The Linux Foundation. All rights reserved.
+ * Not a Contribution, Apache license notifications and license are retained
+ * for attribution purposes only.
+ *
+ * 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 <math.h>
+#include "hwc_mdpcomp.h"
+#include <sys/ioctl.h>
+#include "hdmi.h"
+#include "qdMetaData.h"
+#include "mdp_version.h"
+#include "hwc_fbupdate.h"
+#include "hwc_ad.h"
+#include <overlayRotator.h>
+#include "hwc_copybit.h"
+#include "qd_utils.h"
+
+using namespace overlay;
+using namespace qdutils;
+using namespace overlay::utils;
+namespace ovutils = overlay::utils;
+
+namespace qhwc {
+
+//==============MDPComp========================================================
+
+IdleInvalidator *MDPComp::sIdleInvalidator = NULL;
+bool MDPComp::sIdleFallBack = false;
+bool MDPComp::sDebugLogs = false;
+bool MDPComp::sEnabled = false;
+bool MDPComp::sEnableMixedMode = true;
+int MDPComp::sSimulationFlags = 0;
+int MDPComp::sMaxPipesPerMixer = MAX_PIPES_PER_MIXER;
+bool MDPComp::sEnableYUVsplit = false;
+bool MDPComp::sSrcSplitEnabled = false;
+bool MDPComp::enablePartialUpdateForMDP3 = false;
+bool MDPComp::sIsPartialUpdateActive = true;
+MDPComp* MDPComp::getObject(hwc_context_t *ctx, const int& dpy) {
+    if(qdutils::MDPVersion::getInstance().isSrcSplit()) {
+        sSrcSplitEnabled = true;
+        return new MDPCompSrcSplit(dpy);
+    } else if(isDisplaySplit(ctx, dpy)) {
+        return new MDPCompSplit(dpy);
+    }
+    return new MDPCompNonSplit(dpy);
+}
+
+MDPComp::MDPComp(int dpy) : mDpy(dpy), mModeOn(false), mPrevModeOn(false) {
+};
+
+void MDPComp::dump(android::String8& buf, hwc_context_t *ctx)
+{
+    if(mCurrentFrame.layerCount > MAX_NUM_APP_LAYERS)
+        return;
+
+    dumpsys_log(buf,"HWC Map for Dpy: %s \n",
+                (mDpy == 0) ? "\"PRIMARY\"" :
+                (mDpy == 1) ? "\"EXTERNAL\"" : "\"VIRTUAL\"");
+    dumpsys_log(buf,"CURR_FRAME: layerCount:%2d mdpCount:%2d "
+                "fbCount:%2d \n", mCurrentFrame.layerCount,
+                mCurrentFrame.mdpCount, mCurrentFrame.fbCount);
+    dumpsys_log(buf,"needsFBRedraw:%3s  pipesUsed:%2d  MaxPipesPerMixer: %d \n",
+                (mCurrentFrame.needsRedraw? "YES" : "NO"),
+                mCurrentFrame.mdpCount, sMaxPipesPerMixer);
+    if(isDisplaySplit(ctx, mDpy)) {
+        dumpsys_log(buf, "Programmed ROI's: Left: [%d, %d, %d, %d] "
+                "Right: [%d, %d, %d, %d] \n",
+                ctx->listStats[mDpy].lRoi.left, ctx->listStats[mDpy].lRoi.top,
+                ctx->listStats[mDpy].lRoi.right,
+                ctx->listStats[mDpy].lRoi.bottom,
+                ctx->listStats[mDpy].rRoi.left,ctx->listStats[mDpy].rRoi.top,
+                ctx->listStats[mDpy].rRoi.right,
+                ctx->listStats[mDpy].rRoi.bottom);
+    } else {
+        dumpsys_log(buf, "Programmed ROI: [%d, %d, %d, %d] \n",
+                ctx->listStats[mDpy].lRoi.left,ctx->listStats[mDpy].lRoi.top,
+                ctx->listStats[mDpy].lRoi.right,
+                ctx->listStats[mDpy].lRoi.bottom);
+    }
+    dumpsys_log(buf," ---------------------------------------------  \n");
+    dumpsys_log(buf," listIdx | cached? | mdpIndex | comptype  |  Z  \n");
+    dumpsys_log(buf," ---------------------------------------------  \n");
+    for(int index = 0; index < mCurrentFrame.layerCount; index++ )
+        dumpsys_log(buf," %7d | %7s | %8d | %9s | %2d \n",
+                    index,
+                    (mCurrentFrame.isFBComposed[index] ? "YES" : "NO"),
+                     mCurrentFrame.layerToMDP[index],
+                    (mCurrentFrame.isFBComposed[index] ?
+                    (mCurrentFrame.drop[index] ? "DROP" :
+                    (mCurrentFrame.needsRedraw ? "GLES" : "CACHE")) : "MDP"),
+                    (mCurrentFrame.isFBComposed[index] ? mCurrentFrame.fbZ :
+    mCurrentFrame.mdpToLayer[mCurrentFrame.layerToMDP[index]].pipeInfo->zOrder));
+    dumpsys_log(buf,"\n");
+}
+
+bool MDPComp::init(hwc_context_t *ctx) {
+
+    if(!ctx) {
+        ALOGE("%s: Invalid hwc context!!",__FUNCTION__);
+        return false;
+    }
+
+    char property[PROPERTY_VALUE_MAX] = {0};
+
+    sEnabled = false;
+    if((ctx->mMDP.version >= qdutils::MDP_V4_0) &&
+       (property_get("persist.hwc.mdpcomp.enable", property, NULL) > 0) &&
+       (!strncmp(property, "1", PROPERTY_VALUE_MAX ) ||
+        (!strncasecmp(property,"true", PROPERTY_VALUE_MAX )))) {
+        sEnabled = true;
+    }
+
+    sEnableMixedMode = true;
+    if((property_get("debug.mdpcomp.mixedmode.disable", property, NULL) > 0) &&
+       (!strncmp(property, "1", PROPERTY_VALUE_MAX ) ||
+        (!strncasecmp(property,"true", PROPERTY_VALUE_MAX )))) {
+        sEnableMixedMode = false;
+    }
+
+    sMaxPipesPerMixer = MAX_PIPES_PER_MIXER;
+    if(property_get("debug.mdpcomp.maxpermixer", property, "-1") > 0) {
+        int val = atoi(property);
+        if(val >= 0)
+            sMaxPipesPerMixer = min(val, MAX_PIPES_PER_MIXER);
+    }
+
+    if(ctx->mMDP.panel != MIPI_CMD_PANEL &&
+            (ctx->mMDP.version >= qdutils::MDP_V4_0)) {
+        sIdleInvalidator = IdleInvalidator::getInstance();
+        if(sIdleInvalidator->init(timeout_handler, ctx) < 0) {
+            delete sIdleInvalidator;
+            sIdleInvalidator = NULL;
+        }
+    }
+
+    if(!qdutils::MDPVersion::getInstance().isSrcSplit() &&
+        !qdutils::MDPVersion::getInstance().isRotDownscaleEnabled() &&
+            property_get("persist.mdpcomp.4k2kSplit", property, "0") > 0 &&
+            (!strncmp(property, "1", PROPERTY_VALUE_MAX) ||
+            !strncasecmp(property,"true", PROPERTY_VALUE_MAX))) {
+        sEnableYUVsplit = true;
+    }
+
+    bool defaultPTOR = false;
+    //Enable PTOR when "persist.hwc.ptor.enable" is not defined for
+    //8x16 and 8x39 targets by default
+    if((property_get("persist.hwc.ptor.enable", property, NULL) <= 0) &&
+            (qdutils::MDPVersion::getInstance().is8x16() ||
+                qdutils::MDPVersion::getInstance().is8x39())) {
+        defaultPTOR = true;
+    }
+
+    if (defaultPTOR || (!strncasecmp(property, "true", PROPERTY_VALUE_MAX)) ||
+                (!strncmp(property, "1", PROPERTY_VALUE_MAX ))) {
+        ctx->mCopyBit[HWC_DISPLAY_PRIMARY] = new CopyBit(ctx,
+                                                    HWC_DISPLAY_PRIMARY);
+    }
+
+    if((property_get("persist.mdp3.partialUpdate", property, NULL) <= 0) &&
+          (ctx->mMDP.version == qdutils::MDP_V3_0_5)) {
+       enablePartialUpdateForMDP3 = true;
+    }
+
+    if(!enablePartialUpdateForMDP3 &&
+          (!strncmp(property, "1", PROPERTY_VALUE_MAX ) ||
+           (!strncasecmp(property,"true", PROPERTY_VALUE_MAX )))) {
+       enablePartialUpdateForMDP3 = true;
+    }
+
+    int retPartialUpdatePref = getPartialUpdatePref(ctx);
+    if(retPartialUpdatePref >= 0)
+       sIsPartialUpdateActive = (retPartialUpdatePref != 0);
+
+    return true;
+}
+
+void MDPComp::reset(hwc_context_t *ctx) {
+    const int numLayers = ctx->listStats[mDpy].numAppLayers;
+    mCurrentFrame.reset(numLayers);
+    ctx->mOverlay->clear(mDpy);
+    ctx->mLayerRotMap[mDpy]->clear();
+    resetROI(ctx, mDpy);
+    memset(&mCurrentFrame.drop, 0, sizeof(mCurrentFrame.drop));
+    mCurrentFrame.dropCount = 0;
+}
+
+void MDPComp::reset() {
+    mPrevModeOn = mModeOn;
+    mModeOn = false;
+}
+
+void MDPComp::timeout_handler(void *udata) {
+    struct hwc_context_t* ctx = (struct hwc_context_t*)(udata);
+    bool handleTimeout = false;
+
+    if(!ctx) {
+        ALOGE("%s: received empty data in timer callback", __FUNCTION__);
+        return;
+    }
+
+    ctx->mDrawLock.lock();
+
+    /* Handle timeout event only if the previous composition
+       on any display is MDP or MIXED*/
+    for(int i = 0; i < HWC_NUM_DISPLAY_TYPES; i++) {
+        if(ctx->mMDPComp[i])
+            handleTimeout =
+                    ctx->mMDPComp[i]->isMDPComp() || handleTimeout;
+    }
+
+    if(!handleTimeout) {
+        ALOGD_IF(isDebug(), "%s:Do not handle this timeout", __FUNCTION__);
+        ctx->mDrawLock.unlock();
+        return;
+    }
+    if(!ctx->proc) {
+        ALOGE("%s: HWC proc not registered", __FUNCTION__);
+        ctx->mDrawLock.unlock();
+        return;
+    }
+    sIdleFallBack = true;
+    ctx->mDrawLock.unlock();
+    /* Trigger SF to redraw the current frame */
+    ctx->proc->invalidate(ctx->proc);
+}
+
+void MDPComp::setIdleTimeout(const uint32_t& timeout) {
+    enum { ONE_REFRESH_PERIOD_MS = 17, ONE_BILLION_MS = 1000000000 };
+
+    if(sIdleInvalidator) {
+        if(timeout <= ONE_REFRESH_PERIOD_MS) {
+            //If the specified timeout is < 1 draw cycle worth, "virtually"
+            //disable idle timeout. The ideal way for clients to disable
+            //timeout is to set it to 0
+            sIdleInvalidator->setIdleTimeout(ONE_BILLION_MS);
+            ALOGI("Disabled idle timeout");
+            return;
+        }
+        sIdleInvalidator->setIdleTimeout(timeout);
+        ALOGI("Idle timeout set to %u", timeout);
+    } else {
+        ALOGW("Cannot set idle timeout, IdleInvalidator not enabled");
+    }
+}
+
+void MDPComp::setMDPCompLayerFlags(hwc_context_t *ctx,
+                                   hwc_display_contents_1_t* list) {
+    LayerProp *layerProp = ctx->layerProp[mDpy];
+
+    for(int index = 0; index < ctx->listStats[mDpy].numAppLayers; index++) {
+        hwc_layer_1_t* layer = &(list->hwLayers[index]);
+        if(!mCurrentFrame.isFBComposed[index]) {
+            layerProp[index].mFlags |= HWC_MDPCOMP;
+            layer->compositionType = HWC_OVERLAY;
+            layer->hints |= HWC_HINT_CLEAR_FB;
+        } else {
+            /* Drop the layer when its already present in FB OR when it lies
+             * outside frame's ROI */
+            if(!mCurrentFrame.needsRedraw || mCurrentFrame.drop[index]) {
+                layer->compositionType = HWC_OVERLAY;
+            }
+        }
+    }
+}
+
+void MDPComp::setRedraw(hwc_context_t *ctx,
+        hwc_display_contents_1_t* list) {
+    mCurrentFrame.needsRedraw = false;
+    if(!mCachedFrame.isSameFrame(mCurrentFrame, list) ||
+            (list->flags & HWC_GEOMETRY_CHANGED) ||
+            isSkipPresent(ctx, mDpy)) {
+        mCurrentFrame.needsRedraw = true;
+    }
+}
+
+MDPComp::FrameInfo::FrameInfo() {
+    memset(&mdpToLayer, 0, sizeof(mdpToLayer));
+    reset(0);
+}
+
+void MDPComp::FrameInfo::reset(const int& numLayers) {
+    for(int i = 0; i < MAX_PIPES_PER_MIXER; i++) {
+        if(mdpToLayer[i].pipeInfo) {
+            delete mdpToLayer[i].pipeInfo;
+            mdpToLayer[i].pipeInfo = NULL;
+            //We dont own the rotator
+            mdpToLayer[i].rot = NULL;
+        }
+    }
+
+    memset(&mdpToLayer, 0, sizeof(mdpToLayer));
+    memset(&layerToMDP, -1, sizeof(layerToMDP));
+    memset(&isFBComposed, 1, sizeof(isFBComposed));
+
+    layerCount = numLayers;
+    fbCount = numLayers;
+    mdpCount = 0;
+    needsRedraw = true;
+    fbZ = -1;
+}
+
+void MDPComp::FrameInfo::map() {
+    // populate layer and MDP maps
+    int mdpIdx = 0;
+    for(int idx = 0; idx < layerCount; idx++) {
+        if(!isFBComposed[idx]) {
+            mdpToLayer[mdpIdx].listIndex = idx;
+            layerToMDP[idx] = mdpIdx++;
+        }
+    }
+}
+
+MDPComp::LayerCache::LayerCache() {
+    reset();
+}
+
+void MDPComp::LayerCache::reset() {
+    memset(&isFBComposed, true, sizeof(isFBComposed));
+    memset(&drop, false, sizeof(drop));
+    layerCount = 0;
+}
+
+void MDPComp::LayerCache::updateCounts(const FrameInfo& curFrame) {
+    layerCount = curFrame.layerCount;
+    memcpy(&isFBComposed, &curFrame.isFBComposed, sizeof(isFBComposed));
+    memcpy(&drop, &curFrame.drop, sizeof(drop));
+}
+
+bool MDPComp::LayerCache::isSameFrame(const FrameInfo& curFrame,
+                                      hwc_display_contents_1_t* list) {
+    if(layerCount != curFrame.layerCount)
+        return false;
+    for(int i = 0; i < curFrame.layerCount; i++) {
+        if((curFrame.isFBComposed[i] != isFBComposed[i]) ||
+                (curFrame.drop[i] != drop[i])) {
+            return false;
+        }
+        hwc_layer_1_t const* layer = &list->hwLayers[i];
+        if(curFrame.isFBComposed[i] && layerUpdating(layer)) {
+            return false;
+        }
+    }
+    return true;
+}
+
+bool MDPComp::LayerCache::isSameFrame(hwc_context_t *ctx, int dpy,
+                                      hwc_display_contents_1_t* list) {
+
+    if(layerCount != ctx->listStats[dpy].numAppLayers)
+        return false;
+
+    if((list->flags & HWC_GEOMETRY_CHANGED) ||
+       isSkipPresent(ctx, dpy)) {
+        return false;
+    }
+
+    for(int i = 0; i < layerCount; i++) {
+        hwc_layer_1_t const* layer = &list->hwLayers[i];
+        if(layerUpdating(layer))
+            return false;
+    }
+
+    return true;
+}
+
+bool MDPComp::isSupportedForMDPComp(hwc_context_t *ctx, hwc_layer_1_t* layer) {
+    private_handle_t *hnd = (private_handle_t *)layer->handle;
+    if((has90Transform(layer) and (not isRotationDoable(ctx, hnd))) ||
+        (not isValidDimension(ctx,layer)) ||
+        isSkipLayer(layer)) {
+        //More conditions here, sRGB+Blend etc
+        return false;
+    }
+    return true;
+}
+
+bool MDPComp::isValidDimension(hwc_context_t *ctx, hwc_layer_1_t *layer) {
+    private_handle_t *hnd = (private_handle_t *)layer->handle;
+
+    if(!hnd) {
+        if (layer->flags & HWC_COLOR_FILL) {
+            // Color layer
+            return true;
+        }
+        ALOGD_IF(isDebug(), "%s: layer handle is NULL", __FUNCTION__);
+        return false;
+    }
+
+    //XXX: Investigate doing this with pixel phase on MDSS
+    if(!isSecureBuffer(hnd) && isNonIntegralSourceCrop(layer->sourceCropf))
+        return false;
+
+    hwc_rect_t crop = integerizeSourceCrop(layer->sourceCropf);
+    hwc_rect_t dst = layer->displayFrame;
+    bool rotated90 = (bool)(layer->transform & HAL_TRANSFORM_ROT_90);
+    int crop_w = rotated90 ? crop.bottom - crop.top : crop.right - crop.left;
+    int crop_h = rotated90 ? crop.right - crop.left : crop.bottom - crop.top;
+    int dst_w = dst.right - dst.left;
+    int dst_h = dst.bottom - dst.top;
+    float w_scale = ((float)crop_w / (float)dst_w);
+    float h_scale = ((float)crop_h / (float)dst_h);
+    MDPVersion& mdpHw = MDPVersion::getInstance();
+
+    /* Workaround for MDP HW limitation in DSI command mode panels where
+     * FPS will not go beyond 30 if buffers on RGB pipes are of width or height
+     * less than 5 pixels
+     * There also is a HW limilation in MDP, minimum block size is 2x2
+     * Fallback to GPU if height is less than 2.
+     */
+    if(mdpHw.hasMinCropWidthLimitation() and (crop_w < 5 or crop_h < 5))
+        return false;
+
+    if((w_scale > 1.0f) || (h_scale > 1.0f)) {
+        const uint32_t maxMDPDownscale = mdpHw.getMaxMDPDownscale();
+        const float w_dscale = w_scale;
+        const float h_dscale = h_scale;
+
+        if(ctx->mMDP.version >= qdutils::MDSS_V5) {
+
+            if(!mdpHw.supportsDecimation()) {
+                /* On targets that doesnt support Decimation (eg.,8x26)
+                 * maximum downscale support is overlay pipe downscale.
+                 */
+                if(crop_w > (int) mdpHw.getMaxMixerWidth() ||
+                        w_dscale > maxMDPDownscale ||
+                        h_dscale > maxMDPDownscale)
+                    return false;
+            } else {
+                // Decimation on macrotile format layers is not supported.
+                if(isTileRendered(hnd)) {
+                    /* Bail out if
+                     *      1. Src crop > Mixer limit on nonsplit MDPComp
+                     *      2. exceeds maximum downscale limit
+                     */
+                    if(((crop_w > (int) mdpHw.getMaxMixerWidth()) &&
+                                !sSrcSplitEnabled) ||
+                            w_dscale > maxMDPDownscale ||
+                            h_dscale > maxMDPDownscale) {
+                        return false;
+                    }
+                } else if(w_dscale > 64 || h_dscale > 64)
+                    return false;
+            }
+        } else { //A-family
+            if(w_dscale > maxMDPDownscale || h_dscale > maxMDPDownscale)
+                return false;
+        }
+    }
+
+    if((w_scale < 1.0f) || (h_scale < 1.0f)) {
+        const uint32_t upscale = mdpHw.getMaxMDPUpscale();
+        const float w_uscale = 1.0f / w_scale;
+        const float h_uscale = 1.0f / h_scale;
+
+        if(w_uscale > upscale || h_uscale > upscale)
+            return false;
+    }
+
+    return true;
+}
+
+bool MDPComp::isFrameDoable(hwc_context_t *ctx) {
+    bool ret = true;
+
+    if(!isEnabled()) {
+        ALOGD_IF(isDebug(),"%s: MDP Comp. not enabled.", __FUNCTION__);
+        ret = false;
+    } else if((qdutils::MDPVersion::getInstance().is8x26() ||
+               qdutils::MDPVersion::getInstance().is8x16() ||
+               qdutils::MDPVersion::getInstance().is8x39()) &&
+            ctx->mVideoTransFlag &&
+            isSecondaryConnected(ctx)) {
+        //1 Padding round to shift pipes across mixers
+        ALOGD_IF(isDebug(),"%s: MDP Comp. video transition padding round",
+                __FUNCTION__);
+        ret = false;
+    } else if((qdutils::MDPVersion::getInstance().is8x26() ||
+               qdutils::MDPVersion::getInstance().is8x16() ||
+               qdutils::MDPVersion::getInstance().is8x39()) &&
+              !mDpy && isSecondaryAnimating(ctx) &&
+              isYuvPresent(ctx,HWC_DISPLAY_VIRTUAL)) {
+        ALOGD_IF(isDebug(),"%s: Display animation in progress",
+                 __FUNCTION__);
+        ret = false;
+    } else if(qdutils::MDPVersion::getInstance().getTotalPipes() < 8) {
+       /* TODO: freeing up all the resources only for the targets having total
+                number of pipes < 8. Need to analyze number of VIG pipes used
+                for primary in previous draw cycle and accordingly decide
+                whether to fall back to full GPU comp or video only comp
+        */
+        if(isSecondaryConfiguring(ctx)) {
+            ALOGD_IF( isDebug(),"%s: External Display connection is pending",
+                      __FUNCTION__);
+            ret = false;
+        } else if(ctx->isPaddingRound) {
+            ALOGD_IF(isDebug(), "%s: padding round invoked for dpy %d",
+                     __FUNCTION__,mDpy);
+            ret = false;
+        }
+    }
+    return ret;
+}
+
+void MDPCompNonSplit::trimAgainstROI(hwc_context_t *ctx, hwc_rect_t& fbRect) {
+    hwc_rect_t roi = ctx->listStats[mDpy].lRoi;
+    fbRect = getIntersection(fbRect, roi);
+}
+
+/* 1) Identify layers that are not visible or lying outside the updating ROI and
+ *    drop them from composition.
+ * 2) If we have a scaling layer which needs cropping against generated
+ *    ROI, reset ROI to full resolution. */
+bool MDPCompNonSplit::validateAndApplyROI(hwc_context_t *ctx,
+        hwc_display_contents_1_t* list) {
+    int numAppLayers = ctx->listStats[mDpy].numAppLayers;
+    hwc_rect_t visibleRect = ctx->listStats[mDpy].lRoi;
+
+    for(int i = numAppLayers - 1; i >= 0; i--){
+        if(!isValidRect(visibleRect)) {
+            mCurrentFrame.drop[i] = true;
+            mCurrentFrame.dropCount++;
+            continue;
+        }
+
+        const hwc_layer_1_t* layer =  &list->hwLayers[i];
+        hwc_rect_t dstRect = layer->displayFrame;
+        hwc_rect_t res  = getIntersection(visibleRect, dstRect);
+
+        if(!isValidRect(res)) {
+            mCurrentFrame.drop[i] = true;
+            mCurrentFrame.dropCount++;
+        } else {
+            /* Reset frame ROI when any layer which needs scaling also needs ROI
+             * cropping */
+            if(!isSameRect(res, dstRect) && needsScaling (layer)) {
+                ALOGI("%s: Resetting ROI due to scaling", __FUNCTION__);
+                memset(&mCurrentFrame.drop, 0, sizeof(mCurrentFrame.drop));
+                mCurrentFrame.dropCount = 0;
+                return false;
+            }
+
+            /* deduct any opaque region from visibleRect */
+            if (layer->blending == HWC_BLENDING_NONE &&
+                    layer->planeAlpha == 0xFF)
+                visibleRect = deductRect(visibleRect, res);
+        }
+    }
+    return true;
+}
+
+/* Calculate ROI for the frame by accounting all the layer's dispalyFrame which
+ * are updating. If DirtyRegion is applicable, calculate it by accounting all
+ * the changing layer's dirtyRegion. */
+void MDPCompNonSplit::generateROI(hwc_context_t *ctx,
+        hwc_display_contents_1_t* list) {
+    int numAppLayers = ctx->listStats[mDpy].numAppLayers;
+    if(!canPartialUpdate(ctx, list))
+        return;
+
+    struct hwc_rect roi = (struct hwc_rect){0, 0, 0, 0};
+    hwc_rect fullFrame = (struct hwc_rect) {0, 0,(int)ctx->dpyAttr[mDpy].xres,
+        (int)ctx->dpyAttr[mDpy].yres};
+
+    for(int index = 0; index < numAppLayers; index++ ) {
+        hwc_layer_1_t* layer = &list->hwLayers[index];
+        if (layerUpdating(layer) ||
+                isYuvBuffer((private_handle_t *)layer->handle)) {
+            hwc_rect_t dirtyRect = (struct hwc_rect){0, 0, 0, 0};;
+            if(!needsScaling(layer) && !layer->transform &&
+                   (!isYuvBuffer((private_handle_t *)layer->handle)))
+            {
+                dirtyRect = calculateDirtyRect(layer, fullFrame);
+            }
+
+            roi = getUnion(roi, dirtyRect);
+        }
+    }
+
+    /* No layer is updating. Still SF wants a refresh.*/
+    if(!isValidRect(roi))
+        return;
+
+    // Align ROI coordinates to panel restrictions
+    roi = getSanitizeROI(roi, fullFrame);
+
+    ctx->listStats[mDpy].lRoi = roi;
+    if(!validateAndApplyROI(ctx, list))
+        resetROI(ctx, mDpy);
+
+    ALOGD_IF(isDebug(),"%s: generated ROI: [%d, %d, %d, %d]", __FUNCTION__,
+            ctx->listStats[mDpy].lRoi.left, ctx->listStats[mDpy].lRoi.top,
+            ctx->listStats[mDpy].lRoi.right, ctx->listStats[mDpy].lRoi.bottom);
+}
+
+void MDPCompSplit::trimAgainstROI(hwc_context_t *ctx, hwc_rect_t& fbRect) {
+    hwc_rect l_roi = ctx->listStats[mDpy].lRoi;
+    hwc_rect r_roi = ctx->listStats[mDpy].rRoi;
+
+    hwc_rect_t l_fbRect = getIntersection(fbRect, l_roi);
+    hwc_rect_t r_fbRect = getIntersection(fbRect, r_roi);
+    fbRect = getUnion(l_fbRect, r_fbRect);
+}
+/* 1) Identify layers that are not visible or lying outside BOTH the updating
+ *    ROI's and drop them from composition. If a layer is spanning across both
+ *    the halves of the screen but needed by only ROI, the non-contributing
+ *    half will not be programmed for MDP.
+ * 2) If we have a scaling layer which needs cropping against generated
+ *    ROI, reset ROI to full resolution. */
+bool MDPCompSplit::validateAndApplyROI(hwc_context_t *ctx,
+        hwc_display_contents_1_t* list) {
+
+    int numAppLayers = ctx->listStats[mDpy].numAppLayers;
+
+    hwc_rect_t visibleRectL = ctx->listStats[mDpy].lRoi;
+    hwc_rect_t visibleRectR = ctx->listStats[mDpy].rRoi;
+
+    for(int i = numAppLayers - 1; i >= 0; i--){
+        if(!isValidRect(visibleRectL) && !isValidRect(visibleRectR))
+        {
+            mCurrentFrame.drop[i] = true;
+            mCurrentFrame.dropCount++;
+            continue;
+        }
+
+        const hwc_layer_1_t* layer =  &list->hwLayers[i];
+        hwc_rect_t dstRect = layer->displayFrame;
+
+        hwc_rect_t l_res  = getIntersection(visibleRectL, dstRect);
+        hwc_rect_t r_res  = getIntersection(visibleRectR, dstRect);
+        hwc_rect_t res = getUnion(l_res, r_res);
+
+        if(!isValidRect(l_res) && !isValidRect(r_res)) {
+            mCurrentFrame.drop[i] = true;
+            mCurrentFrame.dropCount++;
+        } else {
+            /* Reset frame ROI when any layer which needs scaling also needs ROI
+             * cropping */
+            if(!isSameRect(res, dstRect) && needsScaling (layer)) {
+                memset(&mCurrentFrame.drop, 0, sizeof(mCurrentFrame.drop));
+                mCurrentFrame.dropCount = 0;
+                return false;
+            }
+
+            if (layer->blending == HWC_BLENDING_NONE &&
+                    layer->planeAlpha == 0xFF) {
+                visibleRectL = deductRect(visibleRectL, l_res);
+                visibleRectR = deductRect(visibleRectR, r_res);
+            }
+        }
+    }
+    return true;
+}
+/* Calculate ROI for the frame by accounting all the layer's dispalyFrame which
+ * are updating. If DirtyRegion is applicable, calculate it by accounting all
+ * the changing layer's dirtyRegion. */
+void MDPCompSplit::generateROI(hwc_context_t *ctx,
+        hwc_display_contents_1_t* list) {
+    if(!canPartialUpdate(ctx, list))
+        return;
+
+    int numAppLayers = ctx->listStats[mDpy].numAppLayers;
+    int lSplit = getLeftSplit(ctx, mDpy);
+
+    int hw_h = (int)ctx->dpyAttr[mDpy].yres;
+    int hw_w = (int)ctx->dpyAttr[mDpy].xres;
+
+    struct hwc_rect l_frame = (struct hwc_rect){0, 0, lSplit, hw_h};
+    struct hwc_rect r_frame = (struct hwc_rect){lSplit, 0, hw_w, hw_h};
+
+    struct hwc_rect l_roi = (struct hwc_rect){0, 0, 0, 0};
+    struct hwc_rect r_roi = (struct hwc_rect){0, 0, 0, 0};
+
+    for(int index = 0; index < numAppLayers; index++ ) {
+        hwc_layer_1_t* layer = &list->hwLayers[index];
+        private_handle_t *hnd = (private_handle_t *)layer->handle;
+        if (layerUpdating(layer) || isYuvBuffer(hnd)) {
+            hwc_rect_t l_dirtyRect = (struct hwc_rect){0, 0, 0, 0};
+            hwc_rect_t r_dirtyRect = (struct hwc_rect){0, 0, 0, 0};
+            if(!needsScaling(layer) && !layer->transform)
+            {
+                l_dirtyRect = calculateDirtyRect(layer, l_frame);
+                r_dirtyRect = calculateDirtyRect(layer, r_frame);
+            }
+            if(isValidRect(l_dirtyRect))
+                l_roi = getUnion(l_roi, l_dirtyRect);
+
+            if(isValidRect(r_dirtyRect))
+                r_roi = getUnion(r_roi, r_dirtyRect);
+        }
+    }
+
+    /* For panels that cannot accept commands in both the interfaces, we cannot
+     * send two ROI's (for each half). We merge them into single ROI and split
+     * them across lSplit for MDP mixer use. The ROI's will be merged again
+     * finally before udpating the panel in the driver. */
+    if(qdutils::MDPVersion::getInstance().needsROIMerge()) {
+        hwc_rect_t temp_roi = getUnion(l_roi, r_roi);
+        l_roi = getIntersection(temp_roi, l_frame);
+        r_roi = getIntersection(temp_roi, r_frame);
+    }
+
+    /* No layer is updating. Still SF wants a refresh. */
+    if(!isValidRect(l_roi) && !isValidRect(r_roi))
+        return;
+
+    l_roi = getSanitizeROI(l_roi, l_frame);
+    r_roi = getSanitizeROI(r_roi, r_frame);
+
+    ctx->listStats[mDpy].lRoi = l_roi;
+    ctx->listStats[mDpy].rRoi = r_roi;
+
+    if(!validateAndApplyROI(ctx, list))
+        resetROI(ctx, mDpy);
+
+    ALOGD_IF(isDebug(),"%s: generated L_ROI: [%d, %d, %d, %d]"
+            "R_ROI: [%d, %d, %d, %d]", __FUNCTION__,
+            ctx->listStats[mDpy].lRoi.left, ctx->listStats[mDpy].lRoi.top,
+            ctx->listStats[mDpy].lRoi.right, ctx->listStats[mDpy].lRoi.bottom,
+            ctx->listStats[mDpy].rRoi.left, ctx->listStats[mDpy].rRoi.top,
+            ctx->listStats[mDpy].rRoi.right, ctx->listStats[mDpy].rRoi.bottom);
+}
+
+/* Checks for conditions where all the layers marked for MDP comp cannot be
+ * bypassed. On such conditions we try to bypass atleast YUV layers */
+bool MDPComp::tryFullFrame(hwc_context_t *ctx,
+                                hwc_display_contents_1_t* list){
+
+    const int numAppLayers = ctx->listStats[mDpy].numAppLayers;
+    int priDispW = ctx->dpyAttr[HWC_DISPLAY_PRIMARY].xres;
+
+    // Fall back to video only composition, if AIV video mode is enabled
+    if(ctx->listStats[mDpy].mAIVVideoMode) {
+        ALOGD_IF(isDebug(), "%s: AIV Video Mode enabled dpy %d",
+            __FUNCTION__, mDpy);
+        return false;
+    }
+
+    // No Idle fall back, if secure display or secure RGB layers are present or
+    // if there's only a single layer being composed
+    if(sIdleFallBack && (!ctx->listStats[mDpy].secureUI &&
+                    !ctx->listStats[mDpy].secureRGBCount) &&
+                    (ctx->listStats[mDpy].numAppLayers != 1)) {
+        ALOGD_IF(isDebug(), "%s: Idle fallback dpy %d",__FUNCTION__, mDpy);
+        return false;
+    }
+
+    if(!mDpy && isSecondaryAnimating(ctx) &&
+       (isYuvPresent(ctx,HWC_DISPLAY_EXTERNAL) ||
+       isYuvPresent(ctx,HWC_DISPLAY_VIRTUAL)) ) {
+        ALOGD_IF(isDebug(),"%s: Display animation in progress",
+                 __FUNCTION__);
+        return false;
+    }
+
+    // if secondary is configuring or Padding round, fall back to video only
+    // composition and release all assigned non VIG pipes from primary.
+    if(isSecondaryConfiguring(ctx)) {
+        ALOGD_IF( isDebug(),"%s: External Display connection is pending",
+                  __FUNCTION__);
+        return false;
+    } else if(ctx->isPaddingRound) {
+        ALOGD_IF(isDebug(), "%s: padding round invoked for dpy %d",
+                 __FUNCTION__,mDpy);
+        return false;
+    }
+
+    MDPVersion& mdpHw = MDPVersion::getInstance();
+    if(mDpy > HWC_DISPLAY_PRIMARY &&
+            (priDispW >  (int) mdpHw.getMaxMixerWidth()) &&
+            (ctx->dpyAttr[mDpy].xres <  mdpHw.getMaxMixerWidth())) {
+        // Disable MDP comp on Secondary when the primary is highres panel and
+        // the secondary is a normal 1080p, because, MDP comp on secondary under
+        // in such usecase, decimation gets used for downscale and there will be
+        // a quality mismatch when there will be a fallback to GPU comp
+        ALOGD_IF(isDebug(), "%s: Disable MDP Compositon for Secondary Disp",
+              __FUNCTION__);
+        return false;
+    }
+
+    // check for action safe flag and MDP scaling mode which requires scaling.
+    if(ctx->dpyAttr[mDpy].mActionSafePresent
+            || ctx->dpyAttr[mDpy].mMDPScalingMode) {
+        ALOGD_IF(isDebug(), "%s: Scaling needed for this frame",__FUNCTION__);
+        return false;
+    }
+
+    for(int i = 0; i < numAppLayers; ++i) {
+        hwc_layer_1_t* layer = &list->hwLayers[i];
+        private_handle_t *hnd = (private_handle_t *)layer->handle;
+
+        if(has90Transform(layer) && isRotationDoable(ctx, hnd)) {
+            if(!canUseRotator(ctx, mDpy)) {
+                ALOGD_IF(isDebug(), "%s: Can't use rotator for dpy %d",
+                        __FUNCTION__, mDpy);
+                return false;
+            }
+        }
+
+        //For 8x26 with panel width>1k, if RGB layer needs HFLIP fail mdp comp
+        // may not need it if Gfx pre-rotation can handle all flips & rotations
+        int transform = (layer->flags & HWC_COLOR_FILL) ? 0 : layer->transform;
+        if( mdpHw.is8x26() && (ctx->dpyAttr[mDpy].xres > 1024) &&
+                (transform & HWC_TRANSFORM_FLIP_H) && (!isYuvBuffer(hnd)))
+            return false;
+    }
+
+    if(ctx->mAD->isDoable()) {
+        return false;
+    }
+
+    //If all above hard conditions are met we can do full or partial MDP comp.
+    bool ret = false;
+    if(fullMDPComp(ctx, list)) {
+        ret = true;
+    } else if(fullMDPCompWithPTOR(ctx, list)) {
+        ret = true;
+    } else if(partialMDPComp(ctx, list)) {
+        ret = true;
+    }
+
+    return ret;
+}
+
+bool MDPComp::fullMDPComp(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
+
+    if(sSimulationFlags & MDPCOMP_AVOID_FULL_MDP)
+        return false;
+
+    //Will benefit presentation / secondary-only layer.
+    if((mDpy > HWC_DISPLAY_PRIMARY) &&
+            (list->numHwLayers - 1) > MAX_SEC_LAYERS) {
+        ALOGD_IF(isDebug(), "%s: Exceeds max secondary pipes",__FUNCTION__);
+        return false;
+    }
+
+    const int numAppLayers = ctx->listStats[mDpy].numAppLayers;
+    for(int i = 0; i < numAppLayers; i++) {
+        hwc_layer_1_t* layer = &list->hwLayers[i];
+        if(not mCurrentFrame.drop[i] and
+           not isSupportedForMDPComp(ctx, layer)) {
+            ALOGD_IF(isDebug(), "%s: Unsupported layer in list",__FUNCTION__);
+            return false;
+        }
+    }
+
+    if(!mDpy && isSecondaryConnected(ctx) &&
+           (qdutils::MDPVersion::getInstance().is8x16() ||
+            qdutils::MDPVersion::getInstance().is8x26() ||
+            qdutils::MDPVersion::getInstance().is8x39()) &&
+           isYuvPresent(ctx, HWC_DISPLAY_VIRTUAL)) {
+        ALOGD_IF(isDebug(), "%s: YUV layer present on secondary", __FUNCTION__);
+        return false;
+    }
+
+    mCurrentFrame.fbCount = 0;
+    memcpy(&mCurrentFrame.isFBComposed, &mCurrentFrame.drop,
+           sizeof(mCurrentFrame.isFBComposed));
+    mCurrentFrame.mdpCount = mCurrentFrame.layerCount - mCurrentFrame.fbCount -
+        mCurrentFrame.dropCount;
+
+    if(sEnableYUVsplit){
+        adjustForSourceSplit(ctx, list);
+    }
+
+    if(!postHeuristicsHandling(ctx, list)) {
+        ALOGD_IF(isDebug(), "post heuristic handling failed");
+        reset(ctx);
+        return false;
+    }
+    ALOGD_IF(sSimulationFlags,"%s: FULL_MDP_COMP SUCCEEDED",
+             __FUNCTION__);
+    return true;
+}
+
+/* Full MDP Composition with Peripheral Tiny Overlap Removal.
+ * MDP bandwidth limitations can be avoided, if the overlap region
+ * covered by the smallest layer at a higher z-order, gets composed
+ * by Copybit on a render buffer, which can be queued to MDP.
+ */
+bool MDPComp::fullMDPCompWithPTOR(hwc_context_t *ctx,
+    hwc_display_contents_1_t* list) {
+
+    const int numAppLayers = ctx->listStats[mDpy].numAppLayers;
+    const int stagesForMDP = min(sMaxPipesPerMixer,
+            ctx->mOverlay->availablePipes(mDpy, Overlay::MIXER_DEFAULT));
+
+    // Hard checks where we cannot use this mode
+    if (mDpy || !ctx->mCopyBit[mDpy]) {
+        ALOGD_IF(isDebug(), "%s: Feature not supported!", __FUNCTION__);
+        return false;
+    }
+
+    // Frame level checks
+    if ((numAppLayers > stagesForMDP) || isSkipPresent(ctx, mDpy) ||
+        isYuvPresent(ctx, mDpy) || mCurrentFrame.dropCount ||
+        isSecurePresent(ctx, mDpy)) {
+        ALOGD_IF(isDebug(), "%s: Frame not supported!", __FUNCTION__);
+        return false;
+    }
+    // MDP comp checks
+    for(int i = 0; i < numAppLayers; i++) {
+        hwc_layer_1_t* layer = &list->hwLayers[i];
+        if(not isSupportedForMDPComp(ctx, layer)) {
+            ALOGD_IF(isDebug(), "%s: Unsupported layer in list",__FUNCTION__);
+            return false;
+        }
+    }
+
+    if(!mDpy && isSecondaryConnected(ctx) &&
+           (qdutils::MDPVersion::getInstance().is8x16() ||
+            qdutils::MDPVersion::getInstance().is8x26() ||
+            qdutils::MDPVersion::getInstance().is8x39()) &&
+           isYuvPresent(ctx, HWC_DISPLAY_VIRTUAL)) {
+        ALOGD_IF(isDebug(), "%s: YUV layer present on secondary", __FUNCTION__);
+        return false;
+    }
+
+    /* We cannot use this composition mode, if:
+     1. A below layer needs scaling.
+     2. Overlap is not peripheral to display.
+     3. Overlap or a below layer has 90 degree transform.
+     4. Overlap area > (1/3 * FrameBuffer) area, based on Perf inputs.
+     */
+
+    int minLayerIndex[MAX_PTOR_LAYERS] = { -1, -1};
+    hwc_rect_t overlapRect[MAX_PTOR_LAYERS];
+    memset(overlapRect, 0, sizeof(overlapRect));
+    int layerPixelCount, minPixelCount = 0;
+    int numPTORLayersFound = 0;
+    for (int i = numAppLayers-1; (i >= 0 &&
+                                  numPTORLayersFound < MAX_PTOR_LAYERS); i--) {
+        hwc_layer_1_t* layer = &list->hwLayers[i];
+        hwc_rect_t crop = integerizeSourceCrop(layer->sourceCropf);
+        hwc_rect_t dispFrame = layer->displayFrame;
+        layerPixelCount = (crop.right - crop.left) * (crop.bottom - crop.top);
+        // PTOR layer should be peripheral and cannot have transform
+        if (!isPeripheral(dispFrame, ctx->mViewFrame[mDpy]) ||
+                                has90Transform(layer)) {
+            continue;
+        }
+        if((3 * (layerPixelCount + minPixelCount)) >
+                ((int)ctx->dpyAttr[mDpy].xres * (int)ctx->dpyAttr[mDpy].yres)) {
+            // Overlap area > (1/3 * FrameBuffer) area, based on Perf inputs.
+            continue;
+        }
+        bool found = false;
+        for (int j = i-1; j >= 0; j--) {
+            // Check if the layers below this layer qualifies for PTOR comp
+            hwc_layer_1_t* layer = &list->hwLayers[j];
+            hwc_rect_t disFrame = layer->displayFrame;
+            // Layer below PTOR is intersecting and has 90 degree transform or
+            // needs scaling cannot be supported.
+            if (isValidRect(getIntersection(dispFrame, disFrame))) {
+                if (has90Transform(layer) || needsScaling(layer)) {
+                    found = false;
+                    break;
+                }
+                found = true;
+            }
+        }
+        // Store the minLayer Index
+        if(found) {
+            minLayerIndex[numPTORLayersFound] = i;
+            overlapRect[numPTORLayersFound] = list->hwLayers[i].displayFrame;
+            minPixelCount += layerPixelCount;
+            numPTORLayersFound++;
+        }
+    }
+
+    // No overlap layers
+    if (!numPTORLayersFound)
+        return false;
+
+    // Store the displayFrame and the sourceCrops of the layers
+    hwc_rect_t displayFrame[numAppLayers];
+    hwc_rect_t sourceCrop[numAppLayers];
+    for(int i = 0; i < numAppLayers; i++) {
+        hwc_layer_1_t* layer = &list->hwLayers[i];
+        displayFrame[i] = layer->displayFrame;
+        sourceCrop[i] = integerizeSourceCrop(layer->sourceCropf);
+    }
+
+    /**
+     * It's possible that 2 PTOR layers might have overlapping.
+     * In such case, remove the intersection(again if peripheral)
+     * from the lower PTOR layer to avoid overlapping.
+     * If intersection is not on peripheral then compromise
+     * by reducing number of PTOR layers.
+     **/
+    hwc_rect_t commonRect = getIntersection(overlapRect[0], overlapRect[1]);
+    if(isValidRect(commonRect)) {
+        overlapRect[1] = deductRect(overlapRect[1], commonRect);
+        list->hwLayers[minLayerIndex[1]].displayFrame = overlapRect[1];
+    }
+
+    ctx->mPtorInfo.count = numPTORLayersFound;
+    for(int i = 0; i < MAX_PTOR_LAYERS; i++) {
+        ctx->mPtorInfo.layerIndex[i] = minLayerIndex[i];
+    }
+
+    if (!ctx->mCopyBit[mDpy]->prepareOverlap(ctx, list)) {
+        // reset PTOR
+        ctx->mPtorInfo.count = 0;
+        if(isValidRect(commonRect)) {
+            // If PTORs are intersecting restore displayframe of PTOR[1]
+            // before returning, as we have modified it above.
+            list->hwLayers[minLayerIndex[1]].displayFrame =
+                    displayFrame[minLayerIndex[1]];
+        }
+        return false;
+    }
+    private_handle_t *renderBuf = ctx->mCopyBit[mDpy]->getCurrentRenderBuffer();
+    Whf layerWhf[numPTORLayersFound]; // To store w,h,f of PTOR layers
+
+    // Store the blending mode, planeAlpha, and transform of PTOR layers
+    int32_t blending[numPTORLayersFound];
+    uint8_t planeAlpha[numPTORLayersFound];
+    uint32_t transform[numPTORLayersFound];
+
+    for(int j = 0; j < numPTORLayersFound; j++) {
+        int index =  ctx->mPtorInfo.layerIndex[j];
+
+        // Update src crop of PTOR layer
+        hwc_layer_1_t* layer = &list->hwLayers[index];
+        layer->sourceCropf.left = (float)ctx->mPtorInfo.displayFrame[j].left;
+        layer->sourceCropf.top = (float)ctx->mPtorInfo.displayFrame[j].top;
+        layer->sourceCropf.right = (float)ctx->mPtorInfo.displayFrame[j].right;
+        layer->sourceCropf.bottom =(float)ctx->mPtorInfo.displayFrame[j].bottom;
+
+        // Store & update w, h, format of PTOR layer
+        private_handle_t *hnd = (private_handle_t *)layer->handle;
+        Whf whf(hnd->width, hnd->height, hnd->format, hnd->size);
+        layerWhf[j] = whf;
+        hnd->width = renderBuf->width;
+        hnd->height = renderBuf->height;
+        hnd->format = renderBuf->format;
+
+        // Store & update blending mode, planeAlpha and transform of PTOR layer
+        blending[j] = layer->blending;
+        planeAlpha[j] = layer->planeAlpha;
+        transform[j] = layer->transform;
+        layer->blending = HWC_BLENDING_NONE;
+        layer->planeAlpha = 0xFF;
+        layer->transform = 0;
+
+        // Remove overlap from crop & displayFrame of below layers
+        for (int i = 0; i < index && index !=-1; i++) {
+            layer = &list->hwLayers[i];
+            if(!isValidRect(getIntersection(layer->displayFrame,
+                                            overlapRect[j])))  {
+                continue;
+            }
+            // Update layer attributes
+            hwc_rect_t srcCrop = integerizeSourceCrop(layer->sourceCropf);
+            hwc_rect_t destRect = deductRect(layer->displayFrame,
+                        getIntersection(layer->displayFrame, overlapRect[j]));
+            qhwc::calculate_crop_rects(srcCrop, layer->displayFrame, destRect,
+                                       layer->transform);
+            layer->sourceCropf.left = (float)srcCrop.left;
+            layer->sourceCropf.top = (float)srcCrop.top;
+            layer->sourceCropf.right = (float)srcCrop.right;
+            layer->sourceCropf.bottom = (float)srcCrop.bottom;
+        }
+    }
+
+    mCurrentFrame.mdpCount = numAppLayers;
+    mCurrentFrame.fbCount = 0;
+    mCurrentFrame.fbZ = -1;
+
+    for (int j = 0; j < numAppLayers; j++) {
+        if(isValidRect(list->hwLayers[j].displayFrame)) {
+            mCurrentFrame.isFBComposed[j] = false;
+        } else {
+            mCurrentFrame.mdpCount--;
+            mCurrentFrame.drop[j] = true;
+        }
+    }
+
+    bool result = postHeuristicsHandling(ctx, list);
+
+    // Restore layer attributes
+    for(int i = 0; i < numAppLayers; i++) {
+        hwc_layer_1_t* layer = &list->hwLayers[i];
+        layer->displayFrame = displayFrame[i];
+        layer->sourceCropf.left = (float)sourceCrop[i].left;
+        layer->sourceCropf.top = (float)sourceCrop[i].top;
+        layer->sourceCropf.right = (float)sourceCrop[i].right;
+        layer->sourceCropf.bottom = (float)sourceCrop[i].bottom;
+    }
+
+    // Restore w,h,f, blending attributes, and transform of PTOR layers
+    for (int i = 0; i < numPTORLayersFound; i++) {
+        int idx = ctx->mPtorInfo.layerIndex[i];
+        hwc_layer_1_t* layer = &list->hwLayers[idx];
+        private_handle_t *hnd = (private_handle_t *)list->hwLayers[idx].handle;
+        hnd->width = layerWhf[i].w;
+        hnd->height = layerWhf[i].h;
+        hnd->format = layerWhf[i].format;
+        layer->blending = blending[i];
+        layer->planeAlpha = planeAlpha[i];
+        layer->transform = transform[i];
+    }
+
+    if (!result) {
+        // reset PTOR
+        ctx->mPtorInfo.count = 0;
+        reset(ctx);
+    } else {
+        ALOGD_IF(isDebug(), "%s: PTOR Indexes: %d and %d", __FUNCTION__,
+                 ctx->mPtorInfo.layerIndex[0],  ctx->mPtorInfo.layerIndex[1]);
+    }
+
+    ALOGD_IF(isDebug(), "%s: Postheuristics %s!", __FUNCTION__,
+             (result ? "successful" : "failed"));
+    return result;
+}
+
+bool MDPComp::partialMDPComp(hwc_context_t *ctx, hwc_display_contents_1_t* list)
+{
+    if(!sEnableMixedMode || !isAlphaPresentinFB(ctx, mDpy)) {
+        //Mixed mode is disabled/can't be used. No need to even try caching.
+        return false;
+    }
+
+    bool ret = false;
+    if(isSkipPresent(ctx, mDpy) or list->flags & HWC_GEOMETRY_CHANGED) {
+        //Try load based first
+        ret =   loadBasedComp(ctx, list) or
+                cacheBasedComp(ctx, list);
+    } else {
+        ret =   cacheBasedComp(ctx, list) or
+                loadBasedComp(ctx, list);
+    }
+
+    return ret;
+}
+
+bool MDPComp::cacheBasedComp(hwc_context_t *ctx,
+        hwc_display_contents_1_t* list) {
+    if(sSimulationFlags & MDPCOMP_AVOID_CACHE_MDP)
+        return false;
+
+    int numAppLayers = ctx->listStats[mDpy].numAppLayers;
+    mCurrentFrame.reset(numAppLayers);
+    updateLayerCache(ctx, list, mCurrentFrame);
+
+    //If an MDP marked layer is unsupported cannot do partial MDP Comp
+    for(int i = 0; i < numAppLayers; i++) {
+        if(!mCurrentFrame.isFBComposed[i]) {
+            hwc_layer_1_t* layer = &list->hwLayers[i];
+            if(not isSupportedForMDPComp(ctx, layer)) {
+                ALOGD_IF(isDebug(), "%s: Unsupported layer in list",
+                        __FUNCTION__);
+                reset(ctx);
+                return false;
+            }
+        }
+    }
+
+    updateYUV(ctx, list, false /*secure only*/, mCurrentFrame);
+    /* mark secure RGB layers for MDP comp */
+    updateSecureRGB(ctx, list);
+    bool ret = markLayersForCaching(ctx, list); //sets up fbZ also
+    if(!ret) {
+        ALOGD_IF(isDebug(),"%s: batching failed, dpy %d",__FUNCTION__, mDpy);
+        reset(ctx);
+        return false;
+    }
+
+    int mdpCount = mCurrentFrame.mdpCount;
+
+    if(sEnableYUVsplit){
+        adjustForSourceSplit(ctx, list);
+    }
+
+    //Will benefit cases where a video has non-updating background.
+    if((mDpy > HWC_DISPLAY_PRIMARY) and
+            (mdpCount > MAX_SEC_LAYERS)) {
+        ALOGD_IF(isDebug(), "%s: Exceeds max secondary pipes",__FUNCTION__);
+        reset(ctx);
+        return false;
+    }
+
+    if(!postHeuristicsHandling(ctx, list)) {
+        ALOGD_IF(isDebug(), "post heuristic handling failed");
+        reset(ctx);
+        return false;
+    }
+    ALOGD_IF(sSimulationFlags,"%s: CACHE_MDP_COMP SUCCEEDED",
+             __FUNCTION__);
+
+    return true;
+}
+
+bool MDPComp::loadBasedComp(hwc_context_t *ctx,
+        hwc_display_contents_1_t* list) {
+    if(sSimulationFlags & MDPCOMP_AVOID_LOAD_MDP)
+        return false;
+
+    if(not isLoadBasedCompDoable(ctx)) {
+        return false;
+    }
+
+    const int numAppLayers = ctx->listStats[mDpy].numAppLayers;
+    const int numNonDroppedLayers = numAppLayers - mCurrentFrame.dropCount;
+    const int stagesForMDP = min(sMaxPipesPerMixer,
+            ctx->mOverlay->availablePipes(mDpy, Overlay::MIXER_DEFAULT));
+
+    int mdpBatchSize = stagesForMDP - 1; //1 stage for FB
+    int fbBatchSize = numNonDroppedLayers - mdpBatchSize;
+    int lastMDPSupportedIndex = numAppLayers;
+    int dropCount = 0;
+
+    //Find the minimum MDP batch size
+    for(int i = 0; i < numAppLayers;i++) {
+        if(mCurrentFrame.drop[i]) {
+            dropCount++;
+            continue;
+        }
+        hwc_layer_1_t* layer = &list->hwLayers[i];
+        if(not isSupportedForMDPComp(ctx, layer)) {
+            lastMDPSupportedIndex = i;
+            mdpBatchSize = min(i - dropCount, stagesForMDP - 1);
+            fbBatchSize = numNonDroppedLayers - mdpBatchSize;
+            break;
+        }
+    }
+
+    ALOGD_IF(isDebug(), "%s:Before optimizing fbBatch, mdpbatch %d, fbbatch %d "
+            "dropped %d", __FUNCTION__, mdpBatchSize, fbBatchSize,
+            mCurrentFrame.dropCount);
+
+    //Start at a point where the fb batch should at least have 2 layers, for
+    //this mode to be justified.
+    while(fbBatchSize < 2) {
+        ++fbBatchSize;
+        --mdpBatchSize;
+    }
+
+    //If there are no layers for MDP, this mode doesnt make sense.
+    if(mdpBatchSize < 1) {
+        ALOGD_IF(isDebug(), "%s: No MDP layers after optimizing for fbBatch",
+                __FUNCTION__);
+        return false;
+    }
+
+    mCurrentFrame.reset(numAppLayers);
+
+    //Try with successively smaller mdp batch sizes until we succeed or reach 1
+    while(mdpBatchSize > 0) {
+        //Mark layers for MDP comp
+        int mdpBatchLeft = mdpBatchSize;
+        for(int i = 0; i < lastMDPSupportedIndex and mdpBatchLeft; i++) {
+            if(mCurrentFrame.drop[i]) {
+                continue;
+            }
+            mCurrentFrame.isFBComposed[i] = false;
+            --mdpBatchLeft;
+        }
+
+        mCurrentFrame.fbZ = mdpBatchSize;
+        mCurrentFrame.fbCount = fbBatchSize;
+        mCurrentFrame.mdpCount = mdpBatchSize;
+
+        ALOGD_IF(isDebug(), "%s:Trying with: mdpbatch %d fbbatch %d dropped %d",
+                __FUNCTION__, mdpBatchSize, fbBatchSize,
+                mCurrentFrame.dropCount);
+
+        if(postHeuristicsHandling(ctx, list)) {
+            ALOGD_IF(isDebug(), "%s: Postheuristics handling succeeded",
+                     __FUNCTION__);
+            ALOGD_IF(sSimulationFlags,"%s: LOAD_MDP_COMP SUCCEEDED",
+                     __FUNCTION__);
+            return true;
+        }
+
+        reset(ctx);
+        --mdpBatchSize;
+        ++fbBatchSize;
+    }
+
+    return false;
+}
+
+bool MDPComp::isLoadBasedCompDoable(hwc_context_t *ctx) {
+    if(mDpy or isSecurePresent(ctx, mDpy) or
+            isYuvPresent(ctx, mDpy)) {
+        return false;
+    }
+    return true;
+}
+
+bool MDPComp::canPartialUpdate(hwc_context_t *ctx,
+        hwc_display_contents_1_t* list){
+    if(!qdutils::MDPVersion::getInstance().isPartialUpdateEnabled() ||
+            isSkipPresent(ctx, mDpy) || (list->flags & HWC_GEOMETRY_CHANGED) ||
+            !sIsPartialUpdateActive || mDpy ) {
+        return false;
+    }
+    if(ctx->listStats[mDpy].secureUI)
+        return false;
+    return true;
+}
+
+bool MDPComp::tryVideoOnly(hwc_context_t *ctx,
+        hwc_display_contents_1_t* list) {
+    const bool secureOnly = true;
+    return videoOnlyComp(ctx, list, not secureOnly) or
+            videoOnlyComp(ctx, list, secureOnly);
+}
+
+bool MDPComp::videoOnlyComp(hwc_context_t *ctx,
+        hwc_display_contents_1_t* list, bool secureOnly) {
+    if(sSimulationFlags & MDPCOMP_AVOID_VIDEO_ONLY)
+        return false;
+    int numAppLayers = ctx->listStats[mDpy].numAppLayers;
+
+    mCurrentFrame.reset(numAppLayers);
+    mCurrentFrame.fbCount -= mCurrentFrame.dropCount;
+    updateYUV(ctx, list, secureOnly, mCurrentFrame);
+    int mdpCount = mCurrentFrame.mdpCount;
+
+    if(!isYuvPresent(ctx, mDpy) or (mdpCount == 0)) {
+        reset(ctx);
+        return false;
+    }
+
+    /* Bail out if we are processing only secured video layers
+     * and we dont have any */
+    if(!isSecurePresent(ctx, mDpy) && secureOnly){
+        reset(ctx);
+        return false;
+    }
+
+    if(mCurrentFrame.fbCount)
+        mCurrentFrame.fbZ = mCurrentFrame.mdpCount;
+
+    if(sEnableYUVsplit){
+        adjustForSourceSplit(ctx, list);
+    }
+
+    if(!postHeuristicsHandling(ctx, list)) {
+        ALOGD_IF(isDebug(), "post heuristic handling failed");
+        reset(ctx);
+        return false;
+    }
+
+    ALOGD_IF(sSimulationFlags,"%s: VIDEO_ONLY_COMP SUCCEEDED",
+             __FUNCTION__);
+    return true;
+}
+
+/* if tryFullFrame fails, try to push all video and secure RGB layers to MDP */
+bool MDPComp::tryMDPOnlyLayers(hwc_context_t *ctx,
+        hwc_display_contents_1_t* list) {
+    // Fall back to video only composition, if AIV video mode is enabled
+    if(ctx->listStats[mDpy].mAIVVideoMode) {
+        ALOGD_IF(isDebug(), "%s: AIV Video Mode enabled dpy %d",
+            __FUNCTION__, mDpy);
+        return false;
+    }
+
+    const bool secureOnly = true;
+    return mdpOnlyLayersComp(ctx, list, not secureOnly) or
+            mdpOnlyLayersComp(ctx, list, secureOnly);
+
+}
+
+bool MDPComp::mdpOnlyLayersComp(hwc_context_t *ctx,
+        hwc_display_contents_1_t* list, bool secureOnly) {
+
+    if(sSimulationFlags & MDPCOMP_AVOID_MDP_ONLY_LAYERS)
+        return false;
+
+    /* Bail out if we are processing only secured video layers
+     * and we dont have any */
+    if(!isSecurePresent(ctx, mDpy) && secureOnly){
+        reset(ctx);
+        return false;
+    }
+
+    int numAppLayers = ctx->listStats[mDpy].numAppLayers;
+    mCurrentFrame.reset(numAppLayers);
+    mCurrentFrame.fbCount -= mCurrentFrame.dropCount;
+
+    updateYUV(ctx, list, secureOnly, mCurrentFrame);
+    /* mark secure RGB layers for MDP comp */
+    updateSecureRGB(ctx, list);
+
+    if(mCurrentFrame.mdpCount == 0) {
+        reset(ctx);
+        return false;
+    }
+
+    /* find the maximum batch of layers to be marked for framebuffer */
+    bool ret = markLayersForCaching(ctx, list); //sets up fbZ also
+    if(!ret) {
+        ALOGD_IF(isDebug(),"%s: batching failed, dpy %d",__FUNCTION__, mDpy);
+        reset(ctx);
+        return false;
+    }
+
+    if(sEnableYUVsplit){
+        adjustForSourceSplit(ctx, list);
+    }
+
+    if(!postHeuristicsHandling(ctx, list)) {
+        ALOGD_IF(isDebug(), "post heuristic handling failed");
+        reset(ctx);
+        return false;
+    }
+
+    ALOGD_IF(sSimulationFlags,"%s: MDP_ONLY_LAYERS_COMP SUCCEEDED",
+             __FUNCTION__);
+    return true;
+}
+
+/* Checks for conditions where YUV layers cannot be bypassed */
+bool MDPComp::isYUVDoable(hwc_context_t* ctx, hwc_layer_1_t* layer) {
+    if(isSkipLayer(layer)) {
+        ALOGD_IF(isDebug(), "%s: Video marked SKIP dpy %d", __FUNCTION__, mDpy);
+        return false;
+    }
+
+    if(has90Transform(layer) && !canUseRotator(ctx, mDpy)) {
+        ALOGD_IF(isDebug(), "%s: no free DMA pipe",__FUNCTION__);
+        return false;
+    }
+
+    if(isSecuring(ctx, layer)) {
+        ALOGD_IF(isDebug(), "%s: MDP securing is active", __FUNCTION__);
+        return false;
+    }
+
+    if(!isValidDimension(ctx, layer)) {
+        ALOGD_IF(isDebug(), "%s: Buffer is of invalid width",
+            __FUNCTION__);
+        return false;
+    }
+
+    if(layer->planeAlpha < 0xFF) {
+        ALOGD_IF(isDebug(), "%s: Cannot handle YUV layer with plane alpha\
+                 in video only mode",
+                 __FUNCTION__);
+        return false;
+    }
+
+    return true;
+}
+
+/* Checks for conditions where Secure RGB layers cannot be bypassed */
+bool MDPComp::isSecureRGBDoable(hwc_context_t* ctx, hwc_layer_1_t* layer) {
+    if(isSkipLayer(layer)) {
+        ALOGD_IF(isDebug(), "%s: Secure RGB layer marked SKIP dpy %d",
+            __FUNCTION__, mDpy);
+        return false;
+    }
+
+    if(isSecuring(ctx, layer)) {
+        ALOGD_IF(isDebug(), "%s: MDP securing is active", __FUNCTION__);
+        return false;
+    }
+
+    if(not isSupportedForMDPComp(ctx, layer)) {
+        ALOGD_IF(isDebug(), "%s: Unsupported secure RGB layer",
+            __FUNCTION__);
+        return false;
+    }
+    return true;
+}
+
+/* starts at fromIndex and check for each layer to find
+ * if it it has overlapping with any Updating layer above it in zorder
+ * till the end of the batch. returns true if it finds any intersection */
+bool MDPComp::canPushBatchToTop(const hwc_display_contents_1_t* list,
+        int fromIndex, int toIndex) {
+    for(int i = fromIndex; i < toIndex; i++) {
+        if(mCurrentFrame.isFBComposed[i] && !mCurrentFrame.drop[i]) {
+            if(intersectingUpdatingLayers(list, i+1, toIndex, i)) {
+                return false;
+            }
+        }
+    }
+    return true;
+}
+
+/* Checks if given layer at targetLayerIndex has any
+ * intersection with all the updating layers in beween
+ * fromIndex and toIndex. Returns true if it finds intersectiion */
+bool MDPComp::intersectingUpdatingLayers(const hwc_display_contents_1_t* list,
+        int fromIndex, int toIndex, int targetLayerIndex) {
+    for(int i = fromIndex; i <= toIndex; i++) {
+        if(!mCurrentFrame.isFBComposed[i]) {
+            if(areLayersIntersecting(&list->hwLayers[i],
+                        &list->hwLayers[targetLayerIndex]))  {
+                return true;
+            }
+        }
+    }
+    return false;
+}
+
+int MDPComp::getBatch(hwc_display_contents_1_t* list,
+        int& maxBatchStart, int& maxBatchEnd,
+        int& maxBatchCount) {
+    int i = 0;
+    int fbZOrder =-1;
+    int droppedLayerCt = 0;
+    while (i < mCurrentFrame.layerCount) {
+        int batchCount = 0;
+        int batchStart = i;
+        int batchEnd = i;
+        /* Adjust batch Z order with the dropped layers so far */
+        int fbZ = batchStart - droppedLayerCt;
+        int firstZReverseIndex = -1;
+        int updatingLayersAbove = 0;//Updating layer count in middle of batch
+        while(i < mCurrentFrame.layerCount) {
+            if(!mCurrentFrame.isFBComposed[i]) {
+                if(!batchCount) {
+                    i++;
+                    break;
+                }
+                updatingLayersAbove++;
+                i++;
+                continue;
+            } else {
+                if(mCurrentFrame.drop[i]) {
+                    i++;
+                    droppedLayerCt++;
+                    continue;
+                } else if(updatingLayersAbove <= 0) {
+                    batchCount++;
+                    batchEnd = i;
+                    i++;
+                    continue;
+                } else { //Layer is FBComposed, not a drop & updatingLayer > 0
+
+                    // We have a valid updating layer already. If layer-i not
+                    // have overlapping with all updating layers in between
+                    // batch-start and i, then we can add layer i to batch.
+                    if(!intersectingUpdatingLayers(list, batchStart, i-1, i)) {
+                        batchCount++;
+                        batchEnd = i;
+                        i++;
+                        continue;
+                    } else if(canPushBatchToTop(list, batchStart, i)) {
+                        //If All the non-updating layers with in this batch
+                        //does not have intersection with the updating layers
+                        //above in z-order, then we can safely move the batch to
+                        //higher z-order. Increment fbZ as it is moving up.
+                        if( firstZReverseIndex < 0) {
+                            firstZReverseIndex = i;
+                        }
+                        batchCount++;
+                        batchEnd = i;
+                        fbZ += updatingLayersAbove;
+                        i++;
+                        updatingLayersAbove = 0;
+                        continue;
+                    } else {
+                        //both failed.start the loop again from here.
+                        if(firstZReverseIndex >= 0) {
+                            i = firstZReverseIndex;
+                        }
+                        break;
+                    }
+                }
+            }
+        }
+        if(batchCount > maxBatchCount) {
+            maxBatchCount = batchCount;
+            maxBatchStart = batchStart;
+            maxBatchEnd = batchEnd;
+            fbZOrder = fbZ;
+        }
+    }
+    return fbZOrder;
+}
+
+bool  MDPComp::markLayersForCaching(hwc_context_t* ctx,
+        hwc_display_contents_1_t* list) {
+    /* Idea is to keep as many non-updating(cached) layers in FB and
+     * send rest of them through MDP. This is done in 2 steps.
+     *   1. Find the maximum contiguous batch of non-updating layers.
+     *   2. See if we can improve this batch size for caching by adding
+     *      opaque layers around the batch, if they don't have
+     *      any overlapping with the updating layers in between.
+     * NEVER mark an updating layer for caching.
+     * But cached ones can be marked for MDP */
+
+    int maxBatchStart = -1;
+    int maxBatchEnd = -1;
+    int maxBatchCount = 0;
+    int fbZ = -1;
+
+    /* Nothing is cached. No batching needed */
+    if(mCurrentFrame.fbCount == 0) {
+        return true;
+    }
+
+    /* No MDP comp layers, try to use other comp modes */
+    if(mCurrentFrame.mdpCount == 0) {
+        return false;
+    }
+
+    fbZ = getBatch(list, maxBatchStart, maxBatchEnd, maxBatchCount);
+
+    /* reset rest of the layers lying inside ROI for MDP comp */
+    for(int i = 0; i < mCurrentFrame.layerCount; i++) {
+        hwc_layer_1_t* layer = &list->hwLayers[i];
+        if((i < maxBatchStart || i > maxBatchEnd) &&
+                mCurrentFrame.isFBComposed[i]){
+            if(!mCurrentFrame.drop[i]){
+                //If an unsupported layer is being attempted to
+                //be pulled out we should fail
+                if(not isSupportedForMDPComp(ctx, layer)) {
+                    return false;
+                }
+                mCurrentFrame.isFBComposed[i] = false;
+            }
+        }
+    }
+
+    // update the frame data
+    mCurrentFrame.fbZ = fbZ;
+    mCurrentFrame.fbCount = maxBatchCount;
+    mCurrentFrame.mdpCount = mCurrentFrame.layerCount -
+            mCurrentFrame.fbCount - mCurrentFrame.dropCount;
+
+    ALOGD_IF(isDebug(),"%s: cached count: %d",__FUNCTION__,
+            mCurrentFrame.fbCount);
+
+    return true;
+}
+
+void MDPComp::updateLayerCache(hwc_context_t* ctx,
+        hwc_display_contents_1_t* list, FrameInfo& frame) {
+    int numAppLayers = ctx->listStats[mDpy].numAppLayers;
+    int fbCount = 0;
+
+    for(int i = 0; i < numAppLayers; i++) {
+        hwc_layer_1_t * layer = &list->hwLayers[i];
+        if (!layerUpdating(layer)) {
+            if(!frame.drop[i])
+                fbCount++;
+            frame.isFBComposed[i] = true;
+        } else {
+            frame.isFBComposed[i] = false;
+        }
+    }
+
+    frame.fbCount = fbCount;
+    frame.mdpCount = frame.layerCount - frame.fbCount
+                                            - frame.dropCount;
+
+    ALOGD_IF(isDebug(),"%s: MDP count: %d FB count %d drop count: %d",
+            __FUNCTION__, frame.mdpCount, frame.fbCount, frame.dropCount);
+}
+
+// drop other non-AIV layers from external display list.
+void MDPComp::dropNonAIVLayers(hwc_context_t* ctx,
+                              hwc_display_contents_1_t* list) {
+    for (size_t i = 0; i < (size_t)ctx->listStats[mDpy].numAppLayers; i++) {
+        hwc_layer_1_t * layer = &list->hwLayers[i];
+         if(!(isAIVVideoLayer(layer) || isAIVCCLayer(layer))) {
+            mCurrentFrame.dropCount++;
+            mCurrentFrame.drop[i] = true;
+        }
+    }
+    mCurrentFrame.fbCount -= mCurrentFrame.dropCount;
+    mCurrentFrame.mdpCount = mCurrentFrame.layerCount -
+            mCurrentFrame.fbCount - mCurrentFrame.dropCount;
+    ALOGD_IF(isDebug(),"%s: fb count: %d mdp count %d drop count %d",
+        __FUNCTION__, mCurrentFrame.fbCount, mCurrentFrame.mdpCount,
+        mCurrentFrame.dropCount);
+}
+
+void MDPComp::updateYUV(hwc_context_t* ctx, hwc_display_contents_1_t* list,
+        bool secureOnly, FrameInfo& frame) {
+    int nYuvCount = ctx->listStats[mDpy].yuvCount;
+    for(int index = 0;index < nYuvCount; index++){
+        int nYuvIndex = ctx->listStats[mDpy].yuvIndices[index];
+        hwc_layer_1_t* layer = &list->hwLayers[nYuvIndex];
+
+        if(mCurrentFrame.drop[nYuvIndex]) {
+            continue;
+        }
+
+        if(!isYUVDoable(ctx, layer)) {
+            if(!frame.isFBComposed[nYuvIndex]) {
+                frame.isFBComposed[nYuvIndex] = true;
+                frame.fbCount++;
+            }
+        } else {
+            if(frame.isFBComposed[nYuvIndex]) {
+                private_handle_t *hnd = (private_handle_t *)layer->handle;
+                if(!secureOnly || isSecureBuffer(hnd)) {
+                    frame.isFBComposed[nYuvIndex] = false;
+                    frame.fbCount--;
+                }
+            }
+        }
+    }
+
+    frame.mdpCount = frame.layerCount - frame.fbCount - frame.dropCount;
+    ALOGD_IF(isDebug(),"%s: fb count: %d",__FUNCTION__, frame.fbCount);
+}
+
+void MDPComp::updateSecureRGB(hwc_context_t* ctx,
+    hwc_display_contents_1_t* list) {
+    int nSecureRGBCount = ctx->listStats[mDpy].secureRGBCount;
+    for(int index = 0;index < nSecureRGBCount; index++){
+        int nSecureRGBIndex = ctx->listStats[mDpy].secureRGBIndices[index];
+        hwc_layer_1_t* layer = &list->hwLayers[nSecureRGBIndex];
+
+        if(!isSecureRGBDoable(ctx, layer)) {
+            if(!mCurrentFrame.isFBComposed[nSecureRGBIndex]) {
+                mCurrentFrame.isFBComposed[nSecureRGBIndex] = true;
+                mCurrentFrame.fbCount++;
+            }
+        } else {
+            if(mCurrentFrame.isFBComposed[nSecureRGBIndex]) {
+                mCurrentFrame.isFBComposed[nSecureRGBIndex] = false;
+                mCurrentFrame.fbCount--;
+            }
+        }
+    }
+
+    mCurrentFrame.mdpCount = mCurrentFrame.layerCount -
+            mCurrentFrame.fbCount - mCurrentFrame.dropCount;
+    ALOGD_IF(isDebug(),"%s: fb count: %d",__FUNCTION__,
+             mCurrentFrame.fbCount);
+}
+
+hwc_rect_t MDPComp::getUpdatingFBRect(hwc_context_t *ctx,
+        hwc_display_contents_1_t* list){
+    hwc_rect_t fbRect = (struct hwc_rect){0, 0, 0, 0};
+
+    /* Update only the region of FB needed for composition */
+    for(int i = 0; i < mCurrentFrame.layerCount; i++ ) {
+        if(mCurrentFrame.isFBComposed[i] && !mCurrentFrame.drop[i]) {
+            hwc_layer_1_t* layer = &list->hwLayers[i];
+            hwc_rect_t dst = layer->displayFrame;
+            fbRect = getUnion(fbRect, dst);
+        }
+    }
+    trimAgainstROI(ctx, fbRect);
+    return fbRect;
+}
+
+bool MDPComp::postHeuristicsHandling(hwc_context_t *ctx,
+        hwc_display_contents_1_t* list) {
+
+    //Capability checks
+    if(!resourceCheck(ctx, list)) {
+        ALOGD_IF(isDebug(), "%s: resource check failed", __FUNCTION__);
+        return false;
+    }
+
+    //Limitations checks
+    if(!hwLimitationsCheck(ctx, list)) {
+        ALOGD_IF(isDebug(), "%s: HW limitations",__FUNCTION__);
+        return false;
+    }
+
+    //Configure framebuffer first if applicable
+    if(mCurrentFrame.fbZ >= 0) {
+        hwc_rect_t fbRect = getUpdatingFBRect(ctx, list);
+        if(!ctx->mFBUpdate[mDpy]->prepare(ctx, list, fbRect, mCurrentFrame.fbZ))
+        {
+            ALOGD_IF(isDebug(), "%s configure framebuffer failed",
+                    __FUNCTION__);
+            return false;
+        }
+    }
+
+    mCurrentFrame.map();
+
+    if(!allocLayerPipes(ctx, list)) {
+        ALOGD_IF(isDebug(), "%s: Unable to allocate MDP pipes", __FUNCTION__);
+        return false;
+    }
+
+    for (int index = 0, mdpNextZOrder = 0; index < mCurrentFrame.layerCount;
+            index++) {
+        if(!mCurrentFrame.isFBComposed[index]) {
+            int mdpIndex = mCurrentFrame.layerToMDP[index];
+            hwc_layer_1_t* layer = &list->hwLayers[index];
+
+            //Leave fbZ for framebuffer. CACHE/GLES layers go here.
+            if(mdpNextZOrder == mCurrentFrame.fbZ) {
+                mdpNextZOrder++;
+            }
+            MdpPipeInfo* cur_pipe = mCurrentFrame.mdpToLayer[mdpIndex].pipeInfo;
+            cur_pipe->zOrder = mdpNextZOrder++;
+
+            private_handle_t *hnd = (private_handle_t *)layer->handle;
+            if(isYUVSplitNeeded(hnd) && sEnableYUVsplit){
+                if(configure4k2kYuv(ctx, layer,
+                            mCurrentFrame.mdpToLayer[mdpIndex])
+                        != 0 ){
+                    ALOGD_IF(isDebug(), "%s: Failed to configure split pipes \
+                            for layer %d",__FUNCTION__, index);
+                    return false;
+                }
+                else{
+                    mdpNextZOrder++;
+                }
+                continue;
+            }
+            if(configure(ctx, layer, mCurrentFrame.mdpToLayer[mdpIndex]) != 0 ){
+                ALOGD_IF(isDebug(), "%s: Failed to configure overlay for \
+                        layer %d",__FUNCTION__, index);
+                return false;
+            }
+        }
+    }
+
+    if(!ctx->mOverlay->validateAndSet(mDpy, ctx->dpyAttr[mDpy].fd)) {
+        ALOGD_IF(isDebug(), "%s: Failed to validate and set overlay for dpy %d"
+                ,__FUNCTION__, mDpy);
+        return false;
+    }
+
+    setRedraw(ctx, list);
+    return true;
+}
+
+bool MDPComp::resourceCheck(hwc_context_t* ctx,
+        hwc_display_contents_1_t* list) {
+    const bool fbUsed = mCurrentFrame.fbCount;
+    if(mCurrentFrame.mdpCount > sMaxPipesPerMixer - fbUsed) {
+        ALOGD_IF(isDebug(), "%s: Exceeds MAX_PIPES_PER_MIXER",__FUNCTION__);
+        return false;
+    }
+    // Init rotCount to number of rotate sessions used by other displays
+    int rotCount = ctx->mRotMgr->getNumActiveSessions();
+    // Count the number of rotator sessions required for current display
+    for (int index = 0; index < mCurrentFrame.layerCount; index++) {
+        if(!mCurrentFrame.isFBComposed[index]) {
+            hwc_layer_1_t* layer = &list->hwLayers[index];
+            private_handle_t *hnd = (private_handle_t *)layer->handle;
+            if(has90Transform(layer) && isRotationDoable(ctx, hnd)) {
+                rotCount++;
+            }
+        }
+    }
+    // if number of layers to rotate exceeds max rotator sessions, bail out.
+    if(rotCount > RotMgr::MAX_ROT_SESS) {
+        ALOGD_IF(isDebug(), "%s: Exceeds max rotator sessions  %d",
+                                    __FUNCTION__, mDpy);
+        return false;
+    }
+    return true;
+}
+
+bool MDPComp::hwLimitationsCheck(hwc_context_t* ctx,
+        hwc_display_contents_1_t* list) {
+
+    //A-family hw limitation:
+    //If a layer need alpha scaling, MDP can not support.
+    if(ctx->mMDP.version < qdutils::MDSS_V5) {
+        for(int i = 0; i < mCurrentFrame.layerCount; ++i) {
+            if(!mCurrentFrame.isFBComposed[i] &&
+                    isAlphaScaled( &list->hwLayers[i])) {
+                ALOGD_IF(isDebug(), "%s:frame needs alphaScaling",__FUNCTION__);
+                return false;
+            }
+        }
+    }
+
+    // On 8x26 & 8974 hw, we have a limitation of downscaling+blending.
+    //If multiple layers requires downscaling and also they are overlapping
+    //fall back to GPU since MDSS can not handle it.
+    if(qdutils::MDPVersion::getInstance().is8x74v2() ||
+            qdutils::MDPVersion::getInstance().is8x26()) {
+        for(int i = 0; i < mCurrentFrame.layerCount-1; ++i) {
+            hwc_layer_1_t* botLayer = &list->hwLayers[i];
+            if(!mCurrentFrame.isFBComposed[i] &&
+                    isDownscaleRequired(botLayer)) {
+                //if layer-i is marked for MDP and needs downscaling
+                //check if any MDP layer on top of i & overlaps with layer-i
+                for(int j = i+1; j < mCurrentFrame.layerCount; ++j) {
+                    hwc_layer_1_t* topLayer = &list->hwLayers[j];
+                    if(!mCurrentFrame.isFBComposed[j] &&
+                            isDownscaleRequired(topLayer)) {
+                        hwc_rect_t r = getIntersection(botLayer->displayFrame,
+                                topLayer->displayFrame);
+                        if(isValidRect(r))
+                            return false;
+                    }
+                }
+            }
+        }
+    }
+    return true;
+}
+
+void MDPComp::setDynRefreshRate(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
+    //For primary display, set the dynamic refreshrate
+    if(!mDpy && qdutils::MDPVersion::getInstance().isDynFpsSupported() &&
+                                        ctx->mUseMetaDataRefreshRate) {
+        FrameInfo frame;
+        frame.reset(mCurrentFrame.layerCount);
+        memset(&frame.drop, 0, sizeof(frame.drop));
+        frame.dropCount = 0;
+        ALOGD_IF(isDebug(), "%s: Update Cache and YUVInfo for Dyn Refresh Rate",
+                 __FUNCTION__);
+        updateLayerCache(ctx, list, frame);
+        updateYUV(ctx, list, false /*secure only*/, frame);
+        uint32_t refreshRate = ctx->dpyAttr[mDpy].refreshRate;
+        MDPVersion& mdpHw = MDPVersion::getInstance();
+        if(sIdleFallBack) {
+            //Set minimum panel refresh rate during idle timeout
+            refreshRate = mdpHw.getMinFpsSupported();
+        } else if((ctx->listStats[mDpy].yuvCount == frame.mdpCount) ||
+                                (frame.layerCount == 1)) {
+            //Set the new fresh rate, if there is only one updating YUV layer
+            //or there is one single RGB layer with this request
+            refreshRate = ctx->listStats[mDpy].refreshRateRequest;
+        }
+        setRefreshRate(ctx, mDpy, refreshRate);
+    }
+}
+
+int MDPComp::prepare(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
+    int ret = 0;
+    char property[PROPERTY_VALUE_MAX];
+
+    if(!ctx || !list) {
+        ALOGE("%s: Invalid context or list",__FUNCTION__);
+        mCachedFrame.reset();
+        return -1;
+    }
+
+    const int numLayers = ctx->listStats[mDpy].numAppLayers;
+    if(mDpy == HWC_DISPLAY_PRIMARY) {
+        sSimulationFlags = 0;
+        if(property_get("debug.hwc.simulate", property, NULL) > 0) {
+            int currentFlags = atoi(property);
+            if(currentFlags != sSimulationFlags) {
+                sSimulationFlags = currentFlags;
+                ALOGI("%s: Simulation Flag read: 0x%x (%d)", __FUNCTION__,
+                        sSimulationFlags, sSimulationFlags);
+            }
+        }
+    }
+    // reset PTOR
+    if(!mDpy)
+        memset(&(ctx->mPtorInfo), 0, sizeof(ctx->mPtorInfo));
+
+    //reset old data
+    mCurrentFrame.reset(numLayers);
+    memset(&mCurrentFrame.drop, 0, sizeof(mCurrentFrame.drop));
+    mCurrentFrame.dropCount = 0;
+
+    //Do not cache the information for next draw cycle.
+    if(numLayers > MAX_NUM_APP_LAYERS or (!numLayers)) {
+        ALOGI("%s: Unsupported layer count for mdp composition",
+                __FUNCTION__);
+        mCachedFrame.reset();
+#ifdef DYNAMIC_FPS
+        // Reset refresh rate
+        setRefreshRate(ctx, mDpy, ctx->dpyAttr[mDpy].refreshRate);
+#endif
+        return -1;
+    }
+
+    // Detect the start of animation and fall back to GPU only once to cache
+    // all the layers in FB and display FB content untill animation completes.
+    if(ctx->listStats[mDpy].isDisplayAnimating) {
+        mCurrentFrame.needsRedraw = false;
+        if(ctx->mAnimationState[mDpy] == ANIMATION_STOPPED) {
+            mCurrentFrame.needsRedraw = true;
+            ctx->mAnimationState[mDpy] = ANIMATION_STARTED;
+        }
+        setMDPCompLayerFlags(ctx, list);
+        mCachedFrame.updateCounts(mCurrentFrame);
+#ifdef DYNAMIC_FPS
+        // Reset refresh rate
+        setRefreshRate(ctx, mDpy, ctx->dpyAttr[mDpy].refreshRate);
+#endif
+        ret = -1;
+        return ret;
+    } else {
+        ctx->mAnimationState[mDpy] = ANIMATION_STOPPED;
+    }
+
+    if(!mDpy and !isSecondaryConnected(ctx) and !mPrevModeOn and
+       mCachedFrame.isSameFrame(ctx,mDpy,list)) {
+
+        ALOGD_IF(isDebug(),"%s: Avoid new composition",__FUNCTION__);
+        mCurrentFrame.needsRedraw = false;
+        setMDPCompLayerFlags(ctx, list);
+        mCachedFrame.updateCounts(mCurrentFrame);
+#ifdef DYNAMIC_FPS
+        setDynRefreshRate(ctx, list);
+#endif
+        return -1;
+
+    }
+
+    //Hard conditions, if not met, cannot do MDP comp
+    if(isFrameDoable(ctx)) {
+        generateROI(ctx, list);
+        // if AIV Video mode is enabled, drop all non AIV layers from the
+        // external display list.
+        if(ctx->listStats[mDpy].mAIVVideoMode) {
+            dropNonAIVLayers(ctx, list);
+        }
+
+        // if tryFullFrame fails, try to push all video and secure RGB layers
+        // to MDP for composition.
+        mModeOn = tryFullFrame(ctx, list) || tryMDPOnlyLayers(ctx, list) ||
+                  tryVideoOnly(ctx, list);
+        if(mModeOn) {
+            setMDPCompLayerFlags(ctx, list);
+        } else {
+            resetROI(ctx, mDpy);
+            reset(ctx);
+            memset(&mCurrentFrame.drop, 0, sizeof(mCurrentFrame.drop));
+            mCurrentFrame.dropCount = 0;
+            ret = -1;
+            ALOGE_IF(sSimulationFlags && (mDpy == HWC_DISPLAY_PRIMARY),
+                    "MDP Composition Strategies Failed");
+        }
+    } else {
+        if ((ctx->mMDP.version == qdutils::MDP_V3_0_5) && ctx->mCopyBit[mDpy] &&
+                enablePartialUpdateForMDP3) {
+            generateROI(ctx, list);
+            for(int i = 0; i < ctx->listStats[mDpy].numAppLayers; i++) {
+                ctx->copybitDrop[i] = mCurrentFrame.drop[i];
+            }
+        }
+        ALOGD_IF( isDebug(),"%s: MDP Comp not possible for this frame",
+                __FUNCTION__);
+        ret = -1;
+    }
+
+    if(isDebug()) {
+        ALOGD("GEOMETRY change: %d",
+                (list->flags & HWC_GEOMETRY_CHANGED));
+        android::String8 sDump("");
+        dump(sDump, ctx);
+        ALOGD("%s",sDump.string());
+    }
+
+#ifdef DYNAMIC_FPS
+    setDynRefreshRate(ctx, list);
+#endif
+
+    mCachedFrame.updateCounts(mCurrentFrame);
+    return ret;
+}
+
+bool MDPComp::allocSplitVGPipesfor4k2k(hwc_context_t *ctx, int index) {
+
+    bool bRet = true;
+    int mdpIndex = mCurrentFrame.layerToMDP[index];
+    PipeLayerPair& info = mCurrentFrame.mdpToLayer[mdpIndex];
+    info.pipeInfo = new MdpYUVPipeInfo;
+    info.rot = NULL;
+    MdpYUVPipeInfo& pipe_info = *(MdpYUVPipeInfo*)info.pipeInfo;
+
+    pipe_info.lIndex = ovutils::OV_INVALID;
+    pipe_info.rIndex = ovutils::OV_INVALID;
+
+    Overlay::PipeSpecs pipeSpecs;
+    pipeSpecs.formatClass = Overlay::FORMAT_YUV;
+    pipeSpecs.needsScaling = true;
+    pipeSpecs.dpy = mDpy;
+    pipeSpecs.fb = false;
+
+    pipe_info.lIndex = ctx->mOverlay->getPipe(pipeSpecs);
+    if(pipe_info.lIndex == ovutils::OV_INVALID){
+        bRet = false;
+        ALOGD_IF(isDebug(),"%s: allocating first VG pipe failed",
+                __FUNCTION__);
+    }
+    pipe_info.rIndex = ctx->mOverlay->getPipe(pipeSpecs);
+    if(pipe_info.rIndex == ovutils::OV_INVALID){
+        bRet = false;
+        ALOGD_IF(isDebug(),"%s: allocating second VG pipe failed",
+                __FUNCTION__);
+    }
+    return bRet;
+}
+
+int MDPComp::drawOverlap(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
+    int fd = -1;
+    if (ctx->mPtorInfo.isActive()) {
+        fd = ctx->mCopyBit[mDpy]->drawOverlap(ctx, list);
+        if (fd < 0) {
+            ALOGD_IF(isDebug(),"%s: failed", __FUNCTION__);
+        }
+    }
+    return fd;
+}
+//=============MDPCompNonSplit==================================================
+
+void MDPCompNonSplit::adjustForSourceSplit(hwc_context_t *ctx,
+        hwc_display_contents_1_t* list) {
+    //If 4k2k Yuv layer split is possible,  and if
+    //fbz is above 4k2k layer, increment fb zorder by 1
+    //as we split 4k2k layer and increment zorder for right half
+    //of the layer
+    if(!ctx)
+        return;
+    if(mCurrentFrame.fbZ >= 0) {
+        for (int index = 0, mdpNextZOrder = 0; index < mCurrentFrame.layerCount;
+                index++) {
+            if(!mCurrentFrame.isFBComposed[index]) {
+                if(mdpNextZOrder == mCurrentFrame.fbZ) {
+                    mdpNextZOrder++;
+                }
+                mdpNextZOrder++;
+                hwc_layer_1_t* layer = &list->hwLayers[index];
+                private_handle_t *hnd = (private_handle_t *)layer->handle;
+                if(isYUVSplitNeeded(hnd)) {
+                    if(mdpNextZOrder <= mCurrentFrame.fbZ)
+                        mCurrentFrame.fbZ += 1;
+                    mdpNextZOrder++;
+                    //As we split 4kx2k yuv layer and program to 2 VG pipes
+                    //(if available) increase mdpcount by 1.
+                    mCurrentFrame.mdpCount++;
+                }
+            }
+        }
+    }
+}
+
+/*
+ * Configures pipe(s) for MDP composition
+ */
+int MDPCompNonSplit::configure(hwc_context_t *ctx, hwc_layer_1_t *layer,
+                             PipeLayerPair& PipeLayerPair) {
+    MdpPipeInfoNonSplit& mdp_info =
+        *(static_cast<MdpPipeInfoNonSplit*>(PipeLayerPair.pipeInfo));
+    eMdpFlags mdpFlags = OV_MDP_BACKEND_COMPOSITION;
+    eZorder zOrder = static_cast<eZorder>(mdp_info.zOrder);
+    eDest dest = mdp_info.index;
+
+    ALOGD_IF(isDebug(),"%s: configuring: layer: %p z_order: %d dest_pipe: %d",
+             __FUNCTION__, layer, zOrder, dest);
+
+    return configureNonSplit(ctx, layer, mDpy, mdpFlags, zOrder, dest,
+                           &PipeLayerPair.rot);
+}
+
+bool MDPCompNonSplit::allocLayerPipes(hwc_context_t *ctx,
+        hwc_display_contents_1_t* list) {
+    for(int index = 0; index < mCurrentFrame.layerCount; index++) {
+
+        if(mCurrentFrame.isFBComposed[index]) continue;
+
+        hwc_layer_1_t* layer = &list->hwLayers[index];
+        private_handle_t *hnd = (private_handle_t *)layer->handle;
+        if(isYUVSplitNeeded(hnd) && sEnableYUVsplit){
+            if(allocSplitVGPipesfor4k2k(ctx, index)){
+                continue;
+            }
+        }
+
+        int mdpIndex = mCurrentFrame.layerToMDP[index];
+        PipeLayerPair& info = mCurrentFrame.mdpToLayer[mdpIndex];
+        info.pipeInfo = new MdpPipeInfoNonSplit;
+        info.rot = NULL;
+        MdpPipeInfoNonSplit& pipe_info = *(MdpPipeInfoNonSplit*)info.pipeInfo;
+
+        Overlay::PipeSpecs pipeSpecs;
+        pipeSpecs.formatClass = isYuvBuffer(hnd) ?
+                Overlay::FORMAT_YUV : Overlay::FORMAT_RGB;
+        pipeSpecs.needsScaling = qhwc::needsScaling(layer) or
+                (qdutils::MDPVersion::getInstance().is8x26() and
+                ctx->dpyAttr[HWC_DISPLAY_PRIMARY].xres > 1024);
+        pipeSpecs.dpy = mDpy;
+        pipeSpecs.fb = false;
+        pipeSpecs.numActiveDisplays = ctx->numActiveDisplays;
+
+        pipe_info.index = ctx->mOverlay->getPipe(pipeSpecs);
+
+        if(pipe_info.index == ovutils::OV_INVALID) {
+            ALOGD_IF(isDebug(), "%s: Unable to get pipe", __FUNCTION__);
+            return false;
+        }
+    }
+    return true;
+}
+
+int MDPCompNonSplit::configure4k2kYuv(hwc_context_t *ctx, hwc_layer_1_t *layer,
+        PipeLayerPair& PipeLayerPair) {
+    MdpYUVPipeInfo& mdp_info =
+            *(static_cast<MdpYUVPipeInfo*>(PipeLayerPair.pipeInfo));
+    eZorder zOrder = static_cast<eZorder>(mdp_info.zOrder);
+    eMdpFlags mdpFlagsL = OV_MDP_BACKEND_COMPOSITION;
+    eDest lDest = mdp_info.lIndex;
+    eDest rDest = mdp_info.rIndex;
+
+    return configureSourceSplit(ctx, layer, mDpy, mdpFlagsL, zOrder,
+            lDest, rDest, &PipeLayerPair.rot);
+}
+
+bool MDPCompNonSplit::draw(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
+
+    if(!isEnabled() or !mModeOn) {
+        ALOGD_IF(isDebug(),"%s: MDP Comp not enabled/configured", __FUNCTION__);
+        return true;
+    }
+
+    overlay::Overlay& ov = *ctx->mOverlay;
+    LayerProp *layerProp = ctx->layerProp[mDpy];
+
+    int numHwLayers = ctx->listStats[mDpy].numAppLayers;
+    for(int i = 0; i < numHwLayers && mCurrentFrame.mdpCount; i++ )
+    {
+        if(mCurrentFrame.isFBComposed[i]) continue;
+
+        hwc_layer_1_t *layer = &list->hwLayers[i];
+        private_handle_t *hnd = (private_handle_t *)layer->handle;
+        if(!hnd) {
+            if (!(layer->flags & HWC_COLOR_FILL)) {
+                ALOGE("%s handle null", __FUNCTION__);
+                return false;
+            }
+            // No PLAY for Color layer
+            layerProp[i].mFlags &= ~HWC_MDPCOMP;
+            continue;
+        }
+
+        int mdpIndex = mCurrentFrame.layerToMDP[i];
+
+        if(isYUVSplitNeeded(hnd) && sEnableYUVsplit)
+        {
+            MdpYUVPipeInfo& pipe_info =
+                *(MdpYUVPipeInfo*)mCurrentFrame.mdpToLayer[mdpIndex].pipeInfo;
+            Rotator *rot = mCurrentFrame.mdpToLayer[mdpIndex].rot;
+            ovutils::eDest indexL = pipe_info.lIndex;
+            ovutils::eDest indexR = pipe_info.rIndex;
+            int fd = hnd->fd;
+            uint32_t offset = (uint32_t)hnd->offset;
+            if(rot) {
+                rot->queueBuffer(fd, offset);
+                fd = rot->getDstMemId();
+                offset = rot->getDstOffset();
+            }
+            if(indexL != ovutils::OV_INVALID) {
+                ovutils::eDest destL = (ovutils::eDest)indexL;
+                ALOGD_IF(isDebug(),"%s: MDP Comp: Drawing layer: %p hnd: %p \
+                        using  pipe: %d", __FUNCTION__, layer, hnd, indexL );
+                if (!ov.queueBuffer(fd, offset, destL)) {
+                    ALOGE("%s: queueBuffer failed for display:%d",
+                            __FUNCTION__, mDpy);
+                    return false;
+                }
+            }
+
+            if(indexR != ovutils::OV_INVALID) {
+                ovutils::eDest destR = (ovutils::eDest)indexR;
+                ALOGD_IF(isDebug(),"%s: MDP Comp: Drawing layer: %p hnd: %p \
+                        using  pipe: %d", __FUNCTION__, layer, hnd, indexR );
+                if (!ov.queueBuffer(fd, offset, destR)) {
+                    ALOGE("%s: queueBuffer failed for display:%d",
+                            __FUNCTION__, mDpy);
+                    return false;
+                }
+            }
+        }
+        else{
+            MdpPipeInfoNonSplit& pipe_info =
+            *(MdpPipeInfoNonSplit*)mCurrentFrame.mdpToLayer[mdpIndex].pipeInfo;
+            ovutils::eDest dest = pipe_info.index;
+            if(dest == ovutils::OV_INVALID) {
+                ALOGE("%s: Invalid pipe index (%d)", __FUNCTION__, dest);
+                return false;
+            }
+
+            if(!(layerProp[i].mFlags & HWC_MDPCOMP)) {
+                continue;
+            }
+
+            int fd = hnd->fd;
+            uint32_t offset = (uint32_t)hnd->offset;
+            int index = ctx->mPtorInfo.getPTORArrayIndex(i);
+            if (!mDpy && (index != -1)) {
+                hnd = ctx->mCopyBit[mDpy]->getCurrentRenderBuffer();
+                fd = hnd->fd;
+                offset = 0;
+            }
+
+            ALOGD_IF(isDebug(),"%s: MDP Comp: Drawing layer: %p hnd: %p \
+                    using  pipe: %d", __FUNCTION__, layer,
+                    hnd, dest );
+
+            Rotator *rot = mCurrentFrame.mdpToLayer[mdpIndex].rot;
+            if(rot) {
+                if(!rot->queueBuffer(fd, offset))
+                    return false;
+                fd = rot->getDstMemId();
+                offset = rot->getDstOffset();
+            }
+
+            if (!ov.queueBuffer(fd, offset, dest)) {
+                ALOGE("%s: queueBuffer failed for display:%d ",
+                        __FUNCTION__, mDpy);
+                return false;
+            }
+        }
+
+        layerProp[i].mFlags &= ~HWC_MDPCOMP;
+    }
+    return true;
+}
+
+//=============MDPCompSplit===================================================
+
+void MDPCompSplit::adjustForSourceSplit(hwc_context_t *ctx,
+         hwc_display_contents_1_t* list){
+    //if 4kx2k yuv layer is totally present in either in left half
+    //or right half then try splitting the yuv layer to avoid decimation
+    const int lSplit = getLeftSplit(ctx, mDpy);
+    if(mCurrentFrame.fbZ >= 0) {
+        for (int index = 0, mdpNextZOrder = 0; index < mCurrentFrame.layerCount;
+                index++) {
+            if(!mCurrentFrame.isFBComposed[index]) {
+                if(mdpNextZOrder == mCurrentFrame.fbZ) {
+                    mdpNextZOrder++;
+                }
+                mdpNextZOrder++;
+                hwc_layer_1_t* layer = &list->hwLayers[index];
+                private_handle_t *hnd = (private_handle_t *)layer->handle;
+                if(isYUVSplitNeeded(hnd)) {
+                    hwc_rect_t dst = layer->displayFrame;
+                    if((dst.left > lSplit) || (dst.right < lSplit)) {
+                        mCurrentFrame.mdpCount += 1;
+                    }
+                    if(mdpNextZOrder <= mCurrentFrame.fbZ)
+                        mCurrentFrame.fbZ += 1;
+                    mdpNextZOrder++;
+                }
+            }
+        }
+    }
+}
+
+bool MDPCompSplit::acquireMDPPipes(hwc_context_t *ctx, hwc_layer_1_t* layer,
+        MdpPipeInfoSplit& pipe_info) {
+
+    const int lSplit = getLeftSplit(ctx, mDpy);
+    private_handle_t *hnd = (private_handle_t *)layer->handle;
+    hwc_rect_t dst = layer->displayFrame;
+    pipe_info.lIndex = ovutils::OV_INVALID;
+    pipe_info.rIndex = ovutils::OV_INVALID;
+
+    Overlay::PipeSpecs pipeSpecs;
+    pipeSpecs.formatClass = isYuvBuffer(hnd) ?
+            Overlay::FORMAT_YUV : Overlay::FORMAT_RGB;
+    pipeSpecs.needsScaling = qhwc::needsScalingWithSplit(ctx, layer, mDpy);
+    pipeSpecs.dpy = mDpy;
+    pipeSpecs.mixer = Overlay::MIXER_LEFT;
+    pipeSpecs.fb = false;
+
+    // Acquire pipe only for the updating half
+    hwc_rect_t l_roi = ctx->listStats[mDpy].lRoi;
+    hwc_rect_t r_roi = ctx->listStats[mDpy].rRoi;
+
+    if (dst.left < lSplit && isValidRect(getIntersection(dst, l_roi))) {
+        pipe_info.lIndex = ctx->mOverlay->getPipe(pipeSpecs);
+        if(pipe_info.lIndex == ovutils::OV_INVALID)
+            return false;
+    }
+
+    if(dst.right > lSplit && isValidRect(getIntersection(dst, r_roi))) {
+        pipeSpecs.mixer = Overlay::MIXER_RIGHT;
+        pipe_info.rIndex = ctx->mOverlay->getPipe(pipeSpecs);
+        if(pipe_info.rIndex == ovutils::OV_INVALID)
+            return false;
+    }
+
+    return true;
+}
+
+bool MDPCompSplit::allocLayerPipes(hwc_context_t *ctx,
+        hwc_display_contents_1_t* list) {
+    for(int index = 0 ; index < mCurrentFrame.layerCount; index++) {
+
+        if(mCurrentFrame.isFBComposed[index]) continue;
+
+        hwc_layer_1_t* layer = &list->hwLayers[index];
+        private_handle_t *hnd = (private_handle_t *)layer->handle;
+        hwc_rect_t dst = layer->displayFrame;
+        const int lSplit = getLeftSplit(ctx, mDpy);
+        if(isYUVSplitNeeded(hnd) && sEnableYUVsplit){
+            if((dst.left > lSplit)||(dst.right < lSplit)){
+                if(allocSplitVGPipesfor4k2k(ctx, index)){
+                    continue;
+                }
+            }
+        }
+        int mdpIndex = mCurrentFrame.layerToMDP[index];
+        PipeLayerPair& info = mCurrentFrame.mdpToLayer[mdpIndex];
+        info.pipeInfo = new MdpPipeInfoSplit;
+        info.rot = NULL;
+        MdpPipeInfoSplit& pipe_info = *(MdpPipeInfoSplit*)info.pipeInfo;
+
+        if(!acquireMDPPipes(ctx, layer, pipe_info)) {
+            ALOGD_IF(isDebug(), "%s: Unable to get pipe for type",
+                    __FUNCTION__);
+            return false;
+        }
+    }
+    return true;
+}
+
+int MDPCompSplit::configure4k2kYuv(hwc_context_t *ctx, hwc_layer_1_t *layer,
+        PipeLayerPair& PipeLayerPair) {
+    const int lSplit = getLeftSplit(ctx, mDpy);
+    hwc_rect_t dst = layer->displayFrame;
+    if((dst.left > lSplit)||(dst.right < lSplit)){
+        MdpYUVPipeInfo& mdp_info =
+                *(static_cast<MdpYUVPipeInfo*>(PipeLayerPair.pipeInfo));
+        eZorder zOrder = static_cast<eZorder>(mdp_info.zOrder);
+        eMdpFlags mdpFlagsL = OV_MDP_BACKEND_COMPOSITION;
+        eDest lDest = mdp_info.lIndex;
+        eDest rDest = mdp_info.rIndex;
+
+        return configureSourceSplit(ctx, layer, mDpy, mdpFlagsL, zOrder,
+                lDest, rDest, &PipeLayerPair.rot);
+    }
+    else{
+        return configure(ctx, layer, PipeLayerPair);
+    }
+}
+
+/*
+ * Configures pipe(s) for MDP composition
+ */
+int MDPCompSplit::configure(hwc_context_t *ctx, hwc_layer_1_t *layer,
+        PipeLayerPair& PipeLayerPair) {
+    MdpPipeInfoSplit& mdp_info =
+        *(static_cast<MdpPipeInfoSplit*>(PipeLayerPair.pipeInfo));
+    eZorder zOrder = static_cast<eZorder>(mdp_info.zOrder);
+    eMdpFlags mdpFlagsL = OV_MDP_BACKEND_COMPOSITION;
+    eDest lDest = mdp_info.lIndex;
+    eDest rDest = mdp_info.rIndex;
+
+    ALOGD_IF(isDebug(),"%s: configuring: layer: %p z_order: %d dest_pipeL: %d"
+             "dest_pipeR: %d",__FUNCTION__, layer, zOrder, lDest, rDest);
+
+    return configureSplit(ctx, layer, mDpy, mdpFlagsL, zOrder, lDest,
+                            rDest, &PipeLayerPair.rot);
+}
+
+bool MDPCompSplit::draw(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
+
+    if(!isEnabled() or !mModeOn) {
+        ALOGD_IF(isDebug(),"%s: MDP Comp not enabled/configured", __FUNCTION__);
+        return true;
+    }
+
+    overlay::Overlay& ov = *ctx->mOverlay;
+    LayerProp *layerProp = ctx->layerProp[mDpy];
+
+    int numHwLayers = ctx->listStats[mDpy].numAppLayers;
+    for(int i = 0; i < numHwLayers && mCurrentFrame.mdpCount; i++ )
+    {
+        if(mCurrentFrame.isFBComposed[i]) continue;
+
+        hwc_layer_1_t *layer = &list->hwLayers[i];
+        private_handle_t *hnd = (private_handle_t *)layer->handle;
+        if(!hnd) {
+            ALOGE("%s handle null", __FUNCTION__);
+            return false;
+        }
+
+        if(!(layerProp[i].mFlags & HWC_MDPCOMP)) {
+            continue;
+        }
+
+        int mdpIndex = mCurrentFrame.layerToMDP[i];
+
+        if(isYUVSplitNeeded(hnd) && sEnableYUVsplit)
+        {
+            MdpYUVPipeInfo& pipe_info =
+                *(MdpYUVPipeInfo*)mCurrentFrame.mdpToLayer[mdpIndex].pipeInfo;
+            Rotator *rot = mCurrentFrame.mdpToLayer[mdpIndex].rot;
+            ovutils::eDest indexL = pipe_info.lIndex;
+            ovutils::eDest indexR = pipe_info.rIndex;
+            int fd = hnd->fd;
+            uint32_t offset = (uint32_t)hnd->offset;
+            if(rot) {
+                rot->queueBuffer(fd, offset);
+                fd = rot->getDstMemId();
+                offset = rot->getDstOffset();
+            }
+            if(indexL != ovutils::OV_INVALID) {
+                ovutils::eDest destL = (ovutils::eDest)indexL;
+                ALOGD_IF(isDebug(),"%s: MDP Comp: Drawing layer: %p hnd: %p \
+                        using  pipe: %d", __FUNCTION__, layer, hnd, indexL );
+                if (!ov.queueBuffer(fd, offset, destL)) {
+                    ALOGE("%s: queueBuffer failed for display:%d",
+                            __FUNCTION__, mDpy);
+                    return false;
+                }
+            }
+
+            if(indexR != ovutils::OV_INVALID) {
+                ovutils::eDest destR = (ovutils::eDest)indexR;
+                ALOGD_IF(isDebug(),"%s: MDP Comp: Drawing layer: %p hnd: %p \
+                        using  pipe: %d", __FUNCTION__, layer, hnd, indexR );
+                if (!ov.queueBuffer(fd, offset, destR)) {
+                    ALOGE("%s: queueBuffer failed for display:%d",
+                            __FUNCTION__, mDpy);
+                    return false;
+                }
+            }
+        }
+        else{
+            MdpPipeInfoSplit& pipe_info =
+                *(MdpPipeInfoSplit*)mCurrentFrame.mdpToLayer[mdpIndex].pipeInfo;
+            Rotator *rot = mCurrentFrame.mdpToLayer[mdpIndex].rot;
+
+            ovutils::eDest indexL = pipe_info.lIndex;
+            ovutils::eDest indexR = pipe_info.rIndex;
+
+            int fd = hnd->fd;
+            uint32_t offset = (uint32_t)hnd->offset;
+            int index = ctx->mPtorInfo.getPTORArrayIndex(i);
+            if (!mDpy && (index != -1)) {
+                hnd = ctx->mCopyBit[mDpy]->getCurrentRenderBuffer();
+                fd = hnd->fd;
+                offset = 0;
+            }
+
+            if(ctx->mAD->draw(ctx, fd, offset)) {
+                fd = ctx->mAD->getDstFd();
+                offset = ctx->mAD->getDstOffset();
+            }
+
+            if(rot) {
+                rot->queueBuffer(fd, offset);
+                fd = rot->getDstMemId();
+                offset = rot->getDstOffset();
+            }
+
+            //************* play left mixer **********
+            if(indexL != ovutils::OV_INVALID) {
+                ovutils::eDest destL = (ovutils::eDest)indexL;
+                ALOGD_IF(isDebug(),"%s: MDP Comp: Drawing layer: %p hnd: %p \
+                        using  pipe: %d", __FUNCTION__, layer, hnd, indexL );
+                if (!ov.queueBuffer(fd, offset, destL)) {
+                    ALOGE("%s: queueBuffer failed for left mixer",
+                            __FUNCTION__);
+                    return false;
+                }
+            }
+
+            //************* play right mixer **********
+            if(indexR != ovutils::OV_INVALID) {
+                ovutils::eDest destR = (ovutils::eDest)indexR;
+                ALOGD_IF(isDebug(),"%s: MDP Comp: Drawing layer: %p hnd: %p \
+                        using  pipe: %d", __FUNCTION__, layer, hnd, indexR );
+                if (!ov.queueBuffer(fd, offset, destR)) {
+                    ALOGE("%s: queueBuffer failed for right mixer",
+                            __FUNCTION__);
+                    return false;
+                }
+            }
+        }
+
+        layerProp[i].mFlags &= ~HWC_MDPCOMP;
+    }
+
+    return true;
+}
+
+//================MDPCompSrcSplit==============================================
+bool MDPCompSrcSplit::acquireMDPPipes(hwc_context_t *ctx, hwc_layer_1_t* layer,
+        MdpPipeInfoSplit& pipe_info) {
+    private_handle_t *hnd = (private_handle_t *)layer->handle;
+    hwc_rect_t dst = layer->displayFrame;
+    hwc_rect_t crop = integerizeSourceCrop(layer->sourceCropf);
+    pipe_info.lIndex = ovutils::OV_INVALID;
+    pipe_info.rIndex = ovutils::OV_INVALID;
+
+    //If 2 pipes are staged on a single stage of a mixer, then the left pipe
+    //should have a higher priority than the right one. Pipe priorities are
+    //starting with VG0, VG1 ... , RGB0 ..., DMA1
+
+    Overlay::PipeSpecs pipeSpecs;
+    pipeSpecs.formatClass = isYuvBuffer(hnd) ?
+            Overlay::FORMAT_YUV : Overlay::FORMAT_RGB;
+    pipeSpecs.needsScaling = qhwc::needsScaling(layer);
+    pipeSpecs.dpy = mDpy;
+    pipeSpecs.fb = false;
+
+    //1 pipe by default for a layer
+    pipe_info.lIndex = ctx->mOverlay->getPipe(pipeSpecs);
+    if(pipe_info.lIndex == ovutils::OV_INVALID) {
+        return false;
+    }
+
+    /* Use 2 pipes IF
+        a) Layer's crop width is > 2048 or
+        b) Layer's dest width > 2048 or
+        c) On primary, driver has indicated with caps to split always. This is
+           based on an empirically derived value of panel height. Applied only
+           if the layer's width is > mixer's width
+    */
+
+    MDPVersion& mdpHw = MDPVersion::getInstance();
+    bool primarySplitAlways = (mDpy == HWC_DISPLAY_PRIMARY) and
+            mdpHw.isSrcSplitAlways();
+    int lSplit = getLeftSplit(ctx, mDpy);
+    int dstWidth = dst.right - dst.left;
+    int cropWidth = has90Transform(layer) ? crop.bottom - crop.top :
+            crop.right - crop.left;
+
+    //TODO Even if a 4k video is going to be rot-downscaled to dimensions under
+    //pipe line length, we are still using 2 pipes. This is fine just because
+    //this is source split where destination doesn't matter. Evaluate later to
+    //see if going through all the calcs to save a pipe is worth it
+    if(dstWidth > (int) mdpHw.getMaxMixerWidth() or
+            cropWidth > (int) mdpHw.getMaxMixerWidth() or
+            (primarySplitAlways and (cropWidth > lSplit))) {
+        pipe_info.rIndex = ctx->mOverlay->getPipe(pipeSpecs);
+        if(pipe_info.rIndex == ovutils::OV_INVALID) {
+            return false;
+        }
+
+        // Return values
+        // 1  Left pipe is higher priority, do nothing.
+        // 0  Pipes of same priority.
+        //-1  Right pipe is of higher priority, needs swap.
+        if(ctx->mOverlay->comparePipePriority(pipe_info.lIndex,
+                pipe_info.rIndex) == -1) {
+            qhwc::swap(pipe_info.lIndex, pipe_info.rIndex);
+        }
+    }
+
+    return true;
+}
+
+int MDPCompSrcSplit::configure(hwc_context_t *ctx, hwc_layer_1_t *layer,
+        PipeLayerPair& PipeLayerPair) {
+    private_handle_t *hnd = (private_handle_t *)layer->handle;
+    if(!hnd) {
+        ALOGE("%s: layer handle is NULL", __FUNCTION__);
+        return -1;
+    }
+    MetaData_t *metadata = (MetaData_t *)hnd->base_metadata;
+    MdpPipeInfoSplit& mdp_info =
+        *(static_cast<MdpPipeInfoSplit*>(PipeLayerPair.pipeInfo));
+    Rotator **rot = &PipeLayerPair.rot;
+    eZorder z = static_cast<eZorder>(mdp_info.zOrder);
+    eDest lDest = mdp_info.lIndex;
+    eDest rDest = mdp_info.rIndex;
+    hwc_rect_t crop = integerizeSourceCrop(layer->sourceCropf);
+    hwc_rect_t dst = layer->displayFrame;
+    int transform = layer->transform;
+    eTransform orient = static_cast<eTransform>(transform);
+    int rotFlags = ROT_FLAGS_NONE;
+    uint32_t format = ovutils::getMdpFormat(hnd->format, isTileRendered(hnd));
+    Whf whf(getWidth(hnd), getHeight(hnd), format, hnd->size);
+
+    ALOGD_IF(isDebug(),"%s: configuring: layer: %p z_order: %d dest_pipeL: %d"
+             "dest_pipeR: %d",__FUNCTION__, layer, z, lDest, rDest);
+
+    // Handle R/B swap
+    if (layer->flags & HWC_FORMAT_RB_SWAP) {
+        if (hnd->format == HAL_PIXEL_FORMAT_RGBA_8888)
+            whf.format = getMdpFormat(HAL_PIXEL_FORMAT_BGRA_8888);
+        else if (hnd->format == HAL_PIXEL_FORMAT_RGBX_8888)
+            whf.format = getMdpFormat(HAL_PIXEL_FORMAT_BGRX_8888);
+    }
+    // update source crop and destination position of AIV video layer.
+    if(ctx->listStats[mDpy].mAIVVideoMode && isYuvBuffer(hnd)) {
+        updateCoordinates(ctx, crop, dst, mDpy);
+    }
+    /* Calculate the external display position based on MDP downscale,
+       ActionSafe, and extorientation features. */
+    calcExtDisplayPosition(ctx, hnd, mDpy, crop, dst, transform, orient);
+
+    int downscale = getRotDownscale(ctx, layer);
+    eMdpFlags mdpFlags = OV_MDP_BACKEND_COMPOSITION;
+    setMdpFlags(ctx, layer, mdpFlags, downscale, transform);
+
+    if(lDest != OV_INVALID && rDest != OV_INVALID) {
+        //Enable overfetch
+        setMdpFlags(mdpFlags, OV_MDSS_MDP_DUAL_PIPE);
+    }
+
+    if((has90Transform(layer) or downscale) and isRotationDoable(ctx, hnd)) {
+        (*rot) = ctx->mRotMgr->getNext();
+        if((*rot) == NULL) return -1;
+        ctx->mLayerRotMap[mDpy]->add(layer, *rot);
+        //If the video is using a single pipe, enable BWC
+        if(rDest == OV_INVALID) {
+            BwcPM::setBwc(crop, dst, transform, downscale, mdpFlags);
+        }
+        //Configure rotator for pre-rotation
+        if(configRotator(*rot, whf, crop, mdpFlags, orient, downscale) < 0) {
+            ALOGE("%s: configRotator failed!", __FUNCTION__);
+            return -1;
+        }
+        updateSource(orient, whf, crop, *rot);
+        rotFlags |= ovutils::ROT_PREROTATED;
+    }
+
+    //If 2 pipes being used, divide layer into half, crop and dst
+    hwc_rect_t cropL = crop;
+    hwc_rect_t cropR = crop;
+    hwc_rect_t dstL = dst;
+    hwc_rect_t dstR = dst;
+    if(lDest != OV_INVALID && rDest != OV_INVALID) {
+        cropL.right = (crop.right + crop.left) / 2;
+        cropR.left = cropL.right;
+        sanitizeSourceCrop(cropL, cropR, hnd);
+
+        bool cropSwap = false;
+        //Swap crops on H flip since 2 pipes are being used
+        if((orient & OVERLAY_TRANSFORM_FLIP_H) && (*rot) == NULL) {
+            hwc_rect_t tmp = cropL;
+            cropL = cropR;
+            cropR = tmp;
+            cropSwap = true;
+        }
+
+        //cropSwap trick: If the src and dst widths are both odd, let us say
+        //2507, then splitting both into half would cause left width to be 1253
+        //and right 1254. If crop is swapped because of H flip, this will cause
+        //left crop width to be 1254, whereas left dst width remains 1253, thus
+        //inducing a scaling that is unaccounted for. To overcome that we add 1
+        //to the dst width if there is a cropSwap. So if the original width was
+        //2507, the left dst width will be 1254. Even if the original width was
+        //even for ex: 2508, the left dst width will still remain 1254.
+        dstL.right = (dst.right + dst.left + cropSwap) / 2;
+        dstR.left = dstL.right;
+    }
+
+    //For the mdp, since either we are pre-rotating or MDP does flips
+    orient = OVERLAY_TRANSFORM_0;
+    transform = 0;
+
+    //configure left pipe
+    if(lDest != OV_INVALID) {
+        PipeArgs pargL(mdpFlags, whf, z,
+                static_cast<eRotFlags>(rotFlags), layer->planeAlpha,
+                (ovutils::eBlending) getBlending(layer->blending));
+
+        if(configMdp(ctx->mOverlay, pargL, orient,
+                    cropL, dstL, metadata, lDest) < 0) {
+            ALOGE("%s: commit failed for left mixer config", __FUNCTION__);
+            return -1;
+        }
+    }
+
+    //configure right pipe
+    if(rDest != OV_INVALID) {
+        PipeArgs pargR(mdpFlags, whf, z,
+                static_cast<eRotFlags>(rotFlags),
+                layer->planeAlpha,
+                (ovutils::eBlending) getBlending(layer->blending));
+        if(configMdp(ctx->mOverlay, pargR, orient,
+                    cropR, dstR, metadata, rDest) < 0) {
+            ALOGE("%s: commit failed for right mixer config", __FUNCTION__);
+            return -1;
+        }
+    }
+
+    return 0;
+}
+
+int MDPComp::getPartialUpdatePref(hwc_context_t *ctx) {
+    Locker::Autolock _l(ctx->mDrawLock);
+    const int fbNum = Overlay::getFbForDpy(Overlay::DPY_PRIMARY);
+    char path[MAX_SYSFS_FILE_PATH];
+    snprintf (path, sizeof(path), "sys/class/graphics/fb%d/dyn_pu", fbNum);
+    int fd = open(path, O_RDONLY);
+    if(fd < 0) {
+        ALOGE("%s: Failed to open sysfs node: %s", __FUNCTION__, path);
+        return -1;
+    }
+    char value[4];
+    ssize_t size_read = read(fd, value, sizeof(value)-1);
+    if(size_read <= 0) {
+        ALOGE("%s: Failed to read sysfs node: %s", __FUNCTION__, path);
+        close(fd);
+        return -1;
+    }
+    close(fd);
+    value[size_read] = '\0';
+    return atoi(value);
+}
+
+int MDPComp::setPartialUpdatePref(hwc_context_t *ctx, bool enable) {
+    Locker::Autolock _l(ctx->mDrawLock);
+    const int fbNum = Overlay::getFbForDpy(Overlay::DPY_PRIMARY);
+    char path[MAX_SYSFS_FILE_PATH];
+    snprintf (path, sizeof(path), "sys/class/graphics/fb%d/dyn_pu", fbNum);
+    int fd = open(path, O_WRONLY);
+    if(fd < 0) {
+        ALOGE("%s: Failed to open sysfs node: %s", __FUNCTION__, path);
+        return -1;
+    }
+    char value[4];
+    snprintf(value, sizeof(value), "%d", (int)enable);
+    ssize_t ret = write(fd, value, strlen(value));
+    if(ret <= 0) {
+        ALOGE("%s: Failed to write to sysfs nodes: %s", __FUNCTION__, path);
+        close(fd);
+        return -1;
+    }
+    close(fd);
+    return 0;
+}
+}; //namespace
+
diff --git a/msm8909/libhwcomposer/hwc_mdpcomp.h b/msm8909/libhwcomposer/hwc_mdpcomp.h
new file mode 100644
index 0000000..e6b0228
--- /dev/null
+++ b/msm8909/libhwcomposer/hwc_mdpcomp.h
@@ -0,0 +1,371 @@
+/*
+ * Copyright (C) 2012-2015, The Linux Foundation. All rights reserved.
+ *
+ * Not a Contribution, Apache license notifications and license are retained
+ * for attribution purposes only.
+ *
+ * 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 HWC_MDP_COMP
+#define HWC_MDP_COMP
+
+#include <hwc_utils.h>
+#include <idle_invalidator.h>
+#include <cutils/properties.h>
+#include <overlay.h>
+
+#define MAX_PIPES_PER_MIXER 4
+
+namespace overlay {
+class Rotator;
+};
+
+namespace qhwc {
+namespace ovutils = overlay::utils;
+
+class MDPComp {
+public:
+    explicit MDPComp(int);
+    virtual ~MDPComp(){};
+    /*sets up mdp comp for the current frame */
+    int prepare(hwc_context_t *ctx, hwc_display_contents_1_t* list);
+    /* draw */
+    virtual bool draw(hwc_context_t *ctx, hwc_display_contents_1_t *list) = 0;
+    //Reset values
+    void reset();
+    /* dumpsys */
+    void dump(android::String8& buf, hwc_context_t *ctx);
+    bool isGLESOnlyComp() { return (mCurrentFrame.mdpCount == 0); }
+    bool isMDPComp() { return mModeOn; }
+    int drawOverlap(hwc_context_t *ctx, hwc_display_contents_1_t* list);
+    static MDPComp* getObject(hwc_context_t *ctx, const int& dpy);
+    /* Handler to invoke frame redraw on Idle Timer expiry */
+    static void timeout_handler(void *udata);
+    /* Initialize MDP comp*/
+    static bool init(hwc_context_t *ctx);
+    static void resetIdleFallBack() { sIdleFallBack = false; }
+    static bool isIdleFallback() { return sIdleFallBack; }
+    static void dynamicDebug(bool enable){ sDebugLogs = enable; }
+    static void setIdleTimeout(const uint32_t& timeout);
+    static int setPartialUpdatePref(hwc_context_t *ctx, bool enable);
+    void setDynRefreshRate(hwc_context_t *ctx, hwc_display_contents_1_t* list);
+    static int getPartialUpdatePref(hwc_context_t *ctx);
+    static void enablePartialUpdate(bool enable)
+                                          { sIsPartialUpdateActive = enable; };
+
+protected:
+    enum { MAX_SEC_LAYERS = 1 }; //TODO add property support
+
+    enum ePipeType {
+        MDPCOMP_OV_RGB = ovutils::OV_MDP_PIPE_RGB,
+        MDPCOMP_OV_VG = ovutils::OV_MDP_PIPE_VG,
+        MDPCOMP_OV_DMA = ovutils::OV_MDP_PIPE_DMA,
+        MDPCOMP_OV_ANY,
+    };
+
+    //Simulation flags
+    enum {
+        MDPCOMP_AVOID_FULL_MDP = 0x001,
+        MDPCOMP_AVOID_CACHE_MDP = 0x002,
+        MDPCOMP_AVOID_LOAD_MDP = 0x004,
+        MDPCOMP_AVOID_VIDEO_ONLY = 0x008,
+        MDPCOMP_AVOID_MDP_ONLY_LAYERS = 0x010,
+    };
+
+    /* mdp pipe data */
+    struct MdpPipeInfo {
+        int zOrder;
+        virtual ~MdpPipeInfo(){};
+    };
+
+    struct MdpYUVPipeInfo : public MdpPipeInfo{
+        ovutils::eDest lIndex;
+        ovutils::eDest rIndex;
+        virtual ~MdpYUVPipeInfo(){};
+    };
+
+    /* per layer data */
+    struct PipeLayerPair {
+        MdpPipeInfo *pipeInfo;
+        overlay::Rotator* rot;
+        int listIndex;
+    };
+
+    /* per frame data */
+    struct FrameInfo {
+        /* maps layer list to mdp list */
+        int layerCount;
+        int layerToMDP[MAX_NUM_APP_LAYERS];
+
+        /* maps mdp list to layer list */
+        int mdpCount;
+        struct PipeLayerPair mdpToLayer[MAX_PIPES_PER_MIXER];
+
+        /* layer composing on FB? */
+        int fbCount;
+        bool isFBComposed[MAX_NUM_APP_LAYERS];
+        /* layers lying outside ROI. Will
+         * be dropped off from the composition */
+        int dropCount;
+        bool drop[MAX_NUM_APP_LAYERS];
+
+        bool needsRedraw;
+        int fbZ;
+
+        /* c'tor */
+        FrameInfo();
+        /* clear old frame data */
+        void reset(const int& numLayers);
+        void map();
+    };
+
+    /* cached data */
+    struct LayerCache {
+        int layerCount;
+        bool isFBComposed[MAX_NUM_APP_LAYERS];
+        bool drop[MAX_NUM_APP_LAYERS];
+
+        /* c'tor */
+        LayerCache();
+        /* clear caching info*/
+        void reset();
+        void updateCounts(const FrameInfo&);
+        bool isSameFrame(const FrameInfo& curFrame,
+                         hwc_display_contents_1_t* list);
+        bool isSameFrame(hwc_context_t *ctx, int dpy,
+                                        hwc_display_contents_1_t* list);
+    };
+
+    /* allocates pipe from pipe book */
+    virtual bool allocLayerPipes(hwc_context_t *ctx,
+                                 hwc_display_contents_1_t* list) = 0;
+    /* configures MPD pipes */
+    virtual int configure(hwc_context_t *ctx, hwc_layer_1_t *layer,
+                          PipeLayerPair& pipeLayerPair) = 0;
+    /* Increments mdpCount if 4k2k yuv layer split is enabled.
+     * updates framebuffer z order if fb lies above source-split layer */
+    virtual void adjustForSourceSplit(hwc_context_t *ctx,
+            hwc_display_contents_1_t* list) = 0;
+    /* configures 4kx2k yuv layer*/
+    virtual int configure4k2kYuv(hwc_context_t *ctx, hwc_layer_1_t *layer,
+            PipeLayerPair& PipeLayerPair) = 0;
+    /* generates ROI based on the modified area of the frame */
+    virtual void generateROI(hwc_context_t *ctx,
+            hwc_display_contents_1_t* list) = 0;
+    /* validates the ROI generated for fallback conditions */
+    virtual bool validateAndApplyROI(hwc_context_t *ctx,
+            hwc_display_contents_1_t* list) = 0;
+    /* Trims fbRect calculated against ROI generated */
+    virtual void trimAgainstROI(hwc_context_t *ctx, hwc_rect_t& fbRect) = 0;
+
+    /* set/reset flags for MDPComp */
+    void setMDPCompLayerFlags(hwc_context_t *ctx,
+                              hwc_display_contents_1_t* list);
+    void setRedraw(hwc_context_t *ctx,
+            hwc_display_contents_1_t* list);
+    /* checks for conditions where mdpcomp is not possible */
+    bool isFrameDoable(hwc_context_t *ctx);
+    /* checks for conditions where RGB layers cannot be bypassed */
+    bool tryFullFrame(hwc_context_t *ctx, hwc_display_contents_1_t* list);
+    /* checks if full MDP comp can be done */
+    bool fullMDPComp(hwc_context_t *ctx, hwc_display_contents_1_t* list);
+    /* Full MDP Composition with Peripheral Tiny Overlap Removal */
+    bool fullMDPCompWithPTOR(hwc_context_t *ctx,hwc_display_contents_1_t* list);
+    /* check if we can use layer cache to do at least partial MDP comp */
+    bool partialMDPComp(hwc_context_t *ctx, hwc_display_contents_1_t* list);
+    /* Partial MDP comp that uses caching to save power as primary goal */
+    bool cacheBasedComp(hwc_context_t *ctx, hwc_display_contents_1_t* list);
+    /* Partial MDP comp that balances the load between MDP and GPU such that
+     * MDP is loaded to the max of its capacity. The lower z order layers are
+     * fed to MDP, whereas the upper ones to GPU, because the upper ones have
+     * lower number of pixels and can reduce GPU processing time */
+    bool loadBasedComp(hwc_context_t *ctx, hwc_display_contents_1_t* list);
+    /* Checks if its worth doing load based partial comp */
+    bool isLoadBasedCompDoable(hwc_context_t *ctx);
+    /* checks for conditions where only video can be bypassed */
+    bool tryVideoOnly(hwc_context_t *ctx, hwc_display_contents_1_t* list);
+    bool videoOnlyComp(hwc_context_t *ctx, hwc_display_contents_1_t* list,
+            bool secureOnly);
+    /* checks for conditions where only secure RGB and video can be bypassed */
+    bool tryMDPOnlyLayers(hwc_context_t *ctx, hwc_display_contents_1_t* list);
+    bool mdpOnlyLayersComp(hwc_context_t *ctx, hwc_display_contents_1_t* list,
+            bool secureOnly);
+    /* checks for conditions where YUV layers cannot be bypassed */
+    bool isYUVDoable(hwc_context_t* ctx, hwc_layer_1_t* layer);
+    /* checks for conditions where Secure RGB layers cannot be bypassed */
+    bool isSecureRGBDoable(hwc_context_t* ctx, hwc_layer_1_t* layer);
+    /* checks if MDP/MDSS can process current list w.r.to HW limitations
+     * All peculiar HW limitations should go here */
+    bool hwLimitationsCheck(hwc_context_t* ctx, hwc_display_contents_1_t* list);
+    /* Is debug enabled */
+    static bool isDebug() { return sDebugLogs ? true : false; };
+    /* Is feature enabled */
+    static bool isEnabled() { return sEnabled; };
+    /* checks for mdp comp dimension limitation */
+    bool isValidDimension(hwc_context_t *ctx, hwc_layer_1_t *layer);
+    /* tracks non updating layers*/
+    void updateLayerCache(hwc_context_t* ctx, hwc_display_contents_1_t* list,
+                          FrameInfo& frame);
+    /* optimize layers for mdp comp*/
+    bool markLayersForCaching(hwc_context_t* ctx,
+            hwc_display_contents_1_t* list);
+    int getBatch(hwc_display_contents_1_t* list,
+            int& maxBatchStart, int& maxBatchEnd,
+            int& maxBatchCount);
+    bool canPushBatchToTop(const hwc_display_contents_1_t* list,
+            int fromIndex, int toIndex);
+    bool intersectingUpdatingLayers(const hwc_display_contents_1_t* list,
+            int fromIndex, int toIndex, int targetLayerIndex);
+
+    /* drop other non-AIV layers from external display list.*/
+    void dropNonAIVLayers(hwc_context_t* ctx, hwc_display_contents_1_t* list);
+
+        /* updates cache map with YUV info */
+    void updateYUV(hwc_context_t* ctx, hwc_display_contents_1_t* list,
+            bool secureOnly, FrameInfo& frame);
+    /* updates cache map with secure RGB info */
+    void updateSecureRGB(hwc_context_t* ctx,
+            hwc_display_contents_1_t* list);
+    /* Validates if the GPU/MDP layer split chosen by a strategy is supported
+     * by MDP.
+     * Sets up MDP comp data structures to reflect covnversion from layers to
+     * overlay pipes.
+     * Configures overlay.
+     * Configures if GPU should redraw.
+     */
+    bool postHeuristicsHandling(hwc_context_t *ctx,
+            hwc_display_contents_1_t* list);
+    void reset(hwc_context_t *ctx);
+    bool isSupportedForMDPComp(hwc_context_t *ctx, hwc_layer_1_t* layer);
+    bool resourceCheck(hwc_context_t* ctx, hwc_display_contents_1_t* list);
+    hwc_rect_t getUpdatingFBRect(hwc_context_t *ctx,
+            hwc_display_contents_1_t* list);
+    /* checks for conditions to enable partial udpate */
+    bool canPartialUpdate(hwc_context_t *ctx, hwc_display_contents_1_t* list);
+
+    int mDpy;
+    static bool sEnabled;
+    static bool sEnableMixedMode;
+    static int sSimulationFlags;
+    static bool sDebugLogs;
+    static bool sIdleFallBack;
+    static int sMaxPipesPerMixer;
+    static bool sSrcSplitEnabled;
+    static IdleInvalidator *sIdleInvalidator;
+    struct FrameInfo mCurrentFrame;
+    struct LayerCache mCachedFrame;
+    static bool sIsPartialUpdateActive;
+    //Enable 4kx2k yuv layer split
+    static bool sEnableYUVsplit;
+    bool mModeOn; // if prepare happened
+    bool allocSplitVGPipesfor4k2k(hwc_context_t *ctx, int index);
+    bool mPrevModeOn; //if previous prepare happened
+    //Enable Partial Update for MDP3 targets
+    static bool enablePartialUpdateForMDP3;
+};
+
+class MDPCompNonSplit : public MDPComp {
+public:
+    explicit MDPCompNonSplit(int dpy):MDPComp(dpy){};
+    virtual ~MDPCompNonSplit(){};
+    virtual bool draw(hwc_context_t *ctx, hwc_display_contents_1_t *list);
+
+private:
+    struct MdpPipeInfoNonSplit : public MdpPipeInfo {
+        ovutils::eDest index;
+        virtual ~MdpPipeInfoNonSplit() {};
+    };
+
+    /* configure's overlay pipes for the frame */
+    virtual int configure(hwc_context_t *ctx, hwc_layer_1_t *layer,
+                          PipeLayerPair& pipeLayerPair);
+
+    /* allocates pipes to selected candidates */
+    virtual bool allocLayerPipes(hwc_context_t *ctx,
+                                 hwc_display_contents_1_t* list);
+
+    /* Increments mdpCount if 4k2k yuv layer split is enabled.
+     * updates framebuffer z order if fb lies above source-split layer */
+    virtual void adjustForSourceSplit(hwc_context_t *ctx,
+            hwc_display_contents_1_t* list);
+
+    /* configures 4kx2k yuv layer to 2 VG pipes*/
+    virtual int configure4k2kYuv(hwc_context_t *ctx, hwc_layer_1_t *layer,
+            PipeLayerPair& PipeLayerPair);
+    /* generates ROI based on the modified area of the frame */
+    virtual void generateROI(hwc_context_t *ctx,
+            hwc_display_contents_1_t* list);
+    /* validates the ROI generated for fallback conditions */
+    virtual bool validateAndApplyROI(hwc_context_t *ctx,
+            hwc_display_contents_1_t* list);
+    /* Trims fbRect calculated against ROI generated */
+    virtual void trimAgainstROI(hwc_context_t *ctx, hwc_rect_t& fbRect);
+};
+
+class MDPCompSplit : public MDPComp {
+public:
+    explicit MDPCompSplit(int dpy):MDPComp(dpy){};
+    virtual ~MDPCompSplit(){};
+    virtual bool draw(hwc_context_t *ctx, hwc_display_contents_1_t *list);
+
+protected:
+    struct MdpPipeInfoSplit : public MdpPipeInfo {
+        ovutils::eDest lIndex;
+        ovutils::eDest rIndex;
+        virtual ~MdpPipeInfoSplit() {};
+    };
+
+    virtual bool acquireMDPPipes(hwc_context_t *ctx, hwc_layer_1_t* layer,
+                         MdpPipeInfoSplit& pipe_info);
+
+    /* configure's overlay pipes for the frame */
+    virtual int configure(hwc_context_t *ctx, hwc_layer_1_t *layer,
+                          PipeLayerPair& pipeLayerPair);
+
+    /* allocates pipes to selected candidates */
+    virtual bool allocLayerPipes(hwc_context_t *ctx,
+                                 hwc_display_contents_1_t* list);
+private:
+    /* Increments mdpCount if 4k2k yuv layer split is enabled.
+     * updates framebuffer z order if fb lies above source-split layer */
+    virtual void adjustForSourceSplit(hwc_context_t *ctx,
+            hwc_display_contents_1_t* list);
+
+    /* configures 4kx2k yuv layer*/
+    virtual int configure4k2kYuv(hwc_context_t *ctx, hwc_layer_1_t *layer,
+            PipeLayerPair& PipeLayerPair);
+    /* generates ROI based on the modified area of the frame */
+    virtual void generateROI(hwc_context_t *ctx,
+            hwc_display_contents_1_t* list);
+    /* validates the ROI generated for fallback conditions */
+    virtual bool validateAndApplyROI(hwc_context_t *ctx,
+            hwc_display_contents_1_t* list);
+    /* Trims fbRect calculated against ROI generated */
+    virtual void trimAgainstROI(hwc_context_t *ctx, hwc_rect_t& fbRect);
+};
+
+class MDPCompSrcSplit : public MDPCompSplit {
+public:
+    explicit MDPCompSrcSplit(int dpy) : MDPCompSplit(dpy){};
+    virtual ~MDPCompSrcSplit(){};
+private:
+    virtual bool acquireMDPPipes(hwc_context_t *ctx, hwc_layer_1_t* layer,
+            MdpPipeInfoSplit& pipe_info);
+
+    virtual int configure(hwc_context_t *ctx, hwc_layer_1_t *layer,
+            PipeLayerPair& pipeLayerPair);
+};
+
+}; //namespace
+#endif
diff --git a/msm8909/libhwcomposer/hwc_qclient.cpp b/msm8909/libhwcomposer/hwc_qclient.cpp
new file mode 100644
index 0000000..4db4fa7
--- /dev/null
+++ b/msm8909/libhwcomposer/hwc_qclient.cpp
@@ -0,0 +1,401 @@
+/*
+ *  Copyright (c) 2013-15, The Linux Foundation. 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 The Linux Foundation 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 CLIENTS; 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.
+ */
+
+#include <hwc_qclient.h>
+#include <IQService.h>
+#include <hwc_utils.h>
+#include <mdp_version.h>
+#include <hwc_mdpcomp.h>
+#include <hwc_virtual.h>
+#include <overlay.h>
+#include <display_config.h>
+#include <hwc_qdcm.h>
+
+#define QCLIENT_DEBUG 0
+
+using namespace android;
+using namespace qService;
+using namespace qhwc;
+using namespace overlay;
+using namespace qdutils;
+using namespace qQdcm;
+
+namespace qClient {
+
+// ----------------------------------------------------------------------------
+QClient::QClient(hwc_context_t *ctx) : mHwcContext(ctx),
+        mMPDeathNotifier(new MPDeathNotifier(ctx))
+{
+    ALOGD_IF(QCLIENT_DEBUG, "QClient Constructor invoked");
+}
+
+QClient::~QClient()
+{
+    ALOGD_IF(QCLIENT_DEBUG,"QClient Destructor invoked");
+}
+
+static void securing(hwc_context_t *ctx, uint32_t startEnd) {
+    //The only way to make this class in this process subscribe to media
+    //player's death.
+    IMediaDeathNotifier::getMediaPlayerService();
+
+    ctx->mDrawLock.lock();
+    ctx->mSecuring = startEnd;
+    //We're done securing
+    if(startEnd == IQService::END)
+        ctx->mSecureMode = true;
+    ctx->mDrawLock.unlock();
+
+    if(ctx->proc)
+        ctx->proc->invalidate(ctx->proc);
+}
+
+static void unsecuring(hwc_context_t *ctx, uint32_t startEnd) {
+    ctx->mDrawLock.lock();
+    ctx->mSecuring = startEnd;
+    //We're done unsecuring
+    if(startEnd == IQService::END)
+        ctx->mSecureMode = false;
+    ctx->mDrawLock.unlock();
+
+    if(ctx->proc)
+        ctx->proc->invalidate(ctx->proc);
+}
+
+void QClient::MPDeathNotifier::died() {
+    mHwcContext->mDrawLock.lock();
+    ALOGD_IF(QCLIENT_DEBUG, "Media Player died");
+    mHwcContext->mSecuring = false;
+    mHwcContext->mSecureMode = false;
+    mHwcContext->mDrawLock.unlock();
+    if(mHwcContext->proc)
+        mHwcContext->proc->invalidate(mHwcContext->proc);
+}
+
+static android::status_t screenRefresh(hwc_context_t *ctx) {
+    status_t result = NO_INIT;
+    if(ctx->proc) {
+        ctx->proc->invalidate(ctx->proc);
+        result = NO_ERROR;
+    }
+    return result;
+}
+
+static void setExtOrientation(hwc_context_t *ctx, uint32_t orientation) {
+    ctx->mExtOrientation = orientation;
+}
+
+static void isExternalConnected(hwc_context_t* ctx, Parcel* outParcel) {
+    int connected;
+    connected = ctx->dpyAttr[HWC_DISPLAY_EXTERNAL].connected ? 1 : 0;
+    outParcel->writeInt32(connected);
+}
+
+static void getDisplayAttributes(hwc_context_t* ctx, const Parcel* inParcel,
+        Parcel* outParcel) {
+    int dpy = inParcel->readInt32();
+    outParcel->writeInt32(ctx->dpyAttr[dpy].vsync_period);
+    if (ctx->dpyAttr[dpy].customFBSize) {
+        outParcel->writeInt32(ctx->dpyAttr[dpy].xres_new);
+        outParcel->writeInt32(ctx->dpyAttr[dpy].yres_new);
+    } else {
+        outParcel->writeInt32(ctx->dpyAttr[dpy].xres);
+        outParcel->writeInt32(ctx->dpyAttr[dpy].yres);
+    }
+    outParcel->writeFloat(ctx->dpyAttr[dpy].xdpi);
+    outParcel->writeFloat(ctx->dpyAttr[dpy].ydpi);
+    //XXX: Need to check what to return for HDMI
+    outParcel->writeInt32(ctx->mMDP.panel);
+}
+static void setHSIC(const Parcel* inParcel) {
+    int dpy = inParcel->readInt32();
+    ALOGD_IF(0, "In %s: dpy = %d", __FUNCTION__, dpy);
+    HSICData_t hsic_data;
+    hsic_data.hue = inParcel->readInt32();
+    hsic_data.saturation = inParcel->readFloat();
+    hsic_data.intensity = inParcel->readInt32();
+    hsic_data.contrast = inParcel->readFloat();
+    //XXX: Actually set the HSIC data through ABL lib
+}
+
+
+static void setBufferMirrorMode(hwc_context_t *ctx, uint32_t enable) {
+    ctx->mBufferMirrorMode = enable;
+}
+
+static status_t getDisplayVisibleRegion(hwc_context_t* ctx, int dpy,
+                                Parcel* outParcel) {
+    // Get the info only if the dpy is valid
+    if(dpy >= HWC_DISPLAY_PRIMARY && dpy <= HWC_DISPLAY_VIRTUAL) {
+        Locker::Autolock _sl(ctx->mDrawLock);
+        if(dpy && (ctx->mExtOrientation || ctx->mBufferMirrorMode)) {
+            // Return the destRect on external, if external orienation
+            // is enabled
+            outParcel->writeInt32(ctx->dpyAttr[dpy].mDstRect.left);
+            outParcel->writeInt32(ctx->dpyAttr[dpy].mDstRect.top);
+            outParcel->writeInt32(ctx->dpyAttr[dpy].mDstRect.right);
+            outParcel->writeInt32(ctx->dpyAttr[dpy].mDstRect.bottom);
+        } else {
+            outParcel->writeInt32(ctx->mViewFrame[dpy].left);
+            outParcel->writeInt32(ctx->mViewFrame[dpy].top);
+            outParcel->writeInt32(ctx->mViewFrame[dpy].right);
+            outParcel->writeInt32(ctx->mViewFrame[dpy].bottom);
+        }
+        return NO_ERROR;
+    } else {
+        ALOGE("In %s: invalid dpy index %d", __FUNCTION__, dpy);
+        return BAD_VALUE;
+    }
+}
+
+// USed for setting the secondary(hdmi/wfd) status
+static void setSecondaryDisplayStatus(hwc_context_t *ctx,
+                                      const Parcel* inParcel) {
+    uint32_t dpy = inParcel->readInt32();
+    uint32_t status = inParcel->readInt32();
+    ALOGD_IF(QCLIENT_DEBUG, "%s: dpy = %d status = %s", __FUNCTION__,
+                                        dpy, getExternalDisplayState(status));
+
+    if(dpy > HWC_DISPLAY_PRIMARY && dpy <= HWC_DISPLAY_VIRTUAL) {
+        if(dpy == HWC_DISPLAY_VIRTUAL && status == qdutils::EXTERNAL_OFFLINE) {
+            ctx->mWfdSyncLock.lock();
+            ctx->mWfdSyncLock.signal();
+            ctx->mWfdSyncLock.unlock();
+        } else if(status == qdutils::EXTERNAL_PAUSE) {
+            handle_pause(ctx, dpy);
+        } else if(status == qdutils::EXTERNAL_RESUME) {
+            handle_resume(ctx, dpy);
+        }
+    } else {
+        ALOGE("%s: Invalid dpy %d", __FUNCTION__, dpy);
+        return;
+    }
+}
+
+
+static status_t setViewFrame(hwc_context_t* ctx, const Parcel* inParcel) {
+    int dpy = inParcel->readInt32();
+    if(dpy >= HWC_DISPLAY_PRIMARY && dpy <= HWC_DISPLAY_VIRTUAL) {
+        Locker::Autolock _sl(ctx->mDrawLock);
+        ctx->mViewFrame[dpy].left   = inParcel->readInt32();
+        ctx->mViewFrame[dpy].top    = inParcel->readInt32();
+        ctx->mViewFrame[dpy].right  = inParcel->readInt32();
+        ctx->mViewFrame[dpy].bottom = inParcel->readInt32();
+        ALOGD_IF(QCLIENT_DEBUG, "%s: mViewFrame[%d] = [%d %d %d %d]",
+            __FUNCTION__, dpy,
+            ctx->mViewFrame[dpy].left, ctx->mViewFrame[dpy].top,
+            ctx->mViewFrame[dpy].right, ctx->mViewFrame[dpy].bottom);
+        return NO_ERROR;
+    } else {
+        ALOGE("In %s: invalid dpy index %d", __FUNCTION__, dpy);
+        return BAD_VALUE;
+    }
+}
+
+static void toggleDynamicDebug(hwc_context_t* ctx, const Parcel* inParcel) {
+    int debug_type = inParcel->readInt32();
+    bool enable = !!inParcel->readInt32();
+    ALOGD("%s: debug_type: %d enable:%d",
+            __FUNCTION__, debug_type, enable);
+    Locker::Autolock _sl(ctx->mDrawLock);
+    switch (debug_type) {
+        //break is ignored for DEBUG_ALL to toggle all of them at once
+        case IQService::DEBUG_ALL:
+        case IQService::DEBUG_MDPCOMP:
+            qhwc::MDPComp::dynamicDebug(enable);
+            if (debug_type != IQService::DEBUG_ALL)
+                break;
+        case IQService::DEBUG_VSYNC:
+            ctx->vstate.debug = enable;
+            if (debug_type != IQService::DEBUG_ALL)
+                break;
+        case IQService::DEBUG_VD:
+            HWCVirtualVDS::dynamicDebug(enable);
+            if (debug_type != IQService::DEBUG_ALL)
+                break;
+        case IQService::DEBUG_PIPE_LIFECYCLE:
+            Overlay::debugPipeLifecycle(enable);
+            if (debug_type != IQService::DEBUG_ALL)
+                break;
+    }
+}
+
+static void setIdleTimeout(hwc_context_t* ctx, const Parcel* inParcel) {
+    uint32_t timeout = (uint32_t)inParcel->readInt32();
+    ALOGD("%s :%u ms", __FUNCTION__, timeout);
+    Locker::Autolock _sl(ctx->mDrawLock);
+    MDPComp::setIdleTimeout(timeout);
+}
+
+static void configureDynRefreshRate(hwc_context_t* ctx,
+                                    const Parcel* inParcel) {
+    uint32_t op = (uint32_t)inParcel->readInt32();
+    uint32_t refresh_rate = (uint32_t)inParcel->readInt32();
+    MDPVersion& mdpHw = MDPVersion::getInstance();
+    uint32_t dpy = HWC_DISPLAY_PRIMARY;
+
+    if(mdpHw.isDynFpsSupported()) {
+        Locker::Autolock _sl(ctx->mDrawLock);
+
+        switch (op) {
+        case DISABLE_METADATA_DYN_REFRESH_RATE:
+            ctx->mUseMetaDataRefreshRate = false;
+            setRefreshRate(ctx, dpy, ctx->dpyAttr[dpy].refreshRate);
+            break;
+        case ENABLE_METADATA_DYN_REFRESH_RATE:
+            ctx->mUseMetaDataRefreshRate = true;
+            setRefreshRate(ctx, dpy, ctx->dpyAttr[dpy].refreshRate);
+            break;
+        case SET_BINDER_DYN_REFRESH_RATE:
+            if(ctx->mUseMetaDataRefreshRate)
+                ALOGW("%s: Ignoring binder request to change refresh-rate",
+                      __FUNCTION__);
+            else {
+                uint32_t rate = roundOff(refresh_rate);
+                if((rate >= mdpHw.getMinFpsSupported() &&
+                    rate <= mdpHw.getMaxFpsSupported())) {
+                    setRefreshRate(ctx, dpy, rate);
+                } else {
+                    ALOGE("%s: Requested refresh-rate should be between \
+                          (%d) and (%d). Given (%d)", __FUNCTION__,
+                          mdpHw.getMinFpsSupported(),
+                          mdpHw.getMaxFpsSupported(), rate);
+                }
+            }
+            break;
+        default:
+            ALOGE("%s: Invalid op %d",__FUNCTION__,op);
+        }
+    }
+}
+
+static status_t setPartialUpdateState(hwc_context_t *ctx, uint32_t state) {
+    ALOGD("%s: state: %d", __FUNCTION__, state);
+    switch(state) {
+        case IQService::PREF_PARTIAL_UPDATE:
+            if(qhwc::MDPComp::setPartialUpdatePref(ctx, true) < 0)
+                return NO_INIT;
+            return NO_ERROR;
+        case IQService::PREF_POST_PROCESSING:
+            if(qhwc::MDPComp::setPartialUpdatePref(ctx, false) < 0)
+                return NO_INIT;
+            qhwc::MDPComp::enablePartialUpdate(false);
+            return NO_ERROR;
+        case IQService::ENABLE_PARTIAL_UPDATE:
+            qhwc::MDPComp::enablePartialUpdate(true);
+            return NO_ERROR;
+        default:
+            ALOGE("%s: Invalid state", __FUNCTION__);
+            return NO_ERROR;
+    };
+}
+
+static void toggleScreenUpdate(hwc_context_t* ctx, uint32_t on) {
+    ALOGD("%s: toggle update: %d", __FUNCTION__, on);
+    if (on == 0) {
+        ctx->mDrawLock.lock();
+        ctx->dpyAttr[HWC_DISPLAY_PRIMARY].isPause = true;
+        ctx->mOverlay->configBegin();
+        ctx->mOverlay->configDone();
+        ctx->mRotMgr->clear();
+        if(!Overlay::displayCommit(ctx->dpyAttr[0].fd)) {
+            ALOGE("%s: Display commit failed", __FUNCTION__);
+        }
+        ctx->mDrawLock.unlock();
+    } else {
+        ctx->mDrawLock.lock();
+        ctx->dpyAttr[HWC_DISPLAY_PRIMARY].isPause = false;
+        ctx->mDrawLock.unlock();
+        ctx->proc->invalidate(ctx->proc);
+    }
+}
+
+status_t QClient::notifyCallback(uint32_t command, const Parcel* inParcel,
+        Parcel* outParcel) {
+    status_t ret = NO_ERROR;
+
+    switch(command) {
+        case IQService::SECURING:
+            securing(mHwcContext, inParcel->readInt32());
+            break;
+        case IQService::UNSECURING:
+            unsecuring(mHwcContext, inParcel->readInt32());
+            break;
+        case IQService::SCREEN_REFRESH:
+            return screenRefresh(mHwcContext);
+            break;
+        case IQService::EXTERNAL_ORIENTATION:
+            setExtOrientation(mHwcContext, inParcel->readInt32());
+            break;
+        case IQService::BUFFER_MIRRORMODE:
+            setBufferMirrorMode(mHwcContext, inParcel->readInt32());
+            break;
+        case IQService::GET_DISPLAY_VISIBLE_REGION:
+            ret = getDisplayVisibleRegion(mHwcContext, inParcel->readInt32(),
+                                    outParcel);
+            break;
+        case IQService::CHECK_EXTERNAL_STATUS:
+            isExternalConnected(mHwcContext, outParcel);
+            break;
+        case IQService::GET_DISPLAY_ATTRIBUTES:
+            getDisplayAttributes(mHwcContext, inParcel, outParcel);
+            break;
+        case IQService::SET_HSIC_DATA:
+            setHSIC(inParcel);
+            break;
+        case IQService::SET_SECONDARY_DISPLAY_STATUS:
+            setSecondaryDisplayStatus(mHwcContext, inParcel);
+            break;
+        case IQService::SET_VIEW_FRAME:
+            setViewFrame(mHwcContext, inParcel);
+            break;
+        case IQService::DYNAMIC_DEBUG:
+            toggleDynamicDebug(mHwcContext, inParcel);
+            break;
+        case IQService::SET_IDLE_TIMEOUT:
+            setIdleTimeout(mHwcContext, inParcel);
+            break;
+        case IQService::SET_PARTIAL_UPDATE:
+            ret = setPartialUpdateState(mHwcContext, inParcel->readInt32());
+            break;
+        case IQService::CONFIGURE_DYN_REFRESH_RATE:
+            configureDynRefreshRate(mHwcContext, inParcel);
+        case IQService::QDCM_SVC_CMDS:
+            qdcmCmdsHandler(mHwcContext, inParcel, outParcel);
+            break;
+        case IQService::TOGGLE_SCREEN_UPDATE:
+            toggleScreenUpdate(mHwcContext, inParcel->readInt32());
+            break;
+        default:
+            ret = NO_ERROR;
+    }
+    return ret;
+}
+
+}
diff --git a/msm8909/libhwcomposer/hwc_qclient.h b/msm8909/libhwcomposer/hwc_qclient.h
new file mode 100644
index 0000000..d955377
--- /dev/null
+++ b/msm8909/libhwcomposer/hwc_qclient.h
@@ -0,0 +1,67 @@
+/*
+ *  Copyright (c) 2013, The Linux Foundation. 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 The Linux Foundation 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 CLIENTS; 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 ANDROID_QCLIENT_H
+#define ANDROID_QCLIENT_H
+
+#include <utils/Errors.h>
+#include <sys/types.h>
+#include <cutils/log.h>
+#include <binder/IServiceManager.h>
+#include <media/IMediaDeathNotifier.h>
+#include <IQClient.h>
+
+struct hwc_context_t;
+
+class Params;
+namespace qClient {
+// ----------------------------------------------------------------------------
+
+class QClient : public BnQClient {
+public:
+    QClient(hwc_context_t *ctx);
+    virtual ~QClient();
+    virtual android::status_t notifyCallback(uint32_t command,
+            const android::Parcel* inParcel,
+            android::Parcel* outParcel);
+
+private:
+    //Notifies of Media Player death
+    class MPDeathNotifier : public android::IMediaDeathNotifier {
+    public:
+        MPDeathNotifier(hwc_context_t* ctx) : mHwcContext(ctx){}
+        virtual void died();
+        hwc_context_t *mHwcContext;
+    };
+
+    hwc_context_t *mHwcContext;
+    const android::sp<android::IMediaDeathNotifier> mMPDeathNotifier;
+};
+}; // namespace qClient
+#endif // ANDROID_QCLIENT_H
diff --git a/msm8909/libhwcomposer/hwc_qdcm.cpp b/msm8909/libhwcomposer/hwc_qdcm.cpp
new file mode 100644
index 0000000..9821e4e
--- /dev/null
+++ b/msm8909/libhwcomposer/hwc_qdcm.cpp
@@ -0,0 +1,292 @@
+/*
+ *  Copyright (c) 2014, The Linux Foundation. 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 The Linux Foundation 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.
+ */
+
+#include <hwc_qdcm.h>
+#include <hwc_utils.h>
+#include <utils/String16.h>
+#include <mdp_version.h>
+#include "mode_manager.h"
+#include "libmm-disp-apis.h"
+#include "IQService.h"
+
+using namespace android;
+using namespace qService;
+using namespace qhwc;
+using namespace qmode;
+
+namespace qQdcm {
+//----------------------------------------------------------------------------
+void qdcmInitContext(hwc_context_t *ctx)
+{
+    loadQdcmLibrary(ctx);
+}
+
+void qdcmCloseContext(hwc_context_t *ctx)
+{
+    if (ctx->mQdcmInfo.mQdcmMode) {
+        unloadQdcmLibrary(ctx);
+    }
+}
+
+void qdcmApplyDefaultAfterBootAnimationDone(hwc_context_t *ctx)
+{
+    if (ctx->mQdcmInfo.mQdcmMode)
+        ctx->mQdcmInfo.mQdcmMode->applyDefaultMode(0);
+}
+
+static void qdcmSetActiveMode(hwc_context_t *ctx, const Parcel *in, Parcel *out)
+{
+    int ret = 0;
+
+    if (ctx->mQdcmInfo.mQdcmMode && in && out) {
+
+        struct SET_MODE_PROP_IN params =
+                           { (disp_id_type)in->readInt32(), in->readInt32()};
+
+        ret = ctx->mQdcmInfo.mQdcmMode->requestRoute((int)CMD_SET_ACTIVE_MODE,
+                (void *)&params, (void *)NULL);
+
+        out->writeInt32(ret);  //return operation status via binder.
+    }
+}
+
+static void qdcmSetDefaultMode(hwc_context_t *ctx, const Parcel *in, Parcel *out)
+{
+    int ret = 0;
+
+    if (ctx->mQdcmInfo.mQdcmMode && in && out) {
+
+        struct SET_MODE_PROP_IN params =
+                          { (disp_id_type)in->readInt32(), in->readInt32()};
+
+        ret = ctx->mQdcmInfo.mQdcmMode->requestRoute((int)CMD_SET_DEFAULT_MODE,
+                (void *)&params, (void *)NULL);
+
+        out->writeInt32(ret);  //return operation status via binder.
+    }
+}
+
+static void qdcmGetDefaultMode(hwc_context_t *ctx,
+                                            const Parcel *in, Parcel *out)
+{
+    int ret = 0;
+
+    if (ctx->mQdcmInfo.mQdcmMode && in && out) {
+
+        int params = in->readInt32();
+        int modeid = 0;
+
+        ret = ctx->mQdcmInfo.mQdcmMode->requestRoute((int)CMD_GET_DEFAULT_MODE,
+                (const void *)&params, (void *)&modeid);
+
+        out->writeInt32(modeid);
+        out->writeInt32(ret);  //return operation status via binder.
+    }
+}
+
+static void qdcmGetColorBalanceRange(hwc_context_t *ctx __unused,
+                const Parcel *in __unused, Parcel *out __unused)
+{
+}
+
+static void qdcmGetColorBalance(hwc_context_t *ctx,
+                                            const Parcel *in, Parcel *out)
+{
+    int ret = 0;
+
+    if (ctx->mQdcmInfo.mQdcmMode && in && out) {
+
+        int params = in->readInt32();
+        int warmness = 0;
+
+        ret = ctx->mQdcmInfo.mQdcmMode->requestRoute((int)CMD_GET_CB,
+                (const void *)&params, (void *)&warmness);
+
+        out->writeInt32(warmness);
+        out->writeInt32(ret);  //return operation status via binder.
+    }
+}
+
+static void qdcmSetColorBalance(hwc_context_t *ctx,
+                                            const Parcel *in, Parcel *out)
+{
+    int ret = 0;
+
+    if (ctx->mQdcmInfo.mQdcmMode && in && out) {
+
+        struct SET_CB_IN params =
+                           { (disp_id_type)in->readInt32(), in->readInt32() };
+
+        ALOGD_IF(QDCM_DEBUG, "%s dispID = %d, warmness = %d\n",
+                __FUNCTION__, params.id, params.warmness);
+
+        ret = ctx->mQdcmInfo.mQdcmMode->requestRoute((int)CMD_SET_CB,
+                (const void *)&params, NULL);
+
+        out->writeInt32(ret);  //return operation status via binder.
+    }
+}
+
+static void qdcmSaveModeV2(hwc_context_t *ctx, const Parcel *in, Parcel *out)
+{
+    int ret = 0;
+
+    if (ctx->mQdcmInfo.mQdcmMode && in && out) {
+
+        struct SAVE_DISPLAY_MODE_V2_IN params =
+                     { (disp_id_type)in->readInt32(),
+                                     in->readCString(),
+                           (uint32_t)in->readInt32(),
+                                     in->readInt32()
+                     };
+        int value = 0;
+
+        ret = ctx->mQdcmInfo.mQdcmMode->requestRoute((int)CMD_SAVE_MODE_V2,
+                (const void *)&params, (void *)&value);
+
+        out->writeInt32(value);
+        out->writeInt32(ret);  //return operation status via binder.
+    }
+}
+
+static void qdcmSetPaConfig(hwc_context_t *ctx, const Parcel *in, Parcel *out)
+{
+    int ret = 0;
+
+    if (ctx->mQdcmInfo.mQdcmMode && in && out) {
+
+        struct SET_PA_CONFIG_IN params;
+
+        params.id = (disp_id_type)in->readInt32();
+        params.pa.ops = in->readInt32();
+        params.pa.data.hue = in->readInt32();
+        params.pa.data.saturation = in->readInt32();
+        params.pa.data.value = in->readInt32();
+        params.pa.data.contrast = in->readInt32();
+        params.pa.data.sat_thresh = in->readInt32();
+
+        ret = ctx->mQdcmInfo.mQdcmMode->requestRoute((int)CMD_SET_PA_CONFIG,
+                (const void *)&params, NULL);
+
+        out->writeInt32(ret);  //return operation status via binder.
+    }
+}
+
+static void qdcmGetPaConfig(hwc_context_t *ctx, const Parcel *in, Parcel *out)
+{
+    int ret = 0;
+
+    if (ctx->mQdcmInfo.mQdcmMode && in && out) {
+
+        int params = in->readInt32();
+        struct disp_pa_config value;
+
+        ret = ctx->mQdcmInfo.mQdcmMode->requestRoute((int)CMD_GET_PA_CONFIG,
+                (const void *)&params, (void *)&value);
+
+        out->writeInt32(value.ops);
+        out->writeInt32(value.data.hue);
+        out->writeInt32(value.data.saturation);
+        out->writeInt32(value.data.value);
+        out->writeInt32(value.data.contrast);
+        out->writeInt32(value.data.sat_thresh);
+
+        out->writeInt32(ret);  //return operation status via binder.
+    }
+}
+
+static void qdcmGetPaRange(hwc_context_t *ctx, const Parcel *in, Parcel *out)
+{
+    int ret = 0;
+
+    if (ctx->mQdcmInfo.mQdcmMode && in && out) {
+
+        int params = in->readInt32();
+        struct disp_pa_range value;
+
+        ret = ctx->mQdcmInfo.mQdcmMode->requestRoute((int)CMD_GET_PA_RANGE,
+                (const void *)&params, (void *)&value);
+
+        out->writeInt32(value.max.hue);
+        out->writeInt32(value.max.saturation);
+        out->writeInt32(value.max.value);
+        out->writeInt32(value.max.contrast);
+        out->writeInt32(value.max.sat_thresh);
+        out->writeInt32(value.min.hue);
+        out->writeInt32(value.min.saturation);
+        out->writeInt32(value.min.value);
+        out->writeInt32(value.min.contrast);
+        out->writeInt32(value.min.sat_thresh);
+
+        out->writeInt32(ret);  //return operation status via binder.
+    }
+}
+
+void qdcmCmdsHandler(hwc_context_t *ctx, const Parcel *in, Parcel *out)
+{
+    int subcmd = in->readInt32();
+
+    ALOGD_IF(QDCM_DEBUG, "%s enter subcmd = %d\n", __FUNCTION__, subcmd);
+    switch (subcmd) {
+        case CMD_SET_ACTIVE_MODE:
+            qdcmSetActiveMode(ctx, in, out);
+            break;
+        case CMD_SET_DEFAULT_MODE:
+            qdcmSetDefaultMode(ctx, in, out);
+            break;
+        case CMD_GET_DEFAULT_MODE:
+            qdcmGetDefaultMode(ctx, in, out);
+            break;
+        case CMD_GET_CB_RANGE:
+            qdcmGetColorBalanceRange(ctx, in, out);
+            break;
+        case CMD_GET_CB:
+            qdcmGetColorBalance(ctx, in, out);
+            break;
+        case CMD_SET_CB:
+            qdcmSetColorBalance(ctx, in, out);
+            break;
+        case CMD_SAVE_MODE_V2:
+            qdcmSaveModeV2(ctx, in, out);
+            break;
+        case CMD_SET_PA_CONFIG:
+            qdcmSetPaConfig(ctx, in, out);
+            break;
+        case CMD_GET_PA_CONFIG:
+            qdcmGetPaConfig(ctx, in, out);
+            break;
+        case CMD_GET_PA_RANGE:
+            qdcmGetPaRange(ctx, in, out);
+            break;
+    }
+}
+
+
+} //namespace qQdcm
+
diff --git a/msm8909/libhwcomposer/hwc_qdcm.h b/msm8909/libhwcomposer/hwc_qdcm.h
new file mode 100644
index 0000000..6453159
--- /dev/null
+++ b/msm8909/libhwcomposer/hwc_qdcm.h
@@ -0,0 +1,94 @@
+/*
+ *  Copyright (c) 2014, The Linux Foundation. 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 The Linux Foundation 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 ANDROID_QDCM_H
+#define ANDROID_QDCM_H
+
+#include <utils/Errors.h>
+#include <sys/types.h>
+#include <cutils/log.h>
+#include <hwc_utils.h>
+#include <dlfcn.h>
+#include <binder/Parcel.h>
+#include <cutils/properties.h>
+
+#define QDCM_DEBUG 0
+
+namespace qmode {
+class ModeManager;
+}
+
+using namespace android;
+
+namespace qQdcm {
+// ----------------------------------------------------------------------------
+
+//function prototypes used for QDCM library and service
+static inline void loadQdcmLibrary(hwc_context_t *ctx)
+{
+    ctx->mQdcmInfo.mQdcmLib = dlopen("libmm-qdcm.so", RTLD_NOW);
+    qmode::ModeManager* (*factory)() = NULL;
+
+    if (ctx->mQdcmInfo.mQdcmLib)
+        *(void **)&factory = dlsym(ctx->mQdcmInfo.mQdcmLib, "getObject");
+
+    if (factory) {
+        ctx->mQdcmInfo.mQdcmMode = factory();
+    } else {
+        ctx->mQdcmInfo.mQdcmMode = NULL;
+        ALOGE("QDCM LIbrary load failing!");
+    }
+
+    ALOGD_IF(QDCM_DEBUG, "QDCM LIbrary loaded successfully!");
+}
+
+static inline void unloadQdcmLibrary(hwc_context_t *ctx)
+{
+    void (*destroy)(qmode::ModeManager*) = NULL;
+
+    if (ctx->mQdcmInfo.mQdcmLib) {
+        *(void **)&destroy = dlsym(ctx->mQdcmInfo.mQdcmLib, "deleteObject");
+
+        if (destroy) {
+            destroy(ctx->mQdcmInfo.mQdcmMode);
+            ctx->mQdcmInfo.mQdcmMode = NULL;
+        }
+
+        dlclose(ctx->mQdcmInfo.mQdcmLib);
+        ctx->mQdcmInfo.mQdcmLib = NULL;
+    }
+}
+
+void qdcmInitContext(hwc_context_t *);
+void qdcmCloseContext(hwc_context_t *);
+void qdcmApplyDefaultAfterBootAnimationDone(hwc_context_t *);
+void qdcmCmdsHandler(hwc_context_t*, const Parcel*, Parcel*);
+
+}; // namespace qQdcm
+#endif // ANDROID_QDCM_H
diff --git a/msm8909/libhwcomposer/hwc_qdcm_legacy.cpp b/msm8909/libhwcomposer/hwc_qdcm_legacy.cpp
new file mode 100644
index 0000000..9c2c7b0
--- /dev/null
+++ b/msm8909/libhwcomposer/hwc_qdcm_legacy.cpp
@@ -0,0 +1,79 @@
+/*
+ *  Copyright (c) 2014, The Linux Foundation. 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 The Linux Foundation 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.
+ */
+
+#include <hwc_qdcm.h>
+#include <hwc_utils.h>
+#include <IQService.h>
+#include <mdp_version.h>
+#include <dlfcn.h>
+
+using namespace android;
+using namespace qService;
+using namespace qhwc;
+
+namespace qQdcm {
+//----------------------------------------------------------------------------
+void qdcmInitContext(hwc_context_t *ctx)
+{
+}
+
+void qdcmCloseContext(hwc_context_t *ctx)
+{
+}
+
+void qdcmApplyDefaultAfterBootAnimationDone(hwc_context_t *ctx)
+{
+    int ret = 0;
+    int (*applyMode)(int) = NULL;
+    void *modeHandle = NULL;
+
+    modeHandle = dlopen("libmm-qdcm.so", RTLD_NOW);
+    if (modeHandle) {
+        *(void **)&applyMode = dlsym(modeHandle, "applyDefaults");
+        if (applyMode) {
+            ret = applyMode(HWC_DISPLAY_PRIMARY);
+            if (ret)
+                ALOGE("%s: Not able to apply default mode", __FUNCTION__);
+        } else {
+            ALOGE("%s: No symbol applyDefaults found", __FUNCTION__);
+        }
+        dlclose(modeHandle);
+    } else {
+        ALOGE("%s: Not able to load libmm-qdcm.so", __FUNCTION__);
+    }
+}
+
+//do nothing in case qdcm legacy implementation.
+void qdcmCmdsHandler(hwc_context_t *ctx, const Parcel *in, Parcel *out)
+{
+}
+
+
+} //namespace qQdcm
+
diff --git a/msm8909/libhwcomposer/hwc_uevents.cpp b/msm8909/libhwcomposer/hwc_uevents.cpp
new file mode 100644
index 0000000..d1c68a5
--- /dev/null
+++ b/msm8909/libhwcomposer/hwc_uevents.cpp
@@ -0,0 +1,243 @@
+
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ * Copyright (C) 2012-14, The Linux Foundation. All rights reserved.
+ *
+ * Not a Contribution, Apache license notifications and license are
+ * retained for attribution purposes only.
+
+ * 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 UEVENT_DEBUG 0
+#include <hardware_legacy/uevent.h>
+#include <utils/Log.h>
+#include <sys/resource.h>
+#include <sys/prctl.h>
+#include <string.h>
+#include <stdlib.h>
+#include "hwc_utils.h"
+#include "hwc_fbupdate.h"
+#include "hwc_mdpcomp.h"
+#include "hwc_copybit.h"
+#include "comptype.h"
+#include "hdmi.h"
+#include "hwc_virtual.h"
+#include "mdp_version.h"
+using namespace overlay;
+namespace qhwc {
+#define HWC_UEVENT_SWITCH_STR  "change@/devices/virtual/switch/"
+#define HWC_UEVENT_THREAD_NAME "hwcUeventThread"
+
+/* Parse uevent data for devices which we are interested */
+static int getConnectedDisplay(hwc_context_t* ctx, const char* strUdata)
+{
+    int ret = -1;
+    // Switch node for HDMI as PRIMARY/EXTERNAL
+    if(strcasestr("change@/devices/virtual/switch/hdmi", strUdata)) {
+        if (ctx->mHDMIDisplay->isHDMIPrimaryDisplay()) {
+            ret = HWC_DISPLAY_PRIMARY;
+        } else {
+            ret = HWC_DISPLAY_EXTERNAL;
+        }
+    }
+    return ret;
+}
+
+static bool getPanelResetStatus(hwc_context_t* ctx, const char* strUdata, int len)
+{
+    const char* iter_str = strUdata;
+    if (strcasestr("change@/devices/virtual/graphics/fb0", strUdata)) {
+        while(((iter_str - strUdata) <= len) && (*iter_str)) {
+            char* pstr = strstr(iter_str, "PANEL_ALIVE=0");
+            if (pstr != NULL) {
+                ALOGI("%s: got change event in fb0 with PANEL_ALIVE=0",
+                                                           __FUNCTION__);
+                ctx->mPanelResetStatus = true;
+                return true;
+            }
+            iter_str += strlen(iter_str)+1;
+        }
+    }
+    return false;
+}
+
+/* Parse uevent data for action requested for the display */
+static int getConnectedState(const char* strUdata, int len)
+{
+    const char* iter_str = strUdata;
+    while(((iter_str - strUdata) <= len) && (*iter_str)) {
+        char* pstr = strstr(iter_str, "SWITCH_STATE=");
+        if (pstr != NULL) {
+            return (atoi(pstr + strlen("SWITCH_STATE=")));
+        }
+        iter_str += strlen(iter_str)+1;
+    }
+    return -1;
+}
+
+static void handle_uevent(hwc_context_t* ctx, const char* udata, int len)
+{
+    bool bpanelReset = getPanelResetStatus(ctx, udata, len);
+    if (bpanelReset) {
+        ctx->proc->invalidate(ctx->proc);
+        return;
+    }
+
+    int dpy = getConnectedDisplay(ctx, udata);
+    if(dpy < 0) {
+        ALOGD_IF(UEVENT_DEBUG, "%s: Not disp Event ", __FUNCTION__);
+        return;
+    }
+
+    int switch_state = getConnectedState(udata, len);
+
+    ALOGE_IF(UEVENT_DEBUG,"%s: uevent received: %s switch state: %d",
+             __FUNCTION__,udata, switch_state);
+
+    switch(switch_state) {
+    case EXTERNAL_OFFLINE:
+        {
+            /* Display not connected */
+            if(!ctx->dpyAttr[dpy].connected){
+                ALOGE_IF(UEVENT_DEBUG,"%s: Ignoring EXTERNAL_OFFLINE event"
+                         "for display: %d", __FUNCTION__, dpy);
+                break;
+            }
+
+            ctx->mDrawLock.lock();
+            handle_offline(ctx, dpy);
+            ctx->mDrawLock.unlock();
+
+            /* We need to send hotplug to SF only when we are disconnecting
+             * HDMI as an external display. */
+            if(dpy == HWC_DISPLAY_EXTERNAL) {
+                ALOGE_IF(UEVENT_DEBUG,"%s:Sending EXTERNAL OFFLINE hotplug"
+                        "event", __FUNCTION__);
+                ctx->proc->hotplug(ctx->proc, dpy, EXTERNAL_OFFLINE);
+            }
+            break;
+        }
+    case EXTERNAL_ONLINE:
+        {
+            /* Display already connected */
+            if(ctx->dpyAttr[dpy].connected) {
+                ALOGE_IF(UEVENT_DEBUG,"%s: Ignoring EXTERNAL_ONLINE event"
+                         "for display: %d", __FUNCTION__, dpy);
+                break;
+            }
+
+            if (ctx->mHDMIDisplay->isHDMIPrimaryDisplay()) {
+                ctx->mDrawLock.lock();
+                handle_online(ctx, dpy);
+                ctx->mDrawLock.unlock();
+
+                ctx->proc->invalidate(ctx->proc);
+                break;
+            } else {
+                ctx->mDrawLock.lock();
+                //Force composition to give up resources like pipes and
+                //close fb. For example if assertive display is going on,
+                //fb2 could be open, thus connecting Layer Mixer#0 to
+                //WriteBack module. If HDMI attempts to open fb1, the driver
+                //will try to attach Layer Mixer#0 to HDMI INT, which will
+                //fail, since Layer Mixer#0 is still connected to WriteBack.
+                //This block will force composition to close fb2 in above
+                //example.
+                ctx->dpyAttr[dpy].isConfiguring = true;
+                ctx->mDrawLock.unlock();
+
+                ctx->proc->invalidate(ctx->proc);
+            }
+            //2 cycles for slower content
+            usleep(ctx->dpyAttr[HWC_DISPLAY_PRIMARY].vsync_period
+                   * 2 / 1000);
+
+            if(isVDConnected(ctx)) {
+                // Do not initiate WFD teardown if WFD architecture is based
+                // on VDS mechanism.
+                // WFD Stack listens to HDMI intent and initiates virtual
+                // display teardown.
+                // ToDo: Currently non-WFD Virtual display clients do not
+                // involve HWC. If there is a change, we need to come up
+                // with mechanism of how to address non-WFD Virtual display
+                // clients + HDMI
+                ctx->mWfdSyncLock.lock();
+                ALOGD_IF(HWC_WFDDISPSYNC_LOG,
+                        "%s: Waiting for wfd-teardown to be signalled",
+                        __FUNCTION__);
+                ctx->mWfdSyncLock.wait();
+                ALOGD_IF(HWC_WFDDISPSYNC_LOG,
+                        "%s: Teardown signalled. Completed waiting in"
+                        "uevent thread", __FUNCTION__);
+                ctx->mWfdSyncLock.unlock();
+            }
+            ctx->mHDMIDisplay->configure();
+            ctx->mHDMIDisplay->activateDisplay();
+
+            ctx->mDrawLock.lock();
+            updateDisplayInfo(ctx, dpy);
+            initCompositionResources(ctx, dpy);
+            ctx->dpyAttr[dpy].isPause = false;
+            ctx->dpyAttr[dpy].connected = true;
+            ctx->dpyAttr[dpy].isConfiguring = true;
+            ctx->mDrawLock.unlock();
+
+            /* External display is HDMI */
+            ALOGE_IF(UEVENT_DEBUG, "%s: Sending EXTERNAL ONLINE"
+                    "hotplug event", __FUNCTION__);
+            ctx->proc->hotplug(ctx->proc, dpy, EXTERNAL_ONLINE);
+            break;
+        }
+    default:
+        {
+            ALOGE("%s: Invalid state to swtich:%d", __FUNCTION__, switch_state);
+            break;
+        }
+    }
+}
+
+static void *uevent_loop(void *param)
+{
+    int len = 0;
+    static char udata[PAGE_SIZE];
+    hwc_context_t * ctx = reinterpret_cast<hwc_context_t *>(param);
+    char thread_name[64] = HWC_UEVENT_THREAD_NAME;
+    prctl(PR_SET_NAME, (unsigned long) &thread_name, 0, 0, 0);
+    setpriority(PRIO_PROCESS, 0, HAL_PRIORITY_URGENT_DISPLAY);
+    if(!uevent_init()) {
+        ALOGE("%s: failed to init uevent ",__FUNCTION__);
+        return NULL;
+    }
+
+    while(1) {
+        len = uevent_next_event(udata, (int)sizeof(udata) - 2);
+        handle_uevent(ctx, udata, len);
+    }
+
+    return NULL;
+}
+
+void init_uevent_thread(hwc_context_t* ctx)
+{
+    pthread_t uevent_thread;
+    int ret;
+
+    ALOGI("Initializing UEVENT Thread");
+    ret = pthread_create(&uevent_thread, NULL, uevent_loop, (void*) ctx);
+    if (ret) {
+        ALOGE("%s: failed to create %s: %s", __FUNCTION__,
+            HWC_UEVENT_THREAD_NAME, strerror(ret));
+    }
+}
+
+}; //namespace
diff --git a/msm8909/libhwcomposer/hwc_utils.cpp b/msm8909/libhwcomposer/hwc_utils.cpp
new file mode 100644
index 0000000..9222977
--- /dev/null
+++ b/msm8909/libhwcomposer/hwc_utils.cpp
@@ -0,0 +1,2902 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ * Copyright (C) 2012-2014, The Linux Foundation All rights reserved.
+ *
+ * Not a Contribution, Apache license notifications and license are retained
+ * for attribution purposes only.
+ *
+ * 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 ATRACE_TAG (ATRACE_TAG_GRAPHICS | ATRACE_TAG_HAL)
+#define HWC_UTILS_DEBUG 0
+#include <math.h>
+#include <sys/ioctl.h>
+#include <linux/fb.h>
+#include <binder/IServiceManager.h>
+#include <EGL/egl.h>
+#include <cutils/properties.h>
+#include <utils/Trace.h>
+#include <gralloc_priv.h>
+#include <overlay.h>
+#include <overlayRotator.h>
+#include <overlayWriteback.h>
+#include "hwc_utils.h"
+#include "hwc_mdpcomp.h"
+#include "hwc_fbupdate.h"
+#include "hwc_ad.h"
+#include "mdp_version.h"
+#include "hwc_copybit.h"
+#include "hwc_dump_layers.h"
+#include "hdmi.h"
+#include "hwc_qclient.h"
+#include "QService.h"
+#include "comptype.h"
+#include "hwc_virtual.h"
+#include "qd_utils.h"
+#include "hwc_qdcm.h"
+#include <sys/sysinfo.h>
+#include <dlfcn.h>
+
+using namespace qClient;
+using namespace qService;
+using namespace android;
+using namespace overlay;
+using namespace overlay::utils;
+using namespace qQdcm;
+namespace ovutils = overlay::utils;
+
+#ifdef QTI_BSP
+
+#define EGL_GPU_HINT_1        0x32D0
+#define EGL_GPU_HINT_2        0x32D1
+
+#define EGL_GPU_LEVEL_0       0x0
+#define EGL_GPU_LEVEL_1       0x1
+#define EGL_GPU_LEVEL_2       0x2
+#define EGL_GPU_LEVEL_3       0x3
+#define EGL_GPU_LEVEL_4       0x4
+#define EGL_GPU_LEVEL_5       0x5
+
+#endif
+
+#define PROP_DEFAULT_APPBUFFER  "hw.sf.app_buff_count"
+#define MAX_RAM_SIZE  512*1024*1024
+#define qHD_WIDTH 540
+
+
+namespace qhwc {
+
+// Std refresh rates for digital videos- 24p, 30p, 48p and 60p
+uint32_t stdRefreshRates[] = { 30, 24, 48, 60 };
+
+static uint32_t getFBformat(fb_var_screeninfo vinfo) {
+    uint32_t fbformat = HAL_PIXEL_FORMAT_RGBA_8888;
+
+#ifdef GET_FRAMEBUFFER_FORMAT_FROM_HWC
+    // Here, we are adding the formats that are supported by both GPU and MDP.
+    // The formats that fall in this category are RGBA_8888, RGB_565, RGB_888
+    switch(vinfo.bits_per_pixel) {
+        case 16:
+            fbformat = HAL_PIXEL_FORMAT_RGB_565;
+            break;
+        case 24:
+            if ((vinfo.transp.offset == 0) && (vinfo.transp.length == 0))
+                fbformat = HAL_PIXEL_FORMAT_RGB_888;
+            break;
+        case 32:
+            if ((vinfo.red.offset == 0) && (vinfo.green.offset == 8) &&
+                    (vinfo.blue.offset == 16) && (vinfo.transp.offset == 24))
+                fbformat = HAL_PIXEL_FORMAT_RGBA_8888;
+            break;
+        default:
+            fbformat = HAL_PIXEL_FORMAT_RGBA_8888;
+    }
+#endif
+    return fbformat;
+}
+
+bool isValidResolution(hwc_context_t *ctx, uint32_t xres, uint32_t yres)
+{
+    return !((xres > qdutils::MDPVersion::getInstance().getMaxMixerWidth() &&
+                !isDisplaySplit(ctx, HWC_DISPLAY_PRIMARY)) ||
+            (xres < MIN_DISPLAY_XRES || yres < MIN_DISPLAY_YRES));
+}
+
+void changeResolution(hwc_context_t *ctx, int xres_orig, int yres_orig,
+                      int width, int height) {
+    //Store original display resolution.
+    ctx->dpyAttr[HWC_DISPLAY_PRIMARY].xres_new = xres_orig;
+    ctx->dpyAttr[HWC_DISPLAY_PRIMARY].yres_new = yres_orig;
+    ctx->dpyAttr[HWC_DISPLAY_PRIMARY].customFBSize = false;
+    char property[PROPERTY_VALUE_MAX] = {'\0'};
+    char *yptr = NULL;
+    if (property_get("debug.hwc.fbsize", property, NULL) > 0) {
+        yptr = strcasestr(property,"x");
+        if(yptr) {
+            int xres_new = atoi(property);
+            int yres_new = atoi(yptr + 1);
+            if (isValidResolution(ctx,xres_new,yres_new) &&
+                xres_new != xres_orig && yres_new != yres_orig) {
+                ctx->dpyAttr[HWC_DISPLAY_PRIMARY].xres_new = xres_new;
+                ctx->dpyAttr[HWC_DISPLAY_PRIMARY].yres_new = yres_new;
+                ctx->dpyAttr[HWC_DISPLAY_PRIMARY].customFBSize = true;
+
+                //Caluculate DPI according to changed resolution.
+                float xdpi = ((float)xres_new * 25.4f) / (float)width;
+                float ydpi = ((float)yres_new * 25.4f) / (float)height;
+                ctx->dpyAttr[HWC_DISPLAY_PRIMARY].xdpi = xdpi;
+                ctx->dpyAttr[HWC_DISPLAY_PRIMARY].ydpi = ydpi;
+            }
+        }
+    }
+}
+
+// Initialize hdmi display attributes based on
+// hdmi display class state
+void updateDisplayInfo(hwc_context_t* ctx, int dpy) {
+    struct fb_var_screeninfo info;
+
+    if (ioctl(ctx->mHDMIDisplay->getFd(), FBIOGET_VSCREENINFO, &info) == -1) {
+        ALOGE("%s:Error in ioctl FBIOGET_VSCREENINFO: %s",
+                __FUNCTION__, strerror(errno));
+    }
+
+    ctx->dpyAttr[dpy].fbformat = getFBformat(info);
+    ctx->dpyAttr[dpy].fd = ctx->mHDMIDisplay->getFd();
+    ctx->dpyAttr[dpy].xres = ctx->mHDMIDisplay->getWidth();
+    ctx->dpyAttr[dpy].yres = ctx->mHDMIDisplay->getHeight();
+    ctx->dpyAttr[dpy].mMDPScalingMode = ctx->mHDMIDisplay->getMDPScalingMode();
+    ctx->dpyAttr[dpy].vsync_period = ctx->mHDMIDisplay->getVsyncPeriod();
+    ctx->mViewFrame[dpy].left = 0;
+    ctx->mViewFrame[dpy].top = 0;
+    ctx->mViewFrame[dpy].right = ctx->dpyAttr[dpy].xres;
+    ctx->mViewFrame[dpy].bottom = ctx->dpyAttr[dpy].yres;
+}
+
+// Reset hdmi display attributes and list stats structures
+void resetDisplayInfo(hwc_context_t* ctx, int dpy) {
+    memset(&(ctx->dpyAttr[dpy]), 0, sizeof(ctx->dpyAttr[dpy]));
+    memset(&(ctx->listStats[dpy]), 0, sizeof(ctx->listStats[dpy]));
+    // We reset the fd to -1 here but External display class is responsible
+    // for it when the display is disconnected. This is handled as part of
+    // EXTERNAL_OFFLINE event.
+    ctx->dpyAttr[dpy].fd = -1;
+}
+
+// Initialize composition resources
+void initCompositionResources(hwc_context_t* ctx, int dpy) {
+    ctx->mFBUpdate[dpy] = IFBUpdate::getObject(ctx, dpy);
+    ctx->mMDPComp[dpy] = MDPComp::getObject(ctx, dpy);
+}
+
+void destroyCompositionResources(hwc_context_t* ctx, int dpy) {
+    if(ctx->mFBUpdate[dpy]) {
+        delete ctx->mFBUpdate[dpy];
+        ctx->mFBUpdate[dpy] = NULL;
+    }
+    if(ctx->mMDPComp[dpy]) {
+        delete ctx->mMDPComp[dpy];
+        ctx->mMDPComp[dpy] = NULL;
+    }
+}
+
+static int openFramebufferDevice(hwc_context_t *ctx)
+{
+    struct fb_fix_screeninfo finfo;
+    struct fb_var_screeninfo info;
+
+    int fb_fd = openFb(HWC_DISPLAY_PRIMARY);
+    if(fb_fd < 0) {
+        ALOGE("%s: Error Opening FB : %s", __FUNCTION__, strerror(errno));
+        return -errno;
+    }
+
+    if (ioctl(fb_fd, FBIOGET_VSCREENINFO, &info) == -1) {
+        ALOGE("%s:Error in ioctl FBIOGET_VSCREENINFO: %s", __FUNCTION__,
+                                                       strerror(errno));
+        close(fb_fd);
+        return -errno;
+    }
+
+    if (int(info.width) <= 0 || int(info.height) <= 0) {
+        // the driver doesn't return that information
+        // default to 160 dpi
+        info.width  = (int)(((float)info.xres * 25.4f)/160.0f + 0.5f);
+        info.height = (int)(((float)info.yres * 25.4f)/160.0f + 0.5f);
+    }
+
+    float xdpi = ((float)info.xres * 25.4f) / (float)info.width;
+    float ydpi = ((float)info.yres * 25.4f) / (float)info.height;
+
+#ifdef MSMFB_METADATA_GET
+    struct msmfb_metadata metadata;
+    memset(&metadata, 0 , sizeof(metadata));
+    metadata.op = metadata_op_frame_rate;
+
+    if (ioctl(fb_fd, MSMFB_METADATA_GET, &metadata) == -1) {
+        ALOGE("%s:Error retrieving panel frame rate: %s", __FUNCTION__,
+                                                      strerror(errno));
+        close(fb_fd);
+        return -errno;
+    }
+
+    float fps  = (float)metadata.data.panel_frame_rate;
+#else
+    //XXX: Remove reserved field usage on all baselines
+    //The reserved[3] field is used to store FPS by the driver.
+    float fps  = info.reserved[3] & 0xFF;
+#endif
+
+    if (ioctl(fb_fd, FBIOGET_FSCREENINFO, &finfo) == -1) {
+        ALOGE("%s:Error in ioctl FBIOGET_FSCREENINFO: %s", __FUNCTION__,
+                                                       strerror(errno));
+        close(fb_fd);
+        return -errno;
+    }
+
+    ctx->dpyAttr[HWC_DISPLAY_PRIMARY].fd = fb_fd;
+    //xres, yres may not be 32 aligned
+    ctx->dpyAttr[HWC_DISPLAY_PRIMARY].stride = finfo.line_length /(info.xres/8);
+    ctx->dpyAttr[HWC_DISPLAY_PRIMARY].xres = info.xres;
+    ctx->dpyAttr[HWC_DISPLAY_PRIMARY].yres = info.yres;
+    ctx->dpyAttr[HWC_DISPLAY_PRIMARY].xdpi = xdpi;
+    ctx->dpyAttr[HWC_DISPLAY_PRIMARY].ydpi = ydpi;
+    ctx->dpyAttr[HWC_DISPLAY_PRIMARY].refreshRate = (uint32_t)fps;
+    ctx->dpyAttr[HWC_DISPLAY_PRIMARY].dynRefreshRate = (uint32_t)fps;
+    ctx->dpyAttr[HWC_DISPLAY_PRIMARY].vsync_period =
+            (uint32_t)(1000000000l / fps);
+    ctx->dpyAttr[HWC_DISPLAY_PRIMARY].fbformat = getFBformat(info);
+
+    //To change resolution of primary display
+    changeResolution(ctx, info.xres, info.yres, info.width, info.height);
+
+    //Unblank primary on first boot
+    if(ioctl(fb_fd, FBIOBLANK,FB_BLANK_UNBLANK) < 0) {
+        ALOGE("%s: Failed to unblank display", __FUNCTION__);
+        return -errno;
+    }
+    ctx->dpyAttr[HWC_DISPLAY_PRIMARY].isActive = true;
+
+    return 0;
+}
+
+static void changeDefaultAppBufferCount() {
+    struct sysinfo info;
+    unsigned long int ramSize = 0;
+    if (!sysinfo(&info)) {
+           ramSize = info.totalram ;
+    }
+    int fb_fd = -1;
+    struct fb_var_screeninfo sInfo ={0};
+    fb_fd = open("/dev/graphics/fb0", O_RDONLY);
+    if (fb_fd >=0) {
+        ioctl(fb_fd, FBIOGET_VSCREENINFO, &sInfo);
+        close(fb_fd);
+    }
+    if ((ramSize && ramSize < MAX_RAM_SIZE) &&
+         (sInfo.xres &&  sInfo.xres <= qHD_WIDTH )) {
+                  property_set(PROP_DEFAULT_APPBUFFER, "3");
+    }
+}
+
+void initContext(hwc_context_t *ctx)
+{
+    overlay::Overlay::initOverlay();
+    ctx->mHDMIDisplay = new HDMIDisplay();
+    uint32_t priW = 0, priH = 0;
+    // 1. HDMI as Primary
+    //    -If HDMI cable is connected, read display configs from edid data
+    //    -If HDMI cable is not connected then use default data in vscreeninfo
+    // 2. HDMI as External
+    //    -Initialize HDMI class for use with external display
+    //    -Use vscreeninfo to populate display configs
+    if(ctx->mHDMIDisplay->isHDMIPrimaryDisplay()) {
+        int connected = ctx->mHDMIDisplay->getConnectedState();
+        if(connected == 1) {
+            ctx->mHDMIDisplay->configure();
+            updateDisplayInfo(ctx, HWC_DISPLAY_PRIMARY);
+            ctx->dpyAttr[HWC_DISPLAY_PRIMARY].connected = true;
+        } else {
+            openFramebufferDevice(ctx);
+            ctx->dpyAttr[HWC_DISPLAY_PRIMARY].connected = false;
+        }
+    } else {
+        openFramebufferDevice(ctx);
+        ctx->dpyAttr[HWC_DISPLAY_PRIMARY].connected = true;
+        // Send the primary resolution to the hdmi display class
+        // to be used for MDP scaling functionality
+        priW = ctx->dpyAttr[HWC_DISPLAY_PRIMARY].xres;
+        priH = ctx->dpyAttr[HWC_DISPLAY_PRIMARY].yres;
+        ctx->mHDMIDisplay->setPrimaryAttributes(priW, priH);
+    }
+
+    char value[PROPERTY_VALUE_MAX];
+    ctx->mMDP.version = qdutils::MDPVersion::getInstance().getMDPVersion();
+    ctx->mMDP.hasOverlay = qdutils::MDPVersion::getInstance().hasOverlay();
+    ctx->mMDP.panel = qdutils::MDPVersion::getInstance().getPanelType();
+    ctx->mOverlay = overlay::Overlay::getInstance();
+    ctx->mRotMgr = RotMgr::getInstance();
+
+    //default_app_buffer for ferrum
+    if (ctx->mMDP.version ==  qdutils::MDP_V3_0_5) {
+       changeDefaultAppBufferCount();
+    }
+    // Initialize composition objects for the primary display
+    initCompositionResources(ctx, HWC_DISPLAY_PRIMARY);
+
+    // Check if the target supports copybit compostion (dyn/mdp) to
+    // decide if we need to open the copybit module.
+    int compositionType =
+        qdutils::QCCompositionType::getInstance().getCompositionType();
+
+    // Only MDP copybit is used
+    if ((compositionType & (qdutils::COMPOSITION_TYPE_DYN |
+            qdutils::COMPOSITION_TYPE_MDP)) &&
+            ((qdutils::MDPVersion::getInstance().getMDPVersion() ==
+            qdutils::MDP_V3_0_4) ||
+            (qdutils::MDPVersion::getInstance().getMDPVersion() ==
+            qdutils::MDP_V3_0_5))) {
+        ctx->mCopyBit[HWC_DISPLAY_PRIMARY] = new CopyBit(ctx,
+                                                         HWC_DISPLAY_PRIMARY);
+    }
+
+    ctx->mHWCVirtual = new HWCVirtualVDS();
+    ctx->dpyAttr[HWC_DISPLAY_EXTERNAL].isActive = false;
+    ctx->dpyAttr[HWC_DISPLAY_EXTERNAL].connected = false;
+    ctx->dpyAttr[HWC_DISPLAY_VIRTUAL].isActive = false;
+    ctx->dpyAttr[HWC_DISPLAY_VIRTUAL].connected = false;
+    ctx->dpyAttr[HWC_DISPLAY_PRIMARY].mMDPScalingMode= false;
+    ctx->dpyAttr[HWC_DISPLAY_EXTERNAL].mMDPScalingMode = false;
+    ctx->dpyAttr[HWC_DISPLAY_VIRTUAL].mMDPScalingMode = false;
+
+    //Initialize the primary display viewFrame info
+    ctx->mViewFrame[HWC_DISPLAY_PRIMARY].left = 0;
+    ctx->mViewFrame[HWC_DISPLAY_PRIMARY].top = 0;
+    ctx->mViewFrame[HWC_DISPLAY_PRIMARY].right =
+        (int)ctx->dpyAttr[HWC_DISPLAY_PRIMARY].xres;
+    ctx->mViewFrame[HWC_DISPLAY_PRIMARY].bottom =
+         (int)ctx->dpyAttr[HWC_DISPLAY_PRIMARY].yres;
+
+    for (uint32_t i = 0; i < HWC_NUM_DISPLAY_TYPES; i++) {
+        ctx->mHwcDebug[i] = new HwcDebug(i);
+        ctx->mLayerRotMap[i] = new LayerRotMap();
+        ctx->mAnimationState[i] = ANIMATION_STOPPED;
+        ctx->dpyAttr[i].mActionSafePresent = false;
+        ctx->dpyAttr[i].mAsWidthRatio = 0;
+        ctx->dpyAttr[i].mAsHeightRatio = 0;
+    }
+
+    for (uint32_t i = 0; i < HWC_NUM_DISPLAY_TYPES; i++) {
+        ctx->mPrevHwLayerCount[i] = 0;
+    }
+
+    MDPComp::init(ctx);
+    ctx->mAD = new AssertiveDisplay(ctx);
+
+    ctx->vstate.enable = false;
+    ctx->vstate.fakevsync = false;
+    ctx->mExtOrientation = 0;
+    ctx->numActiveDisplays = 1;
+
+    //Right now hwc starts the service but anybody could do it, or it could be
+    //independent process as well.
+    QService::init();
+    sp<IQClient> client = new QClient(ctx);
+    android::sp<qService::IQService> qservice_sp = interface_cast<IQService>(
+            defaultServiceManager()->getService(
+            String16("display.qservice")));
+    if (qservice_sp.get()) {
+      qservice_sp->connect(client);
+    } else {
+      ALOGE("%s: Failed to acquire service pointer", __FUNCTION__);
+      return ;
+    }
+
+    // Initialize device orientation to its default orientation
+    ctx->deviceOrientation = 0;
+    ctx->mBufferMirrorMode = false;
+
+    property_get("sys.hwc.windowbox_aspect_ratio_tolerance", value, "0");
+    ctx->mAspectRatioToleranceLevel = (((float)atoi(value)) / 100.0f);
+
+    ctx->enableABC = false;
+    property_get("debug.sf.hwc.canUseABC", value, "0");
+    ctx->enableABC  = atoi(value) ? true : false;
+
+    // Initializing boot anim completed check to false
+    ctx->mBootAnimCompleted = false;
+
+    // Initialize gpu perfomance hint related parameters
+#ifdef QTI_BSP
+    ctx->mEglLib = NULL;
+    ctx->mpfn_eglGpuPerfHintQCOM = NULL;
+    ctx->mpfn_eglGetCurrentDisplay = NULL;
+    ctx->mpfn_eglGetCurrentContext = NULL;
+    ctx->mGPUHintInfo.mGpuPerfModeEnable = false;
+    ctx->mGPUHintInfo.mEGLDisplay = NULL;
+    ctx->mGPUHintInfo.mEGLContext = NULL;
+    ctx->mGPUHintInfo.mCompositionState = COMPOSITION_STATE_MDP;
+    ctx->mGPUHintInfo.mCurrGPUPerfMode = EGL_GPU_LEVEL_0;
+    if(property_get("sys.hwc.gpu_perf_mode", value, "0") > 0) {
+        int val = atoi(value);
+        if(val > 0 && loadEglLib(ctx)) {
+            ctx->mGPUHintInfo.mGpuPerfModeEnable = true;
+        }
+    }
+#endif
+    // Read the system property to determine if windowboxing feature is enabled.
+    ctx->mWindowboxFeature = false;
+    if(property_get("sys.hwc.windowbox_feature", value, "false")
+            && !strcmp(value, "true")) {
+        ctx->mWindowboxFeature = true;
+    }
+
+    ctx->mUseMetaDataRefreshRate = true;
+    if(property_get("persist.metadata_dynfps.disable", value, "false")
+            && !strcmp(value, "true")) {
+        ctx->mUseMetaDataRefreshRate = false;
+    }
+
+    memset(&(ctx->mPtorInfo), 0, sizeof(ctx->mPtorInfo));
+
+    //init qdcm service related context.
+    qdcmInitContext(ctx);
+
+    ALOGI("Initializing Qualcomm Hardware Composer");
+    ALOGI("MDP version: %d", ctx->mMDP.version);
+}
+
+void closeContext(hwc_context_t *ctx)
+{
+    //close qdcm service related context.
+    qdcmCloseContext(ctx);
+
+    if(ctx->mOverlay) {
+        delete ctx->mOverlay;
+        ctx->mOverlay = NULL;
+    }
+
+    if(ctx->mRotMgr) {
+        delete ctx->mRotMgr;
+        ctx->mRotMgr = NULL;
+    }
+
+    for(int i = 0; i < HWC_NUM_DISPLAY_TYPES; i++) {
+        if(ctx->mCopyBit[i]) {
+            delete ctx->mCopyBit[i];
+            ctx->mCopyBit[i] = NULL;
+        }
+    }
+
+    if(ctx->dpyAttr[HWC_DISPLAY_PRIMARY].fd) {
+        close(ctx->dpyAttr[HWC_DISPLAY_PRIMARY].fd);
+        ctx->dpyAttr[HWC_DISPLAY_PRIMARY].fd = -1;
+    }
+
+    if(ctx->mHDMIDisplay) {
+        delete ctx->mHDMIDisplay;
+        ctx->mHDMIDisplay = NULL;
+    }
+
+    for(int i = 0; i < HWC_NUM_DISPLAY_TYPES; i++) {
+        destroyCompositionResources(ctx, i);
+
+        if(ctx->mHwcDebug[i]) {
+            delete ctx->mHwcDebug[i];
+            ctx->mHwcDebug[i] = NULL;
+        }
+        if(ctx->mLayerRotMap[i]) {
+            delete ctx->mLayerRotMap[i];
+            ctx->mLayerRotMap[i] = NULL;
+        }
+    }
+    if(ctx->mHWCVirtual) {
+        delete ctx->mHWCVirtual;
+        ctx->mHWCVirtual = NULL;
+    }
+    if(ctx->mAD) {
+        delete ctx->mAD;
+        ctx->mAD = NULL;
+    }
+
+#ifdef QTI_BSP
+    ctx->mpfn_eglGpuPerfHintQCOM = NULL;
+    ctx->mpfn_eglGetCurrentDisplay = NULL;
+    ctx->mpfn_eglGetCurrentContext = NULL;
+    if(ctx->mEglLib) {
+        dlclose(ctx->mEglLib);
+        ctx->mEglLib = NULL;
+    }
+#endif
+}
+
+uint32_t getRefreshRate(hwc_context_t* ctx, uint32_t requestedRefreshRate) {
+
+    qdutils::MDPVersion& mdpHw = qdutils::MDPVersion::getInstance();
+    int dpy = HWC_DISPLAY_PRIMARY;
+    uint32_t defaultRefreshRate = ctx->dpyAttr[dpy].refreshRate;
+    uint32_t rate = defaultRefreshRate;
+
+    if(!requestedRefreshRate)
+        return defaultRefreshRate;
+
+    uint32_t maxNumIterations =
+            (uint32_t)ceil(
+                    (float)mdpHw.getMaxFpsSupported()/
+                    (float)requestedRefreshRate);
+
+    for(uint32_t i = 1; i <= maxNumIterations; i++) {
+        rate = i * roundOff(requestedRefreshRate);
+        if(rate < mdpHw.getMinFpsSupported()) {
+            continue;
+        } else if((rate >= mdpHw.getMinFpsSupported() &&
+                   rate <= mdpHw.getMaxFpsSupported())) {
+            break;
+        } else {
+            rate = defaultRefreshRate;
+            break;
+        }
+    }
+    return rate;
+}
+
+//Helper to roundoff the refreshrates to the std refresh-rates
+uint32_t roundOff(uint32_t refreshRate) {
+    int count =  (int) (sizeof(stdRefreshRates)/sizeof(stdRefreshRates[0]));
+    uint32_t rate = refreshRate;
+    for(int i=0; i< count; i++) {
+        if(abs(stdRefreshRates[i] - refreshRate) < 2) {
+            // Most likely used for video, the fps can fluctuate
+            // Ex: b/w 29 and 30 for 30 fps clip
+            rate = stdRefreshRates[i];
+            break;
+        }
+    }
+    return rate;
+}
+
+//Helper func to set the dyn fps
+void setRefreshRate(hwc_context_t* ctx, int dpy, uint32_t refreshRate) {
+    //Update only if different
+    if(!ctx || refreshRate == ctx->dpyAttr[dpy].dynRefreshRate)
+        return;
+    const int fbNum = Overlay::getFbForDpy(dpy);
+    char sysfsPath[qdutils::MAX_SYSFS_FILE_PATH];
+    snprintf (sysfsPath, sizeof(sysfsPath),
+            "/sys/class/graphics/fb%d/dynamic_fps", fbNum);
+
+    int fd = open(sysfsPath, O_WRONLY);
+    if(fd >= 0) {
+        char str[64];
+        snprintf(str, sizeof(str), "%d", refreshRate);
+        ssize_t ret = write(fd, str, strlen(str));
+        if(ret < 0) {
+            ALOGE("%s: Failed to write %d with error %s",
+                    __FUNCTION__, refreshRate, strerror(errno));
+        } else {
+            ctx->dpyAttr[dpy].dynRefreshRate = refreshRate;
+            ALOGD_IF(HWC_UTILS_DEBUG, "%s: Wrote %d to dynamic_fps",
+                     __FUNCTION__, refreshRate);
+        }
+        close(fd);
+    } else {
+        ALOGE("%s: Failed to open %s with error %s", __FUNCTION__, sysfsPath,
+              strerror(errno));
+    }
+}
+
+void dumpsys_log(android::String8& buf, const char* fmt, ...)
+{
+    va_list varargs;
+    va_start(varargs, fmt);
+    buf.appendFormatV(fmt, varargs);
+    va_end(varargs);
+}
+
+int getExtOrientation(hwc_context_t* ctx) {
+    int extOrient = ctx->mExtOrientation;
+    if(ctx->mBufferMirrorMode)
+        extOrient = getMirrorModeOrientation(ctx);
+    return extOrient;
+}
+
+/* Calculates the destination position based on the action safe rectangle */
+void getActionSafePosition(hwc_context_t *ctx, int dpy, hwc_rect_t& rect) {
+    // Position
+    int x = rect.left, y = rect.top;
+    int w = rect.right - rect.left;
+    int h = rect.bottom - rect.top;
+
+    if(!ctx->dpyAttr[dpy].mActionSafePresent)
+        return;
+   // Read action safe properties
+    int asWidthRatio = ctx->dpyAttr[dpy].mAsWidthRatio;
+    int asHeightRatio = ctx->dpyAttr[dpy].mAsHeightRatio;
+
+    float wRatio = 1.0;
+    float hRatio = 1.0;
+    float xRatio = 1.0;
+    float yRatio = 1.0;
+
+    uint32_t fbWidth = ctx->dpyAttr[dpy].xres;
+    uint32_t fbHeight = ctx->dpyAttr[dpy].yres;
+    if(ctx->dpyAttr[dpy].mMDPScalingMode) {
+        // if MDP scaling mode is enabled for external, need to query
+        // the actual width and height, as that is the physical w & h
+         ctx->mHDMIDisplay->getAttributes(fbWidth, fbHeight);
+    }
+
+
+    // Since external is rotated 90, need to swap width/height
+    int extOrient = getExtOrientation(ctx);
+
+    if(extOrient & HWC_TRANSFORM_ROT_90)
+        swap(fbWidth, fbHeight);
+
+    float asX = 0;
+    float asY = 0;
+    float asW = (float)fbWidth;
+    float asH = (float)fbHeight;
+
+    // based on the action safe ratio, get the Action safe rectangle
+    asW = ((float)fbWidth * (1.0f -  (float)asWidthRatio / 100.0f));
+    asH = ((float)fbHeight * (1.0f -  (float)asHeightRatio / 100.0f));
+    asX = ((float)fbWidth - asW) / 2;
+    asY = ((float)fbHeight - asH) / 2;
+
+    // calculate the position ratio
+    xRatio = (float)x/(float)fbWidth;
+    yRatio = (float)y/(float)fbHeight;
+    wRatio = (float)w/(float)fbWidth;
+    hRatio = (float)h/(float)fbHeight;
+
+    //Calculate the position...
+    x = int((xRatio * asW) + asX);
+    y = int((yRatio * asH) + asY);
+    w = int(wRatio * asW);
+    h = int(hRatio * asH);
+
+    // Convert it back to hwc_rect_t
+    rect.left = x;
+    rect.top = y;
+    rect.right = w + rect.left;
+    rect.bottom = h + rect.top;
+
+    return;
+}
+
+// This function gets the destination position for Seconday display
+// based on the position and aspect ratio with orientation
+void getAspectRatioPosition(hwc_context_t* ctx, int dpy, int extOrientation,
+                            hwc_rect_t& inRect, hwc_rect_t& outRect) {
+    // Physical display resolution
+    float fbWidth  = (float)ctx->dpyAttr[dpy].xres;
+    float fbHeight = (float)ctx->dpyAttr[dpy].yres;
+    //display position(x,y,w,h) in correct aspectratio after rotation
+    int xPos = 0;
+    int yPos = 0;
+    float width = fbWidth;
+    float height = fbHeight;
+    // Width/Height used for calculation, after rotation
+    float actualWidth = fbWidth;
+    float actualHeight = fbHeight;
+
+    float wRatio = 1.0;
+    float hRatio = 1.0;
+    float xRatio = 1.0;
+    float yRatio = 1.0;
+    hwc_rect_t rect = {0, 0, (int)fbWidth, (int)fbHeight};
+
+    Dim inPos(inRect.left, inRect.top, inRect.right - inRect.left,
+                inRect.bottom - inRect.top);
+    Dim outPos(outRect.left, outRect.top, outRect.right - outRect.left,
+                outRect.bottom - outRect.top);
+
+    Whf whf((uint32_t)fbWidth, (uint32_t)fbHeight, 0);
+    eTransform extorient = static_cast<eTransform>(extOrientation);
+    // To calculate the destination co-ordinates in the new orientation
+    preRotateSource(extorient, whf, inPos);
+
+    if(extOrientation & HAL_TRANSFORM_ROT_90) {
+        // Swap width/height for input position
+        swapWidthHeight(actualWidth, actualHeight);
+        qdutils::getAspectRatioPosition((int)fbWidth, (int)fbHeight,
+                                (int)actualWidth, (int)actualHeight, rect);
+        xPos = rect.left;
+        yPos = rect.top;
+        width = float(rect.right - rect.left);
+        height = float(rect.bottom - rect.top);
+    }
+    xRatio = (float)((float)inPos.x/actualWidth);
+    yRatio = (float)((float)inPos.y/actualHeight);
+    wRatio = (float)((float)inPos.w/actualWidth);
+    hRatio = (float)((float)inPos.h/actualHeight);
+
+    //Calculate the pos9ition...
+    outPos.x = uint32_t((xRatio * width) + (float)xPos);
+    outPos.y = uint32_t((yRatio * height) + (float)yPos);
+    outPos.w = uint32_t(wRatio * width);
+    outPos.h = uint32_t(hRatio * height);
+    ALOGD_IF(HWC_UTILS_DEBUG, "%s: Calculated AspectRatio Position: x = %d,"
+                 "y = %d w = %d h = %d", __FUNCTION__, outPos.x, outPos.y,
+                 outPos.w, outPos.h);
+
+    // For sidesync, the dest fb will be in portrait orientation, and the crop
+    // will be updated to avoid the black side bands, and it will be upscaled
+    // to fit the dest RB, so recalculate
+    // the position based on the new width and height
+    if ((extOrientation & HWC_TRANSFORM_ROT_90) &&
+                        isOrientationPortrait(ctx)) {
+        hwc_rect_t r = {0, 0, 0, 0};
+        //Calculate the position
+        xRatio = (float)(outPos.x - xPos)/width;
+        // GetaspectRatio -- tricky to get the correct aspect ratio
+        // But we need to do this.
+        qdutils::getAspectRatioPosition((int)width, (int)height,
+                               (int)width,(int)height, r);
+        xPos = r.left;
+        yPos = r.top;
+        float tempHeight = float(r.bottom - r.top);
+        yRatio = (float)yPos/height;
+        wRatio = (float)outPos.w/width;
+        hRatio = tempHeight/height;
+
+        //Map the coordinates back to Framebuffer domain
+        outPos.x = uint32_t(xRatio * fbWidth);
+        outPos.y = uint32_t(yRatio * fbHeight);
+        outPos.w = uint32_t(wRatio * fbWidth);
+        outPos.h = uint32_t(hRatio * fbHeight);
+
+        ALOGD_IF(HWC_UTILS_DEBUG, "%s: Calculated AspectRatio for device in"
+                 "portrait: x = %d,y = %d w = %d h = %d", __FUNCTION__,
+                 outPos.x, outPos.y,
+                 outPos.w, outPos.h);
+    }
+    if(ctx->dpyAttr[dpy].mMDPScalingMode) {
+        uint32_t extW = 0, extH = 0;
+        if(dpy == HWC_DISPLAY_EXTERNAL) {
+            ctx->mHDMIDisplay->getAttributes(extW, extH);
+        } else if(dpy == HWC_DISPLAY_VIRTUAL) {
+            extW = ctx->mHWCVirtual->getScalingWidth();
+            extH = ctx->mHWCVirtual->getScalingHeight();
+        }
+        ALOGD_IF(HWC_UTILS_DEBUG, "%s: Scaling mode extW=%d extH=%d",
+                __FUNCTION__, extW, extH);
+
+        fbWidth  = (float)ctx->dpyAttr[dpy].xres;
+        fbHeight = (float)ctx->dpyAttr[dpy].yres;
+        //Calculate the position...
+        xRatio = (float)outPos.x/fbWidth;
+        yRatio = (float)outPos.y/fbHeight;
+        wRatio = (float)outPos.w/fbWidth;
+        hRatio = (float)outPos.h/fbHeight;
+
+        outPos.x = uint32_t(xRatio * (float)extW);
+        outPos.y = uint32_t(yRatio * (float)extH);
+        outPos.w = uint32_t(wRatio * (float)extW);
+        outPos.h = uint32_t(hRatio * (float)extH);
+    }
+    // Convert Dim to hwc_rect_t
+    outRect.left = outPos.x;
+    outRect.top = outPos.y;
+    outRect.right = outPos.x + outPos.w;
+    outRect.bottom = outPos.y + outPos.h;
+
+    return;
+}
+
+bool isPrimaryPortrait(hwc_context_t *ctx) {
+    int fbWidth = ctx->dpyAttr[HWC_DISPLAY_PRIMARY].xres;
+    int fbHeight = ctx->dpyAttr[HWC_DISPLAY_PRIMARY].yres;
+    if(fbWidth < fbHeight) {
+        return true;
+    }
+    return false;
+}
+
+bool isOrientationPortrait(hwc_context_t *ctx) {
+    if(isPrimaryPortrait(ctx)) {
+        return !(ctx->deviceOrientation & 0x1);
+    }
+    return (ctx->deviceOrientation & 0x1);
+}
+
+void calcExtDisplayPosition(hwc_context_t *ctx,
+                               private_handle_t *hnd,
+                               int dpy,
+                               hwc_rect_t& sourceCrop,
+                               hwc_rect_t& displayFrame,
+                               int& transform,
+                               ovutils::eTransform& orient) {
+    // Swap width and height when there is a 90deg transform
+    int extOrient = getExtOrientation(ctx);
+    if(dpy && ctx->mOverlay->isUIScalingOnExternalSupported()) {
+        if(!isYuvBuffer(hnd)) {
+            if(extOrient & HWC_TRANSFORM_ROT_90) {
+                int dstWidth = ctx->dpyAttr[dpy].xres;
+                int dstHeight = ctx->dpyAttr[dpy].yres;;
+                int srcWidth = ctx->dpyAttr[HWC_DISPLAY_PRIMARY].xres;
+                int srcHeight = ctx->dpyAttr[HWC_DISPLAY_PRIMARY].yres;
+                if(!isPrimaryPortrait(ctx)) {
+                    swap(srcWidth, srcHeight);
+                }                    // Get Aspect Ratio for external
+                qdutils::getAspectRatioPosition(dstWidth, dstHeight, srcWidth,
+                                    srcHeight, displayFrame);
+                // Crop - this is needed, because for sidesync, the dest fb will
+                // be in portrait orientation, so update the crop to not show the
+                // black side bands.
+                if (isOrientationPortrait(ctx)) {
+                    sourceCrop = displayFrame;
+                    displayFrame.left = 0;
+                    displayFrame.top = 0;
+                    displayFrame.right = dstWidth;
+                    displayFrame.bottom = dstHeight;
+                }
+            }
+            if(ctx->dpyAttr[dpy].mMDPScalingMode) {
+                uint32_t extW = 0, extH = 0;
+                // if MDP scaling mode is enabled, map the co-ordinates to new
+                // domain(downscaled)
+                float fbWidth  = (float)ctx->dpyAttr[dpy].xres;
+                float fbHeight = (float)ctx->dpyAttr[dpy].yres;
+                // query MDP configured attributes
+                if(dpy == HWC_DISPLAY_EXTERNAL) {
+                    ctx->mHDMIDisplay->getAttributes(extW, extH);
+                } else if(dpy == HWC_DISPLAY_VIRTUAL) {
+                    extW = ctx->mHWCVirtual->getScalingWidth();
+                    extH = ctx->mHWCVirtual->getScalingHeight();
+                }
+                ALOGD_IF(HWC_UTILS_DEBUG, "%s: Scaling mode extW=%d extH=%d",
+                        __FUNCTION__, extW, extH);
+
+                //Calculate the ratio...
+                float wRatio = ((float)extW)/fbWidth;
+                float hRatio = ((float)extH)/fbHeight;
+
+                //convert Dim to hwc_rect_t
+                displayFrame.left = int(wRatio*(float)displayFrame.left);
+                displayFrame.top = int(hRatio*(float)displayFrame.top);
+                displayFrame.right = int(wRatio*(float)displayFrame.right);
+                displayFrame.bottom = int(hRatio*(float)displayFrame.bottom);
+                ALOGD_IF(DEBUG_MDPDOWNSCALE, "Calculated external display frame"
+                         " for MDPDownscale feature [%d %d %d %d]",
+                         displayFrame.left, displayFrame.top,
+                         displayFrame.right, displayFrame.bottom);
+            }
+        }else {
+            if(extOrient || ctx->dpyAttr[dpy].mMDPScalingMode) {
+                getAspectRatioPosition(ctx, dpy, extOrient,
+                                       displayFrame, displayFrame);
+            }
+        }
+        // If there is a external orientation set, use that
+        if(extOrient) {
+            transform = extOrient;
+            orient = static_cast<ovutils::eTransform >(extOrient);
+        }
+        // Calculate the actionsafe dimensions for External(dpy = 1 or 2)
+        getActionSafePosition(ctx, dpy, displayFrame);
+    }
+}
+
+/* Returns the orientation which needs to be set on External for
+ *  SideSync/Buffer Mirrormode
+ */
+int getMirrorModeOrientation(hwc_context_t *ctx) {
+    int extOrientation = 0;
+    int deviceOrientation = ctx->deviceOrientation;
+    if(!isPrimaryPortrait(ctx))
+        deviceOrientation = (deviceOrientation + 1) % 4;
+     if (deviceOrientation == 0)
+         extOrientation = HWC_TRANSFORM_ROT_270;
+     else if (deviceOrientation == 1)//90
+         extOrientation = 0;
+     else if (deviceOrientation == 2)//180
+         extOrientation = HWC_TRANSFORM_ROT_90;
+     else if (deviceOrientation == 3)//270
+         extOrientation = HWC_TRANSFORM_FLIP_V | HWC_TRANSFORM_FLIP_H;
+
+    return extOrientation;
+}
+
+/* Get External State names */
+const char* getExternalDisplayState(uint32_t external_state) {
+    static const char* externalStates[EXTERNAL_MAXSTATES] = {0};
+    externalStates[EXTERNAL_OFFLINE] = STR(EXTERNAL_OFFLINE);
+    externalStates[EXTERNAL_ONLINE]  = STR(EXTERNAL_ONLINE);
+    externalStates[EXTERNAL_PAUSE]   = STR(EXTERNAL_PAUSE);
+    externalStates[EXTERNAL_RESUME]  = STR(EXTERNAL_RESUME);
+
+    if(external_state >= EXTERNAL_MAXSTATES) {
+        return "EXTERNAL_INVALID";
+    }
+
+    return externalStates[external_state];
+}
+
+bool isDownscaleRequired(hwc_layer_1_t const* layer) {
+    hwc_rect_t displayFrame  = layer->displayFrame;
+    hwc_rect_t sourceCrop = integerizeSourceCrop(layer->sourceCropf);
+    int dst_w, dst_h, src_w, src_h;
+    dst_w = displayFrame.right - displayFrame.left;
+    dst_h = displayFrame.bottom - displayFrame.top;
+    src_w = sourceCrop.right - sourceCrop.left;
+    src_h = sourceCrop.bottom - sourceCrop.top;
+
+    if(((src_w > dst_w) || (src_h > dst_h)))
+        return true;
+
+    return false;
+}
+bool needsScaling(hwc_layer_1_t const* layer) {
+    int dst_w, dst_h, src_w, src_h;
+    hwc_rect_t displayFrame  = layer->displayFrame;
+    hwc_rect_t sourceCrop = integerizeSourceCrop(layer->sourceCropf);
+
+    dst_w = displayFrame.right - displayFrame.left;
+    dst_h = displayFrame.bottom - displayFrame.top;
+    src_w = sourceCrop.right - sourceCrop.left;
+    src_h = sourceCrop.bottom - sourceCrop.top;
+
+    if(((src_w != dst_w) || (src_h != dst_h)))
+        return true;
+
+    return false;
+}
+
+// Checks if layer needs scaling with split
+bool needsScalingWithSplit(hwc_context_t* ctx, hwc_layer_1_t const* layer,
+        const int& dpy) {
+
+    int src_width_l, src_height_l;
+    int src_width_r, src_height_r;
+    int dst_width_l, dst_height_l;
+    int dst_width_r, dst_height_r;
+    int hw_w = ctx->dpyAttr[dpy].xres;
+    int hw_h = ctx->dpyAttr[dpy].yres;
+    hwc_rect_t cropL, dstL, cropR, dstR;
+    const int lSplit = getLeftSplit(ctx, dpy);
+    hwc_rect_t sourceCrop = integerizeSourceCrop(layer->sourceCropf);
+    hwc_rect_t displayFrame  = layer->displayFrame;
+    private_handle_t *hnd = (private_handle_t *)layer->handle;
+
+    cropL = sourceCrop;
+    dstL = displayFrame;
+    hwc_rect_t scissorL = { 0, 0, lSplit, hw_h };
+    scissorL = getIntersection(ctx->mViewFrame[dpy], scissorL);
+    qhwc::calculate_crop_rects(cropL, dstL, scissorL, 0);
+
+    cropR = sourceCrop;
+    dstR = displayFrame;
+    hwc_rect_t scissorR = { lSplit, 0, hw_w, hw_h };
+    scissorR = getIntersection(ctx->mViewFrame[dpy], scissorR);
+    qhwc::calculate_crop_rects(cropR, dstR, scissorR, 0);
+
+    // Sanitize Crop to stitch
+    sanitizeSourceCrop(cropL, cropR, hnd);
+
+    // Calculate the left dst
+    dst_width_l = dstL.right - dstL.left;
+    dst_height_l = dstL.bottom - dstL.top;
+    src_width_l = cropL.right - cropL.left;
+    src_height_l = cropL.bottom - cropL.top;
+
+    // check if there is any scaling on the left
+    if(((src_width_l != dst_width_l) || (src_height_l != dst_height_l)))
+        return true;
+
+    // Calculate the right dst
+    dst_width_r = dstR.right - dstR.left;
+    dst_height_r = dstR.bottom - dstR.top;
+    src_width_r = cropR.right - cropR.left;
+    src_height_r = cropR.bottom - cropR.top;
+
+    // check if there is any scaling on the right
+    if(((src_width_r != dst_width_r) || (src_height_r != dst_height_r)))
+        return true;
+
+    return false;
+}
+
+bool isAlphaScaled(hwc_layer_1_t const* layer) {
+    if(needsScaling(layer) && isAlphaPresent(layer)) {
+        return true;
+    }
+    return false;
+}
+
+bool isAlphaPresent(hwc_layer_1_t const* layer) {
+    private_handle_t *hnd = (private_handle_t *)layer->handle;
+    if(hnd) {
+        int format = hnd->format;
+        switch(format) {
+        case HAL_PIXEL_FORMAT_RGBA_8888:
+        case HAL_PIXEL_FORMAT_BGRA_8888:
+            // In any more formats with Alpha go here..
+            return true;
+        default : return false;
+        }
+    }
+    return false;
+}
+
+bool isAlphaPresentinFB(hwc_context_t *ctx, int dpy) {
+    switch(ctx->dpyAttr[dpy].fbformat) {
+        case HAL_PIXEL_FORMAT_RGBA_8888:
+        case HAL_PIXEL_FORMAT_BGRA_8888:
+            return true;
+        default : return false;
+    }
+    return false;
+}
+
+static void trimLayer(hwc_context_t *ctx, const int& dpy, const int& transform,
+        hwc_rect_t& crop, hwc_rect_t& dst) {
+    int hw_w = ctx->dpyAttr[dpy].xres;
+    int hw_h = ctx->dpyAttr[dpy].yres;
+    if(dst.left < 0 || dst.top < 0 ||
+            dst.right > hw_w || dst.bottom > hw_h) {
+        hwc_rect_t scissor = {0, 0, hw_w, hw_h };
+        scissor = getIntersection(ctx->mViewFrame[dpy], scissor);
+        qhwc::calculate_crop_rects(crop, dst, scissor, transform);
+    }
+}
+
+static void trimList(hwc_context_t *ctx, hwc_display_contents_1_t *list,
+        const int& dpy) {
+    for(uint32_t i = 0; i < list->numHwLayers - 1; i++) {
+        hwc_layer_1_t *layer = &list->hwLayers[i];
+        hwc_rect_t crop = integerizeSourceCrop(layer->sourceCropf);
+        int transform = (list->hwLayers[i].flags & HWC_COLOR_FILL) ? 0 :
+                list->hwLayers[i].transform;
+        trimLayer(ctx, dpy,
+                transform,
+                (hwc_rect_t&)crop,
+                (hwc_rect_t&)list->hwLayers[i].displayFrame);
+        layer->sourceCropf.left = (float)crop.left;
+        layer->sourceCropf.right = (float)crop.right;
+        layer->sourceCropf.top = (float)crop.top;
+        layer->sourceCropf.bottom = (float)crop.bottom;
+    }
+}
+
+void setListStats(hwc_context_t *ctx,
+        hwc_display_contents_1_t *list, int dpy) {
+    const int prevYuvCount = ctx->listStats[dpy].yuvCount;
+    memset(&ctx->listStats[dpy], 0, sizeof(ListStats));
+    ctx->listStats[dpy].numAppLayers = (int)list->numHwLayers - 1;
+    ctx->listStats[dpy].fbLayerIndex = (int)list->numHwLayers - 1;
+    ctx->listStats[dpy].skipCount = 0;
+    ctx->listStats[dpy].preMultipliedAlpha = false;
+    ctx->listStats[dpy].isSecurePresent = false;
+    ctx->listStats[dpy].yuvCount = 0;
+    char property[PROPERTY_VALUE_MAX];
+    ctx->listStats[dpy].isDisplayAnimating = false;
+    ctx->listStats[dpy].secureUI = false;
+    ctx->listStats[dpy].yuv4k2kCount = 0;
+    ctx->dpyAttr[dpy].mActionSafePresent = isActionSafePresent(ctx, dpy);
+    ctx->listStats[dpy].renderBufIndexforABC = -1;
+    ctx->listStats[dpy].secureRGBCount = 0;
+    ctx->listStats[dpy].refreshRateRequest = ctx->dpyAttr[dpy].refreshRate;
+    uint32_t refreshRate = 0;
+    qdutils::MDPVersion& mdpHw = qdutils::MDPVersion::getInstance();
+
+    ctx->listStats[dpy].mAIVVideoMode = false;
+    resetROI(ctx, dpy);
+
+    trimList(ctx, list, dpy);
+    optimizeLayerRects(list);
+    for (size_t i = 0; i < (size_t)ctx->listStats[dpy].numAppLayers; i++) {
+        hwc_layer_1_t const* layer = &list->hwLayers[i];
+        private_handle_t *hnd = (private_handle_t *)layer->handle;
+
+#ifdef QTI_BSP
+        // Window boxing feature is applicable obly for external display, So
+        // enable mAIVVideoMode only for external display
+        if(ctx->mWindowboxFeature && dpy && isAIVVideoLayer(layer)) {
+            ctx->listStats[dpy].mAIVVideoMode = true;
+        }
+        if (layer->flags & HWC_SCREENSHOT_ANIMATOR_LAYER) {
+            ctx->listStats[dpy].isDisplayAnimating = true;
+        }
+        if(isSecureDisplayBuffer(hnd)) {
+            ctx->listStats[dpy].secureUI = true;
+        }
+#endif
+        // continue if number of app layers exceeds MAX_NUM_APP_LAYERS
+        if(ctx->listStats[dpy].numAppLayers > MAX_NUM_APP_LAYERS)
+            continue;
+
+        //reset yuv indices
+        ctx->listStats[dpy].yuvIndices[i] = -1;
+        ctx->listStats[dpy].yuv4k2kIndices[i] = -1;
+
+        if (isSecureBuffer(hnd)) {
+            ctx->listStats[dpy].isSecurePresent = true;
+            if(not isYuvBuffer(hnd)) {
+                // cache secureRGB layer parameters like we cache for YUV layers
+                int& secureRGBCount = ctx->listStats[dpy].secureRGBCount;
+                ctx->listStats[dpy].secureRGBIndices[secureRGBCount] = (int)i;
+                secureRGBCount++;
+            }
+        }
+
+        if (isSkipLayer(&list->hwLayers[i])) {
+            ctx->listStats[dpy].skipCount++;
+        }
+
+        if (UNLIKELY(isYuvBuffer(hnd))) {
+            int& yuvCount = ctx->listStats[dpy].yuvCount;
+            ctx->listStats[dpy].yuvIndices[yuvCount] = (int)i;
+            yuvCount++;
+
+            if(UNLIKELY(isYUVSplitNeeded(hnd))){
+                int& yuv4k2kCount = ctx->listStats[dpy].yuv4k2kCount;
+                ctx->listStats[dpy].yuv4k2kIndices[yuv4k2kCount] = (int)i;
+                yuv4k2kCount++;
+            }
+        }
+        if(layer->blending == HWC_BLENDING_PREMULT)
+            ctx->listStats[dpy].preMultipliedAlpha = true;
+
+#ifdef DYNAMIC_FPS
+        if (!dpy && mdpHw.isDynFpsSupported() && ctx->mUseMetaDataRefreshRate){
+            /* Dyn fps: get refreshrate from metadata */
+            MetaData_t *mdata = hnd ? (MetaData_t *)hnd->base_metadata : NULL;
+            if (mdata && (mdata->operation & UPDATE_REFRESH_RATE)) {
+                // Valid refreshRate in metadata and within the range
+                uint32_t rate = getRefreshRate(ctx, mdata->refreshrate);
+                if (!refreshRate) {
+                    refreshRate = rate;
+                } else if(refreshRate != rate) {
+                    /* Support multiple refresh rates if they are same
+                     * else set to default.
+                     */
+                    refreshRate = ctx->dpyAttr[dpy].refreshRate;
+                }
+            }
+        }
+#endif
+    }
+    if(ctx->listStats[dpy].yuvCount > 0) {
+        if (property_get("hw.cabl.yuv", property, NULL) > 0) {
+            if (atoi(property) != 1) {
+                property_set("hw.cabl.yuv", "1");
+            }
+        }
+    } else {
+        if (property_get("hw.cabl.yuv", property, NULL) > 0) {
+            if (atoi(property) != 0) {
+                property_set("hw.cabl.yuv", "0");
+            }
+        }
+    }
+
+    //The marking of video begin/end is useful on some targets where we need
+    //to have a padding round to be able to shift pipes across mixers.
+    if(prevYuvCount != ctx->listStats[dpy].yuvCount) {
+        ctx->mVideoTransFlag = true;
+    }
+
+    if(dpy == HWC_DISPLAY_PRIMARY) {
+        ctx->mAD->markDoable(ctx, list);
+        //Store the requested fresh rate
+        ctx->listStats[dpy].refreshRateRequest = refreshRate ?
+                                refreshRate : ctx->dpyAttr[dpy].refreshRate;
+    }
+}
+
+
+static void calc_cut(double& leftCutRatio, double& topCutRatio,
+        double& rightCutRatio, double& bottomCutRatio, int orient) {
+    if(orient & HAL_TRANSFORM_FLIP_H) {
+        swap(leftCutRatio, rightCutRatio);
+    }
+    if(orient & HAL_TRANSFORM_FLIP_V) {
+        swap(topCutRatio, bottomCutRatio);
+    }
+    if(orient & HAL_TRANSFORM_ROT_90) {
+        //Anti clock swapping
+        double tmpCutRatio = leftCutRatio;
+        leftCutRatio = topCutRatio;
+        topCutRatio = rightCutRatio;
+        rightCutRatio = bottomCutRatio;
+        bottomCutRatio = tmpCutRatio;
+    }
+}
+
+bool isSecuring(hwc_context_t* ctx, hwc_layer_1_t const* layer) {
+    if((ctx->mMDP.version < qdutils::MDSS_V5) &&
+       (ctx->mMDP.version > qdutils::MDP_V3_0) &&
+        ctx->mSecuring) {
+        return true;
+    }
+    if (isSecureModePolicy(ctx->mMDP.version)) {
+        private_handle_t *hnd = (private_handle_t *)layer->handle;
+        if(ctx->mSecureMode) {
+            if (! isSecureBuffer(hnd)) {
+                ALOGD_IF(HWC_UTILS_DEBUG,"%s:Securing Turning ON ...",
+                         __FUNCTION__);
+                return true;
+            }
+        } else {
+            if (isSecureBuffer(hnd)) {
+                ALOGD_IF(HWC_UTILS_DEBUG,"%s:Securing Turning OFF ...",
+                         __FUNCTION__);
+                return true;
+            }
+        }
+    }
+    return false;
+}
+
+bool isSecureModePolicy(int mdpVersion) {
+    if (mdpVersion < qdutils::MDSS_V5)
+        return true;
+    else
+        return false;
+}
+
+bool isRotatorSupportedFormat(private_handle_t *hnd) {
+    // Following rotator src formats are supported by mdp driver
+    // TODO: Add more formats in future, if mdp driver adds support
+    switch(hnd->format) {
+        case HAL_PIXEL_FORMAT_RGBA_8888:
+        case HAL_PIXEL_FORMAT_RGB_565:
+        case HAL_PIXEL_FORMAT_RGB_888:
+        case HAL_PIXEL_FORMAT_BGRA_8888:
+            return true;
+        default:
+            return false;
+    }
+    return false;
+}
+
+bool isRotationDoable(hwc_context_t *ctx, private_handle_t *hnd) {
+    // Rotate layers, if it is YUV type or rendered by CPU and not
+    // for the MDP versions below MDP5
+    if((isCPURendered(hnd) && isRotatorSupportedFormat(hnd) &&
+        !ctx->mMDP.version < qdutils::MDSS_V5)
+                   || isYuvBuffer(hnd)) {
+        return true;
+    }
+    return false;
+}
+
+// returns true if Action safe dimensions are set and target supports Actionsafe
+bool isActionSafePresent(hwc_context_t *ctx, int dpy) {
+    // if external supports underscan, do nothing
+    // it will be taken care in the driver
+    // Disable Action safe for 8974 due to HW limitation for downscaling
+    // layers with overlapped region
+    // Disable Actionsafe for non HDMI displays.
+    if(!(dpy == HWC_DISPLAY_EXTERNAL) ||
+        qdutils::MDPVersion::getInstance().is8x74v2() ||
+        ctx->mHDMIDisplay->isCEUnderscanSupported()) {
+        return false;
+    }
+
+    char value[PROPERTY_VALUE_MAX];
+    // Read action safe properties
+    property_get("persist.sys.actionsafe.width", value, "0");
+    ctx->dpyAttr[dpy].mAsWidthRatio = atoi(value);
+    property_get("persist.sys.actionsafe.height", value, "0");
+    ctx->dpyAttr[dpy].mAsHeightRatio = atoi(value);
+
+    if(!ctx->dpyAttr[dpy].mAsWidthRatio && !ctx->dpyAttr[dpy].mAsHeightRatio) {
+        //No action safe ratio set, return
+        return false;
+    }
+    return true;
+}
+
+int getBlending(int blending) {
+    switch(blending) {
+    case HWC_BLENDING_NONE:
+        return overlay::utils::OVERLAY_BLENDING_OPAQUE;
+    case HWC_BLENDING_PREMULT:
+        return overlay::utils::OVERLAY_BLENDING_PREMULT;
+    case HWC_BLENDING_COVERAGE :
+    default:
+        return overlay::utils::OVERLAY_BLENDING_COVERAGE;
+    }
+}
+
+//Crops source buffer against destination and FB boundaries
+void calculate_crop_rects(hwc_rect_t& crop, hwc_rect_t& dst,
+                          const hwc_rect_t& scissor, int orient) {
+
+    int& crop_l = crop.left;
+    int& crop_t = crop.top;
+    int& crop_r = crop.right;
+    int& crop_b = crop.bottom;
+    int crop_w = crop.right - crop.left;
+    int crop_h = crop.bottom - crop.top;
+
+    int& dst_l = dst.left;
+    int& dst_t = dst.top;
+    int& dst_r = dst.right;
+    int& dst_b = dst.bottom;
+    int dst_w = abs(dst.right - dst.left);
+    int dst_h = abs(dst.bottom - dst.top);
+
+    const int& sci_l = scissor.left;
+    const int& sci_t = scissor.top;
+    const int& sci_r = scissor.right;
+    const int& sci_b = scissor.bottom;
+
+    double leftCutRatio = 0.0, rightCutRatio = 0.0, topCutRatio = 0.0,
+            bottomCutRatio = 0.0;
+
+    if(dst_l < sci_l) {
+        leftCutRatio = (double)(sci_l - dst_l) / (double)dst_w;
+        dst_l = sci_l;
+    }
+
+    if(dst_r > sci_r) {
+        rightCutRatio = (double)(dst_r - sci_r) / (double)dst_w;
+        dst_r = sci_r;
+    }
+
+    if(dst_t < sci_t) {
+        topCutRatio = (double)(sci_t - dst_t) / (double)dst_h;
+        dst_t = sci_t;
+    }
+
+    if(dst_b > sci_b) {
+        bottomCutRatio = (double)(dst_b - sci_b) / (double)dst_h;
+        dst_b = sci_b;
+    }
+
+    calc_cut(leftCutRatio, topCutRatio, rightCutRatio, bottomCutRatio, orient);
+    crop_l += (int)round((double)crop_w * leftCutRatio);
+    crop_t += (int)round((double)crop_h * topCutRatio);
+    crop_r -= (int)round((double)crop_w * rightCutRatio);
+    crop_b -= (int)round((double)crop_h * bottomCutRatio);
+}
+
+bool areLayersIntersecting(const hwc_layer_1_t* layer1,
+        const hwc_layer_1_t* layer2) {
+    hwc_rect_t irect = getIntersection(layer1->displayFrame,
+            layer2->displayFrame);
+    return isValidRect(irect);
+}
+
+bool isSameRect(const hwc_rect& rect1, const hwc_rect& rect2)
+{
+   return ((rect1.left == rect2.left) && (rect1.top == rect2.top) &&
+           (rect1.right == rect2.right) && (rect1.bottom == rect2.bottom));
+}
+
+bool isValidRect(const hwc_rect& rect)
+{
+   return ((rect.bottom > rect.top) && (rect.right > rect.left)) ;
+}
+
+bool operator ==(const hwc_rect_t& lhs, const hwc_rect_t& rhs) {
+    if(lhs.left == rhs.left && lhs.top == rhs.top &&
+       lhs.right == rhs.right &&  lhs.bottom == rhs.bottom )
+          return true ;
+    return false;
+}
+
+bool layerUpdating(const hwc_layer_1_t* layer) {
+     hwc_region_t surfDamage = layer->surfaceDamage;
+     return ((surfDamage.numRects == 0) ||
+              isValidRect(layer->surfaceDamage.rects[0]));
+}
+
+hwc_rect_t calculateDirtyRect(const hwc_layer_1_t* layer,
+                                       hwc_rect_t& scissor) {
+    hwc_region_t surfDamage = layer->surfaceDamage;
+    hwc_rect_t src = integerizeSourceCrop(layer->sourceCropf);
+    hwc_rect_t dst = layer->displayFrame;
+    int x_off = dst.left - src.left;
+    int y_off = dst.top - src.top;
+    hwc_rect dirtyRect = (hwc_rect){0, 0, 0, 0};
+    hwc_rect_t updatingRect = dst;
+
+    if (surfDamage.numRects == 0) {
+      // full layer updating, dirty rect is full frame
+        dirtyRect = getIntersection(layer->displayFrame, scissor);
+    } else {
+        for(uint32_t i = 0; i < surfDamage.numRects; i++) {
+            updatingRect = moveRect(surfDamage.rects[i], x_off, y_off);
+            hwc_rect_t intersect = getIntersection(updatingRect, scissor);
+            if(isValidRect(intersect)) {
+               dirtyRect = getUnion(intersect, dirtyRect);
+            }
+        }
+     }
+     return dirtyRect;
+}
+
+hwc_rect_t moveRect(const hwc_rect_t& rect, const int& x_off, const int& y_off)
+{
+    hwc_rect_t res;
+
+    if(!isValidRect(rect))
+        return (hwc_rect_t){0, 0, 0, 0};
+
+    res.left = rect.left + x_off;
+    res.top = rect.top + y_off;
+    res.right = rect.right + x_off;
+    res.bottom = rect.bottom + y_off;
+
+    return res;
+}
+
+/* computes the intersection of two rects */
+hwc_rect_t getIntersection(const hwc_rect_t& rect1, const hwc_rect_t& rect2)
+{
+   hwc_rect_t res;
+
+   if(!isValidRect(rect1) || !isValidRect(rect2)){
+      return (hwc_rect_t){0, 0, 0, 0};
+   }
+
+
+   res.left = max(rect1.left, rect2.left);
+   res.top = max(rect1.top, rect2.top);
+   res.right = min(rect1.right, rect2.right);
+   res.bottom = min(rect1.bottom, rect2.bottom);
+
+   if(!isValidRect(res))
+      return (hwc_rect_t){0, 0, 0, 0};
+
+   return res;
+}
+
+/* computes the union of two rects */
+hwc_rect_t getUnion(const hwc_rect &rect1, const hwc_rect &rect2)
+{
+   hwc_rect_t res;
+
+   if(!isValidRect(rect1)){
+      return rect2;
+   }
+
+   if(!isValidRect(rect2)){
+      return rect1;
+   }
+
+   res.left = min(rect1.left, rect2.left);
+   res.top = min(rect1.top, rect2.top);
+   res.right =  max(rect1.right, rect2.right);
+   res.bottom =  max(rect1.bottom, rect2.bottom);
+
+   return res;
+}
+
+/* Not a geometrical rect deduction. Deducts rect2 from rect1 only if it results
+ * a single rect */
+hwc_rect_t deductRect(const hwc_rect_t& rect1, const hwc_rect_t& rect2) {
+
+   hwc_rect_t res = rect1;
+
+   if((rect1.left == rect2.left) && (rect1.right == rect2.right)) {
+      if((rect1.top == rect2.top) && (rect2.bottom <= rect1.bottom))
+         res.top = rect2.bottom;
+      else if((rect1.bottom == rect2.bottom)&& (rect2.top >= rect1.top))
+         res.bottom = rect2.top;
+   }
+   else if((rect1.top == rect2.top) && (rect1.bottom == rect2.bottom)) {
+      if((rect1.left == rect2.left) && (rect2.right <= rect1.right))
+         res.left = rect2.right;
+      else if((rect1.right == rect2.right)&& (rect2.left >= rect1.left))
+         res.right = rect2.left;
+   }
+   return res;
+}
+
+void optimizeLayerRects(const hwc_display_contents_1_t *list) {
+    int i= (int)list->numHwLayers-2;
+    while(i > 0) {
+        //see if there is no blending required.
+        //If it is opaque see if we can substract this region from below
+        //layers.
+        if(list->hwLayers[i].blending == HWC_BLENDING_NONE &&
+                list->hwLayers[i].planeAlpha == 0xFF) {
+            int j= i-1;
+            hwc_rect_t& topframe =
+                (hwc_rect_t&)list->hwLayers[i].displayFrame;
+            while(j >= 0) {
+               if(!needsScaling(&list->hwLayers[j])) {
+                  hwc_layer_1_t* layer = (hwc_layer_1_t*)&list->hwLayers[j];
+                  hwc_rect_t& bottomframe = layer->displayFrame;
+                  hwc_rect_t bottomCrop =
+                      integerizeSourceCrop(layer->sourceCropf);
+                  int transform = (layer->flags & HWC_COLOR_FILL) ? 0 :
+                      layer->transform;
+
+                  hwc_rect_t irect = getIntersection(bottomframe, topframe);
+                  if(isValidRect(irect)) {
+                     hwc_rect_t dest_rect;
+                     //if intersection is valid rect, deduct it
+                     dest_rect  = deductRect(bottomframe, irect);
+                     qhwc::calculate_crop_rects(bottomCrop, bottomframe,
+                                                dest_rect, transform);
+                     //Update layer sourceCropf
+                     layer->sourceCropf.left =(float)bottomCrop.left;
+                     layer->sourceCropf.top = (float)bottomCrop.top;
+                     layer->sourceCropf.right = (float)bottomCrop.right;
+                     layer->sourceCropf.bottom = (float)bottomCrop.bottom;
+                  }
+               }
+               j--;
+            }
+        }
+        i--;
+    }
+}
+
+void getNonWormholeRegion(hwc_display_contents_1_t* list,
+                              hwc_rect_t& nwr)
+{
+    size_t last = list->numHwLayers - 1;
+    hwc_rect_t fbDisplayFrame = list->hwLayers[last].displayFrame;
+    //Initiliaze nwr to first frame
+    nwr.left =  list->hwLayers[0].displayFrame.left;
+    nwr.top =  list->hwLayers[0].displayFrame.top;
+    nwr.right =  list->hwLayers[0].displayFrame.right;
+    nwr.bottom =  list->hwLayers[0].displayFrame.bottom;
+
+    for (size_t i = 1; i < last; i++) {
+        hwc_rect_t displayFrame = list->hwLayers[i].displayFrame;
+        nwr = getUnion(nwr, displayFrame);
+    }
+
+    //Intersect with the framebuffer
+    nwr = getIntersection(nwr, fbDisplayFrame);
+}
+
+bool isExternalActive(hwc_context_t* ctx) {
+    return ctx->dpyAttr[HWC_DISPLAY_EXTERNAL].isActive;
+}
+
+void closeAcquireFds(hwc_display_contents_1_t* list) {
+    if(LIKELY(list)) {
+        for(uint32_t i = 0; i < list->numHwLayers; i++) {
+            //Close the acquireFenceFds
+            //HWC_FRAMEBUFFER are -1 already by SF, rest we close.
+            if(list->hwLayers[i].acquireFenceFd >= 0) {
+                close(list->hwLayers[i].acquireFenceFd);
+                list->hwLayers[i].acquireFenceFd = -1;
+            }
+        }
+        //Writeback
+        if(list->outbufAcquireFenceFd >= 0) {
+            close(list->outbufAcquireFenceFd);
+            list->outbufAcquireFenceFd = -1;
+        }
+    }
+}
+
+int hwc_sync(hwc_context_t *ctx, hwc_display_contents_1_t* list, int dpy,
+        int fd) {
+    ATRACE_CALL();
+    int ret = 0;
+    int acquireFd[MAX_NUM_APP_LAYERS];
+    int count = 0;
+    int releaseFd = -1;
+    int retireFd = -1;
+    int fbFd = -1;
+    bool swapzero = false;
+
+    struct mdp_buf_sync data;
+    memset(&data, 0, sizeof(data));
+    data.acq_fen_fd = acquireFd;
+    data.rel_fen_fd = &releaseFd;
+    data.retire_fen_fd = &retireFd;
+    data.flags = MDP_BUF_SYNC_FLAG_RETIRE_FENCE;
+
+    char property[PROPERTY_VALUE_MAX];
+    if(property_get("debug.egl.swapinterval", property, "1") > 0) {
+        if(atoi(property) == 0)
+            swapzero = true;
+    }
+
+    bool isExtAnimating = false;
+    if(dpy)
+       isExtAnimating = ctx->listStats[dpy].isDisplayAnimating;
+
+    //Send acquireFenceFds to rotator
+    for(uint32_t i = 0; i < ctx->mLayerRotMap[dpy]->getCount(); i++) {
+        int rotFd = ctx->mRotMgr->getRotDevFd();
+        int rotReleaseFd = -1;
+        overlay::Rotator* currRot = ctx->mLayerRotMap[dpy]->getRot(i);
+        hwc_layer_1_t* currLayer = ctx->mLayerRotMap[dpy]->getLayer(i);
+        if((currRot == NULL) || (currLayer == NULL)) {
+            continue;
+        }
+        struct mdp_buf_sync rotData;
+        memset(&rotData, 0, sizeof(rotData));
+        rotData.acq_fen_fd =
+                &currLayer->acquireFenceFd;
+        rotData.rel_fen_fd = &rotReleaseFd; //driver to populate this
+        rotData.session_id = currRot->getSessId();
+        if(currLayer->acquireFenceFd >= 0) {
+            rotData.acq_fen_fd_cnt = 1; //1 ioctl call per rot session
+        }
+        int ret = 0;
+        if(LIKELY(!swapzero) and (not ctx->mLayerRotMap[dpy]->isRotCached(i)))
+            ret = ioctl(rotFd, MSMFB_BUFFER_SYNC, &rotData);
+
+        if(ret < 0) {
+            ALOGE("%s: ioctl MSMFB_BUFFER_SYNC failed for rot sync, err=%s",
+                    __FUNCTION__, strerror(errno));
+            close(rotReleaseFd);
+        } else {
+            close(currLayer->acquireFenceFd);
+            //For MDP to wait on.
+            currLayer->acquireFenceFd =
+                    dup(rotReleaseFd);
+            //A buffer is free to be used by producer as soon as its copied to
+            //rotator
+            currLayer->releaseFenceFd =
+                    rotReleaseFd;
+        }
+    }
+
+    //Accumulate acquireFenceFds for MDP Overlays
+    if(list->outbufAcquireFenceFd >= 0) {
+        //Writeback output buffer
+        if(LIKELY(!swapzero) )
+            acquireFd[count++] = list->outbufAcquireFenceFd;
+    }
+
+    for(uint32_t i = 0; i < list->numHwLayers; i++) {
+        if(((isAbcInUse(ctx)== true ) ||
+          (list->hwLayers[i].compositionType == HWC_OVERLAY)) &&
+                        list->hwLayers[i].acquireFenceFd >= 0) {
+            if(LIKELY(!swapzero) ) {
+                // if ABC is enabled for more than one layer.
+                // renderBufIndexforABC will work as FB.Hence
+                // set the acquireFD from fd - which is coming from copybit
+                if(fd >= 0 && (isAbcInUse(ctx) == true)) {
+                    if(ctx->listStats[dpy].renderBufIndexforABC ==(int32_t)i)
+                        acquireFd[count++] = fd;
+                    else
+                        continue;
+                } else
+                    acquireFd[count++] = list->hwLayers[i].acquireFenceFd;
+            }
+        }
+        if(list->hwLayers[i].compositionType == HWC_FRAMEBUFFER_TARGET) {
+            if(LIKELY(!swapzero) ) {
+                if(fd >= 0) {
+                    //set the acquireFD from fd - which is coming from c2d
+                    acquireFd[count++] = fd;
+                    // Buffer sync IOCTL should be async when using c2d fence is
+                    // used
+                    data.flags &= ~MDP_BUF_SYNC_FLAG_WAIT;
+                } else if(list->hwLayers[i].acquireFenceFd >= 0)
+                    acquireFd[count++] = list->hwLayers[i].acquireFenceFd;
+            }
+        }
+    }
+
+    if ((fd >= 0) && !dpy && ctx->mPtorInfo.isActive()) {
+        // Acquire c2d fence of Overlap render buffer
+        if(LIKELY(!swapzero) )
+            acquireFd[count++] = fd;
+    }
+
+    data.acq_fen_fd_cnt = count;
+    fbFd = ctx->dpyAttr[dpy].fd;
+
+    //Waits for acquire fences, returns a release fence
+    if(LIKELY(!swapzero)) {
+        ret = ioctl(fbFd, MSMFB_BUFFER_SYNC, &data);
+    }
+
+    if(ret < 0) {
+        ALOGE("%s: ioctl MSMFB_BUFFER_SYNC failed, err=%s",
+                  __FUNCTION__, strerror(errno));
+        ALOGE("%s: acq_fen_fd_cnt=%d flags=%d fd=%d dpy=%d numHwLayers=%zu",
+              __FUNCTION__, data.acq_fen_fd_cnt, data.flags, fbFd,
+              dpy, list->numHwLayers);
+        close(releaseFd);
+        releaseFd = -1;
+        close(retireFd);
+        retireFd = -1;
+    }
+
+    for(uint32_t i = 0; i < list->numHwLayers; i++) {
+        if(list->hwLayers[i].compositionType == HWC_OVERLAY ||
+#ifdef QTI_BSP
+           list->hwLayers[i].compositionType == HWC_BLIT ||
+#endif
+           list->hwLayers[i].compositionType == HWC_FRAMEBUFFER_TARGET) {
+            //Populate releaseFenceFds.
+            if(UNLIKELY(swapzero)) {
+                list->hwLayers[i].releaseFenceFd = -1;
+            } else if(isExtAnimating) {
+                // Release all the app layer fds immediately,
+                // if animation is in progress.
+                list->hwLayers[i].releaseFenceFd = -1;
+            } else if(list->hwLayers[i].releaseFenceFd < 0 ) {
+#ifdef QTI_BSP
+                //If rotator has not already populated this field
+                // & if it's a not VPU layer
+
+                // if ABC is enabled for more than one layer
+                if(fd >= 0 && (isAbcInUse(ctx) == true) &&
+                  ctx->listStats[dpy].renderBufIndexforABC !=(int32_t)i){
+                    list->hwLayers[i].releaseFenceFd = dup(fd);
+                } else if((list->hwLayers[i].compositionType == HWC_BLIT)&&
+                                               (isAbcInUse(ctx) == false)){
+                    //For Blit, the app layers should be released when the Blit
+                    //is complete. This fd was passed from copybit->draw
+                    list->hwLayers[i].releaseFenceFd = dup(fd);
+                } else
+#endif
+                {
+                    list->hwLayers[i].releaseFenceFd = dup(releaseFd);
+                }
+            }
+        }
+    }
+
+    if(fd >= 0) {
+        close(fd);
+        fd = -1;
+    }
+
+    if (ctx->mCopyBit[dpy]) {
+        if (!dpy && ctx->mPtorInfo.isActive())
+            ctx->mCopyBit[dpy]->setReleaseFdSync(releaseFd);
+        else
+            ctx->mCopyBit[dpy]->setReleaseFd(releaseFd);
+    }
+
+    //Signals when MDP finishes reading rotator buffers.
+    ctx->mLayerRotMap[dpy]->setReleaseFd(releaseFd);
+    close(releaseFd);
+    releaseFd = -1;
+
+    if(UNLIKELY(swapzero)) {
+        list->retireFenceFd = -1;
+    } else {
+        list->retireFenceFd = retireFd;
+    }
+    return ret;
+}
+
+void setMdpFlags(hwc_context_t *ctx, hwc_layer_1_t *layer,
+        ovutils::eMdpFlags &mdpFlags,
+        int rotDownscale, int transform) {
+    private_handle_t *hnd = (private_handle_t *)layer->handle;
+    MetaData_t *metadata = hnd ? (MetaData_t *)hnd->base_metadata : NULL;
+
+    if(layer->blending == HWC_BLENDING_PREMULT) {
+        ovutils::setMdpFlags(mdpFlags,
+                ovutils::OV_MDP_BLEND_FG_PREMULT);
+    }
+
+    if(metadata && (metadata->operation & PP_PARAM_INTERLACED) &&
+            metadata->interlaced) {
+        ovutils::setMdpFlags(mdpFlags,
+                ovutils::OV_MDP_DEINTERLACE);
+    }
+
+    // Mark MDP flags with SECURE_OVERLAY_SESSION for driver
+    if(isSecureBuffer(hnd)) {
+        ovutils::setMdpFlags(mdpFlags,
+                ovutils::OV_MDP_SECURE_OVERLAY_SESSION);
+    }
+
+    if(isSecureDisplayBuffer(hnd)) {
+        // Mark MDP flags with SECURE_DISPLAY_OVERLAY_SESSION for driver
+        ovutils::setMdpFlags(mdpFlags,
+                             ovutils::OV_MDP_SECURE_DISPLAY_OVERLAY_SESSION);
+    }
+
+    //Pre-rotation will be used using rotator.
+    if(has90Transform(layer) && isRotationDoable(ctx, hnd)) {
+        ovutils::setMdpFlags(mdpFlags,
+                ovutils::OV_MDP_SOURCE_ROTATED_90);
+    }
+    //No 90 component and no rot-downscale then flips done by MDP
+    //If we use rot then it might as well do flips
+    if(!(transform & HWC_TRANSFORM_ROT_90) && !rotDownscale) {
+        if(transform & HWC_TRANSFORM_FLIP_H) {
+            ovutils::setMdpFlags(mdpFlags, ovutils::OV_MDP_FLIP_H);
+        }
+
+        if(transform & HWC_TRANSFORM_FLIP_V) {
+            ovutils::setMdpFlags(mdpFlags,  ovutils::OV_MDP_FLIP_V);
+        }
+    }
+
+    if(metadata &&
+        ((metadata->operation & PP_PARAM_HSIC)
+        || (metadata->operation & PP_PARAM_IGC)
+        || (metadata->operation & PP_PARAM_SHARP2))) {
+        ovutils::setMdpFlags(mdpFlags, ovutils::OV_MDP_PP_EN);
+    }
+}
+
+int configRotator(Rotator *rot, Whf& whf,
+        hwc_rect_t& crop, const eMdpFlags& mdpFlags,
+        const eTransform& orient, const int& downscale) {
+
+    // Fix alignments for TILED format
+    if(whf.format == MDP_Y_CRCB_H2V2_TILE ||
+                            whf.format == MDP_Y_CBCR_H2V2_TILE) {
+        whf.w =  utils::alignup(whf.w, 64);
+        whf.h = utils::alignup(whf.h, 32);
+    }
+    rot->setSource(whf);
+
+    if (qdutils::MDPVersion::getInstance().getMDPVersion() >=
+        qdutils::MDSS_V5) {
+         Dim rotCrop(crop.left, crop.top, crop.right - crop.left,
+                crop.bottom - crop.top);
+        rot->setCrop(rotCrop);
+    }
+
+    rot->setFlags(mdpFlags);
+    rot->setTransform(orient);
+    rot->setDownscale(downscale);
+    if(!rot->commit()) return -1;
+    return 0;
+}
+
+int configMdp(Overlay *ov, const PipeArgs& parg,
+        const eTransform& orient, const hwc_rect_t& crop,
+        const hwc_rect_t& pos, const MetaData_t *metadata,
+        const eDest& dest) {
+    ov->setSource(parg, dest);
+    ov->setTransform(orient, dest);
+
+    int crop_w = crop.right - crop.left;
+    int crop_h = crop.bottom - crop.top;
+    Dim dcrop(crop.left, crop.top, crop_w, crop_h);
+    ov->setCrop(dcrop, dest);
+
+    int posW = pos.right - pos.left;
+    int posH = pos.bottom - pos.top;
+    Dim position(pos.left, pos.top, posW, posH);
+    ov->setPosition(position, dest);
+
+    if (metadata)
+        ov->setVisualParams(*metadata, dest);
+
+    if (!ov->commit(dest)) {
+        return -1;
+    }
+    return 0;
+}
+
+int configColorLayer(hwc_context_t *ctx, hwc_layer_1_t *layer,
+        const int& dpy, eMdpFlags& mdpFlags, eZorder& z,
+        const eDest& dest) {
+
+    hwc_rect_t dst = layer->displayFrame;
+    trimLayer(ctx, dpy, 0, dst, dst);
+
+    int w = ctx->dpyAttr[dpy].xres;
+    int h = ctx->dpyAttr[dpy].yres;
+    int dst_w = dst.right - dst.left;
+    int dst_h = dst.bottom - dst.top;
+    uint32_t color = layer->transform;
+    Whf whf(w, h, getMdpFormat(HAL_PIXEL_FORMAT_RGBA_8888), 0);
+
+    ovutils::setMdpFlags(mdpFlags, ovutils::OV_MDP_SOLID_FILL);
+    if (layer->blending == HWC_BLENDING_PREMULT)
+        ovutils::setMdpFlags(mdpFlags, ovutils::OV_MDP_BLEND_FG_PREMULT);
+
+    PipeArgs parg(mdpFlags, whf, z, static_cast<eRotFlags>(0),
+                  layer->planeAlpha,
+                  (ovutils::eBlending) getBlending(layer->blending));
+
+    // Configure MDP pipe for Color layer
+    Dim pos(dst.left, dst.top, dst_w, dst_h);
+    ctx->mOverlay->setSource(parg, dest);
+    ctx->mOverlay->setColor(color, dest);
+    ctx->mOverlay->setTransform(0, dest);
+    ctx->mOverlay->setCrop(pos, dest);
+    ctx->mOverlay->setPosition(pos, dest);
+
+    if (!ctx->mOverlay->commit(dest)) {
+        ALOGE("%s: Configure color layer failed!", __FUNCTION__);
+        return -1;
+    }
+    return 0;
+}
+
+void updateSource(eTransform& orient, Whf& whf,
+        hwc_rect_t& crop, Rotator *rot) {
+    Dim transformedCrop(crop.left, crop.top,
+            crop.right - crop.left,
+            crop.bottom - crop.top);
+    if (qdutils::MDPVersion::getInstance().getMDPVersion() >=
+        qdutils::MDSS_V5) {
+        //B-family rotator internally could modify destination dimensions if
+        //downscaling is supported
+        whf = rot->getDstWhf();
+        transformedCrop = rot->getDstDimensions();
+    } else {
+        //A-family rotator rotates entire buffer irrespective of crop, forcing
+        //us to recompute the crop based on transform
+        orient = static_cast<eTransform>(ovutils::getMdpOrient(orient));
+        preRotateSource(orient, whf, transformedCrop);
+    }
+
+    crop.left = transformedCrop.x;
+    crop.top = transformedCrop.y;
+    crop.right = transformedCrop.x + transformedCrop.w;
+    crop.bottom = transformedCrop.y + transformedCrop.h;
+}
+
+int getRotDownscale(hwc_context_t *ctx, const hwc_layer_1_t *layer) {
+    if(not qdutils::MDPVersion::getInstance().isRotDownscaleEnabled()) {
+        return 0;
+    }
+
+    int downscale = 0;
+    hwc_rect_t crop = integerizeSourceCrop(layer->sourceCropf);
+    hwc_rect_t dst = layer->displayFrame;
+    private_handle_t *hnd = (private_handle_t *)layer->handle;
+
+    if(not hnd) {
+        return 0;
+    }
+
+    MetaData_t *metadata = (MetaData_t *)hnd->base_metadata;
+    bool isInterlaced = metadata && (metadata->operation & PP_PARAM_INTERLACED)
+                && metadata->interlaced;
+    int transform = layer->transform;
+    uint32_t format = ovutils::getMdpFormat(hnd->format, isTileRendered(hnd));
+
+    if(isYuvBuffer(hnd)) {
+        if(ctx->mMDP.version >= qdutils::MDP_V4_2 &&
+                ctx->mMDP.version < qdutils::MDSS_V5) {
+            downscale = Rotator::getDownscaleFactor(crop.right - crop.left,
+                    crop.bottom - crop.top, dst.right - dst.left,
+                    dst.bottom - dst.top, format, isInterlaced);
+        } else {
+            Dim adjCrop(crop.left, crop.top, crop.right - crop.left,
+                    crop.bottom - crop.top);
+            Dim pos(dst.left, dst.top, dst.right - dst.left,
+                    dst.bottom - dst.top);
+            if(transform & HAL_TRANSFORM_ROT_90) {
+                swap(adjCrop.w, adjCrop.h);
+            }
+            downscale = Rotator::getDownscaleFactor(adjCrop.w, adjCrop.h, pos.w,
+                    pos.h, format, isInterlaced);
+        }
+    }
+    return downscale;
+}
+
+bool isZoomModeEnabled(hwc_rect_t crop) {
+    // This does not work for zooming in top left corner of the image
+    return(crop.top > 0 || crop.left > 0);
+}
+
+void updateCropAIVVideoMode(hwc_context_t *ctx, hwc_rect_t& crop, int dpy) {
+    ALOGD_IF(HWC_UTILS_DEBUG, "dpy %d Source crop [%d %d %d %d]", dpy,
+             crop.left, crop.top, crop.right, crop.bottom);
+    if(isZoomModeEnabled(crop)) {
+        Dim srcCrop(crop.left, crop.top,
+                crop.right - crop.left,
+                crop.bottom - crop.top);
+        int extW = ctx->dpyAttr[dpy].xres;
+        int extH = ctx->dpyAttr[dpy].yres;
+        //Crop the original video in order to fit external display aspect ratio
+        if(srcCrop.w * extH < extW * srcCrop.h) {
+            int offset = (srcCrop.h - ((srcCrop.w * extH) / extW)) / 2;
+            crop.top += offset;
+            crop.bottom -= offset;
+        } else {
+            int offset = (srcCrop.w - ((extW * srcCrop.h) / extH)) / 2;
+            crop.left += offset;
+            crop.right -= offset;
+        }
+        ALOGD_IF(HWC_UTILS_DEBUG, "External Resolution [%d %d] dpy %d Modified"
+                 " source crop [%d %d %d %d]", extW, extH, dpy,
+                 crop.left, crop.top, crop.right, crop.bottom);
+    }
+}
+
+void updateDestAIVVideoMode(hwc_context_t *ctx, hwc_rect_t crop,
+                           hwc_rect_t& dst, int dpy) {
+    ALOGD_IF(HWC_UTILS_DEBUG, "dpy %d Destination position [%d %d %d %d]", dpy,
+             dst.left, dst.top, dst.right, dst.bottom);
+    Dim srcCrop(crop.left, crop.top,
+            crop.right - crop.left,
+            crop.bottom - crop.top);
+    int extW = ctx->dpyAttr[dpy].xres;
+    int extH = ctx->dpyAttr[dpy].yres;
+    // Set the destination coordinates of external display to full screen,
+    // when zoom in mode is enabled or the ratio between video aspect ratio
+    // and external display aspect ratio is below the minimum tolerance level
+    // and above maximum tolerance level
+    float videoAspectRatio = ((float)srcCrop.w / (float)srcCrop.h);
+    float extDisplayAspectRatio = ((float)extW / (float)extH);
+    float videoToExternalRatio = videoAspectRatio / extDisplayAspectRatio;
+    if((fabs(1.0f - videoToExternalRatio) <= ctx->mAspectRatioToleranceLevel) ||
+        (isZoomModeEnabled(crop))) {
+        dst.left = 0;
+        dst.top = 0;
+        dst.right = extW;
+        dst.bottom = extH;
+    }
+    ALOGD_IF(HWC_UTILS_DEBUG, "External Resolution [%d %d] dpy %d Modified"
+             " Destination position [%d %d %d %d] Source crop [%d %d %d %d]",
+             extW, extH, dpy, dst.left, dst.top, dst.right, dst.bottom,
+             crop.left, crop.top, crop.right, crop.bottom);
+}
+
+void updateCoordinates(hwc_context_t *ctx, hwc_rect_t& crop,
+                           hwc_rect_t& dst, int dpy) {
+    updateCropAIVVideoMode(ctx, crop, dpy);
+    updateDestAIVVideoMode(ctx, crop, dst, dpy);
+}
+
+int configureNonSplit(hwc_context_t *ctx, hwc_layer_1_t *layer,
+        const int& dpy, eMdpFlags& mdpFlags, eZorder& z,
+        const eDest& dest, Rotator **rot) {
+
+    private_handle_t *hnd = (private_handle_t *)layer->handle;
+
+    if(!hnd) {
+        if (layer->flags & HWC_COLOR_FILL) {
+            // Configure Color layer
+            return configColorLayer(ctx, layer, dpy, mdpFlags, z, dest);
+        }
+        ALOGE("%s: layer handle is NULL", __FUNCTION__);
+        return -1;
+    }
+
+    MetaData_t *metadata = (MetaData_t *)hnd->base_metadata;
+
+    hwc_rect_t crop = integerizeSourceCrop(layer->sourceCropf);
+    hwc_rect_t dst = layer->displayFrame;
+    int transform = layer->transform;
+    eTransform orient = static_cast<eTransform>(transform);
+    int rotFlags = ovutils::ROT_FLAGS_NONE;
+    uint32_t format = ovutils::getMdpFormat(hnd->format, isTileRendered(hnd));
+    Whf whf(getWidth(hnd), getHeight(hnd), format, (uint32_t)hnd->size);
+
+    // Handle R/B swap
+    if (layer->flags & HWC_FORMAT_RB_SWAP) {
+        if (hnd->format == HAL_PIXEL_FORMAT_RGBA_8888)
+            whf.format = getMdpFormat(HAL_PIXEL_FORMAT_BGRA_8888);
+        else if (hnd->format == HAL_PIXEL_FORMAT_RGBX_8888)
+            whf.format = getMdpFormat(HAL_PIXEL_FORMAT_BGRX_8888);
+    }
+    // update source crop and destination position of AIV video layer.
+    if(ctx->listStats[dpy].mAIVVideoMode && isYuvBuffer(hnd)) {
+        updateCoordinates(ctx, crop, dst, dpy);
+    }
+    calcExtDisplayPosition(ctx, hnd, dpy, crop, dst, transform, orient);
+    int downscale = getRotDownscale(ctx, layer);
+    setMdpFlags(ctx, layer, mdpFlags, downscale, transform);
+
+    //if 90 component or downscale, use rot
+    if((has90Transform(layer) or downscale) and isRotationDoable(ctx, hnd)) {
+        *rot = ctx->mRotMgr->getNext();
+        if(*rot == NULL) return -1;
+        ctx->mLayerRotMap[dpy]->add(layer, *rot);
+        // BWC is not tested for other formats So enable it only for YUV format
+        if(!dpy && isYuvBuffer(hnd))
+            BwcPM::setBwc(crop, dst, transform, downscale, mdpFlags);
+        //Configure rotator for pre-rotation
+        if(configRotator(*rot, whf, crop, mdpFlags, orient, downscale) < 0) {
+            ALOGE("%s: configRotator failed!", __FUNCTION__);
+            return -1;
+        }
+        updateSource(orient, whf, crop, *rot);
+        rotFlags |= ROT_PREROTATED;
+    }
+
+    //For the mdp, since either we are pre-rotating or MDP does flips
+    orient = OVERLAY_TRANSFORM_0;
+    transform = 0;
+    PipeArgs parg(mdpFlags, whf, z,
+                  static_cast<eRotFlags>(rotFlags), layer->planeAlpha,
+                  (ovutils::eBlending) getBlending(layer->blending));
+
+    if(configMdp(ctx->mOverlay, parg, orient, crop, dst, metadata, dest) < 0) {
+        ALOGE("%s: commit failed for low res panel", __FUNCTION__);
+        return -1;
+    }
+    return 0;
+}
+
+//Helper to 1) Ensure crops dont have gaps 2) Ensure L and W are even
+void sanitizeSourceCrop(hwc_rect_t& cropL, hwc_rect_t& cropR,
+        private_handle_t *hnd) {
+    if(cropL.right - cropL.left) {
+        if(isYuvBuffer(hnd)) {
+            //Always safe to even down left
+            ovutils::even_floor(cropL.left);
+            //If right is even, automatically width is even, since left is
+            //already even
+            ovutils::even_floor(cropL.right);
+        }
+        //Make sure there are no gaps between left and right splits if the layer
+        //is spread across BOTH halves
+        if(cropR.right - cropR.left) {
+            cropR.left = cropL.right;
+        }
+    }
+
+    if(cropR.right - cropR.left) {
+        if(isYuvBuffer(hnd)) {
+            //Always safe to even down left
+            ovutils::even_floor(cropR.left);
+            //If right is even, automatically width is even, since left is
+            //already even
+            ovutils::even_floor(cropR.right);
+        }
+    }
+}
+
+int configureSplit(hwc_context_t *ctx, hwc_layer_1_t *layer,
+        const int& dpy, eMdpFlags& mdpFlagsL, eZorder& z,
+        const eDest& lDest, const eDest& rDest,
+        Rotator **rot) {
+    private_handle_t *hnd = (private_handle_t *)layer->handle;
+    if(!hnd) {
+        ALOGE("%s: layer handle is NULL", __FUNCTION__);
+        return -1;
+    }
+
+    MetaData_t *metadata = (MetaData_t *)hnd->base_metadata;
+
+    int hw_w = ctx->dpyAttr[dpy].xres;
+    int hw_h = ctx->dpyAttr[dpy].yres;
+    hwc_rect_t crop = integerizeSourceCrop(layer->sourceCropf);
+    hwc_rect_t dst = layer->displayFrame;
+    int transform = layer->transform;
+    eTransform orient = static_cast<eTransform>(transform);
+    int rotFlags = ROT_FLAGS_NONE;
+    uint32_t format = ovutils::getMdpFormat(hnd->format, isTileRendered(hnd));
+    Whf whf(getWidth(hnd), getHeight(hnd), format, (uint32_t)hnd->size);
+
+    // Handle R/B swap
+    if (layer->flags & HWC_FORMAT_RB_SWAP) {
+        if (hnd->format == HAL_PIXEL_FORMAT_RGBA_8888)
+            whf.format = getMdpFormat(HAL_PIXEL_FORMAT_BGRA_8888);
+        else if (hnd->format == HAL_PIXEL_FORMAT_RGBX_8888)
+            whf.format = getMdpFormat(HAL_PIXEL_FORMAT_BGRX_8888);
+    }
+
+    // update source crop and destination position of AIV video layer.
+    if(ctx->listStats[dpy].mAIVVideoMode && isYuvBuffer(hnd)) {
+        updateCoordinates(ctx, crop, dst, dpy);
+    }
+
+    /* Calculate the external display position based on MDP downscale,
+       ActionSafe, and extorientation features. */
+    calcExtDisplayPosition(ctx, hnd, dpy, crop, dst, transform, orient);
+    int downscale = getRotDownscale(ctx, layer);
+    setMdpFlags(ctx, layer, mdpFlagsL, downscale, transform);
+
+    if(lDest != OV_INVALID && rDest != OV_INVALID) {
+        //Enable overfetch
+        setMdpFlags(mdpFlagsL, OV_MDSS_MDP_DUAL_PIPE);
+    }
+
+    //Will do something only if feature enabled and conditions suitable
+    //hollow call otherwise
+    if(ctx->mAD->prepare(ctx, crop, whf, hnd)) {
+        overlay::Writeback *wb = overlay::Writeback::getInstance();
+        whf.format = wb->getOutputFormat();
+    }
+
+    if((has90Transform(layer) or downscale) and isRotationDoable(ctx, hnd)) {
+        (*rot) = ctx->mRotMgr->getNext();
+        if((*rot) == NULL) return -1;
+        ctx->mLayerRotMap[dpy]->add(layer, *rot);
+        //Configure rotator for pre-rotation
+        if(configRotator(*rot, whf, crop, mdpFlagsL, orient, downscale) < 0) {
+            ALOGE("%s: configRotator failed!", __FUNCTION__);
+            return -1;
+        }
+        updateSource(orient, whf, crop, *rot);
+        rotFlags |= ROT_PREROTATED;
+    }
+
+    eMdpFlags mdpFlagsR = mdpFlagsL;
+    setMdpFlags(mdpFlagsR, OV_MDSS_MDP_RIGHT_MIXER);
+
+    hwc_rect_t tmp_cropL = {0}, tmp_dstL = {0};
+    hwc_rect_t tmp_cropR = {0}, tmp_dstR = {0};
+
+    const int lSplit = getLeftSplit(ctx, dpy);
+
+    // Calculate Left rects
+    if(dst.left < lSplit) {
+        tmp_cropL = crop;
+        tmp_dstL = dst;
+        hwc_rect_t scissor = {0, 0, lSplit, hw_h };
+        scissor = getIntersection(ctx->mViewFrame[dpy], scissor);
+        qhwc::calculate_crop_rects(tmp_cropL, tmp_dstL, scissor, 0);
+    }
+
+    // Calculate Right rects
+    if(dst.right > lSplit) {
+        tmp_cropR = crop;
+        tmp_dstR = dst;
+        hwc_rect_t scissor = {lSplit, 0, hw_w, hw_h };
+        scissor = getIntersection(ctx->mViewFrame[dpy], scissor);
+        qhwc::calculate_crop_rects(tmp_cropR, tmp_dstR, scissor, 0);
+    }
+
+    sanitizeSourceCrop(tmp_cropL, tmp_cropR, hnd);
+
+    //When buffer is H-flipped, contents of mixer config also needs to swapped
+    //Not needed if the layer is confined to one half of the screen.
+    //If rotator has been used then it has also done the flips, so ignore them.
+    if((orient & OVERLAY_TRANSFORM_FLIP_H) && (dst.left < lSplit) &&
+            (dst.right > lSplit) && (*rot) == NULL) {
+        hwc_rect_t new_cropR;
+        new_cropR.left = tmp_cropL.left;
+        new_cropR.right = new_cropR.left + (tmp_cropR.right - tmp_cropR.left);
+
+        hwc_rect_t new_cropL;
+        new_cropL.left  = new_cropR.right;
+        new_cropL.right = tmp_cropR.right;
+
+        tmp_cropL.left =  new_cropL.left;
+        tmp_cropL.right =  new_cropL.right;
+
+        tmp_cropR.left = new_cropR.left;
+        tmp_cropR.right =  new_cropR.right;
+
+    }
+
+    //For the mdp, since either we are pre-rotating or MDP does flips
+    orient = OVERLAY_TRANSFORM_0;
+    transform = 0;
+
+    //configure left mixer
+    if(lDest != OV_INVALID) {
+        PipeArgs pargL(mdpFlagsL, whf, z,
+                       static_cast<eRotFlags>(rotFlags), layer->planeAlpha,
+                       (ovutils::eBlending) getBlending(layer->blending));
+
+        if(configMdp(ctx->mOverlay, pargL, orient,
+                tmp_cropL, tmp_dstL, metadata, lDest) < 0) {
+            ALOGE("%s: commit failed for left mixer config", __FUNCTION__);
+            return -1;
+        }
+    }
+
+    //configure right mixer
+    if(rDest != OV_INVALID) {
+        PipeArgs pargR(mdpFlagsR, whf, z,
+                       static_cast<eRotFlags>(rotFlags),
+                       layer->planeAlpha,
+                       (ovutils::eBlending) getBlending(layer->blending));
+        tmp_dstR.right = tmp_dstR.right - lSplit;
+        tmp_dstR.left = tmp_dstR.left - lSplit;
+        if(configMdp(ctx->mOverlay, pargR, orient,
+                tmp_cropR, tmp_dstR, metadata, rDest) < 0) {
+            ALOGE("%s: commit failed for right mixer config", __FUNCTION__);
+            return -1;
+        }
+    }
+
+    return 0;
+}
+
+int configureSourceSplit(hwc_context_t *ctx, hwc_layer_1_t *layer,
+        const int& dpy, eMdpFlags& mdpFlagsL, eZorder& z,
+        const eDest& lDest, const eDest& rDest,
+        Rotator **rot) {
+    private_handle_t *hnd = (private_handle_t *)layer->handle;
+    if(!hnd) {
+        ALOGE("%s: layer handle is NULL", __FUNCTION__);
+        return -1;
+    }
+
+    MetaData_t *metadata = (MetaData_t *)hnd->base_metadata;
+
+    hwc_rect_t crop = integerizeSourceCrop(layer->sourceCropf);;
+    hwc_rect_t dst = layer->displayFrame;
+    int transform = layer->transform;
+    eTransform orient = static_cast<eTransform>(transform);
+    const int downscale = 0;
+    int rotFlags = ROT_FLAGS_NONE;
+    //Splitting only YUV layer on primary panel needs different zorders
+    //for both layers as both the layers are configured to single mixer
+    eZorder lz = z;
+    eZorder rz = (eZorder)(z + 1);
+
+    Whf whf(getWidth(hnd), getHeight(hnd),
+            getMdpFormat(hnd->format), (uint32_t)hnd->size);
+
+    // update source crop and destination position of AIV video layer.
+    if(ctx->listStats[dpy].mAIVVideoMode && isYuvBuffer(hnd)) {
+        updateCoordinates(ctx, crop, dst, dpy);
+    }
+
+    /* Calculate the external display position based on MDP downscale,
+       ActionSafe, and extorientation features. */
+    calcExtDisplayPosition(ctx, hnd, dpy, crop, dst, transform, orient);
+
+    setMdpFlags(ctx, layer, mdpFlagsL, 0, transform);
+    trimLayer(ctx, dpy, transform, crop, dst);
+
+    if(has90Transform(layer) && isRotationDoable(ctx, hnd)) {
+        (*rot) = ctx->mRotMgr->getNext();
+        if((*rot) == NULL) return -1;
+        ctx->mLayerRotMap[dpy]->add(layer, *rot);
+        // BWC is not tested for other formats So enable it only for YUV format
+        if(!dpy && isYuvBuffer(hnd))
+            BwcPM::setBwc(crop, dst, transform, downscale, mdpFlagsL);
+        //Configure rotator for pre-rotation
+        if(configRotator(*rot, whf, crop, mdpFlagsL, orient, downscale) < 0) {
+            ALOGE("%s: configRotator failed!", __FUNCTION__);
+            return -1;
+        }
+        updateSource(orient, whf, crop, *rot);
+        rotFlags |= ROT_PREROTATED;
+    }
+
+    eMdpFlags mdpFlagsR = mdpFlagsL;
+    int lSplit = dst.left + (dst.right - dst.left)/2;
+
+    hwc_rect_t tmp_cropL = {0}, tmp_dstL = {0};
+    hwc_rect_t tmp_cropR = {0}, tmp_dstR = {0};
+
+    if(lDest != OV_INVALID) {
+        tmp_cropL = crop;
+        tmp_dstL = dst;
+        hwc_rect_t scissor = {dst.left, dst.top, lSplit, dst.bottom };
+        qhwc::calculate_crop_rects(tmp_cropL, tmp_dstL, scissor, 0);
+    }
+    if(rDest != OV_INVALID) {
+        tmp_cropR = crop;
+        tmp_dstR = dst;
+        hwc_rect_t scissor = {lSplit, dst.top, dst.right, dst.bottom };
+        qhwc::calculate_crop_rects(tmp_cropR, tmp_dstR, scissor, 0);
+    }
+
+    sanitizeSourceCrop(tmp_cropL, tmp_cropR, hnd);
+
+    //When buffer is H-flipped, contents of mixer config also needs to swapped
+    //Not needed if the layer is confined to one half of the screen.
+    //If rotator has been used then it has also done the flips, so ignore them.
+    if((orient & OVERLAY_TRANSFORM_FLIP_H) && lDest != OV_INVALID
+            && rDest != OV_INVALID && (*rot) == NULL) {
+        hwc_rect_t new_cropR;
+        new_cropR.left = tmp_cropL.left;
+        new_cropR.right = new_cropR.left + (tmp_cropR.right - tmp_cropR.left);
+
+        hwc_rect_t new_cropL;
+        new_cropL.left  = new_cropR.right;
+        new_cropL.right = tmp_cropR.right;
+
+        tmp_cropL.left =  new_cropL.left;
+        tmp_cropL.right =  new_cropL.right;
+
+        tmp_cropR.left = new_cropR.left;
+        tmp_cropR.right =  new_cropR.right;
+
+    }
+
+    //For the mdp, since either we are pre-rotating or MDP does flips
+    orient = OVERLAY_TRANSFORM_0;
+    transform = 0;
+
+    //configure left half
+    if(lDest != OV_INVALID) {
+        PipeArgs pargL(mdpFlagsL, whf, lz,
+                static_cast<eRotFlags>(rotFlags), layer->planeAlpha,
+                (ovutils::eBlending) getBlending(layer->blending));
+
+        if(configMdp(ctx->mOverlay, pargL, orient,
+                    tmp_cropL, tmp_dstL, metadata, lDest) < 0) {
+            ALOGE("%s: commit failed for left half config", __FUNCTION__);
+            return -1;
+        }
+    }
+
+    //configure right half
+    if(rDest != OV_INVALID) {
+        PipeArgs pargR(mdpFlagsR, whf, rz,
+                static_cast<eRotFlags>(rotFlags),
+                layer->planeAlpha,
+                (ovutils::eBlending) getBlending(layer->blending));
+        if(configMdp(ctx->mOverlay, pargR, orient,
+                    tmp_cropR, tmp_dstR, metadata, rDest) < 0) {
+            ALOGE("%s: commit failed for right half config", __FUNCTION__);
+            return -1;
+        }
+    }
+
+    return 0;
+}
+
+bool canUseRotator(hwc_context_t *ctx, int dpy) {
+    if(ctx->mOverlay->isDMAMultiplexingSupported() &&
+            isSecondaryConnected(ctx) &&
+            !ctx->dpyAttr[HWC_DISPLAY_VIRTUAL].isPause) {
+        /* mdss driver on certain targets support multiplexing of DMA pipe
+         * in LINE and BLOCK modes for writeback panels.
+         */
+        if(dpy == HWC_DISPLAY_PRIMARY)
+            return false;
+    }
+    if((ctx->mMDP.version == qdutils::MDP_V3_0_4)
+          ||(ctx->mMDP.version == qdutils::MDP_V3_0_5))
+        return false;
+    return true;
+}
+
+int getLeftSplit(hwc_context_t *ctx, const int& dpy) {
+    //Default even split for all displays with high res
+    int lSplit = ctx->dpyAttr[dpy].xres / 2;
+    if(dpy == HWC_DISPLAY_PRIMARY &&
+            qdutils::MDPVersion::getInstance().getLeftSplit()) {
+        //Override if split published by driver for primary
+        lSplit = qdutils::MDPVersion::getInstance().getLeftSplit();
+    }
+    return lSplit;
+}
+
+bool isDisplaySplit(hwc_context_t* ctx, int dpy) {
+    qdutils::MDPVersion& mdpHw = qdutils::MDPVersion::getInstance();
+    if(ctx->dpyAttr[dpy].xres > mdpHw.getMaxMixerWidth()) {
+        return true;
+    }
+    //For testing we could split primary via device tree values
+    if(dpy == HWC_DISPLAY_PRIMARY && mdpHw.getRightSplit()) {
+        return true;
+    }
+    return false;
+}
+
+//clear prev layer prop flags and realloc for current frame
+void reset_layer_prop(hwc_context_t* ctx, int dpy, int numAppLayers) {
+    if(ctx->layerProp[dpy]) {
+       delete[] ctx->layerProp[dpy];
+       ctx->layerProp[dpy] = NULL;
+    }
+    ctx->layerProp[dpy] = new LayerProp[numAppLayers];
+}
+
+bool isAbcInUse(hwc_context_t *ctx){
+  return (ctx->enableABC && ctx->listStats[0].renderBufIndexforABC == 0);
+}
+
+void dumpBuffer(private_handle_t *ohnd, char *bufferName) {
+    if (ohnd != NULL && ohnd->base) {
+        char dumpFilename[PATH_MAX];
+        bool bResult = false;
+        int width = getWidth(ohnd);
+        int height = getHeight(ohnd);
+        int format = ohnd->format;
+        //dummy aligned w & h.
+        int alW = 0, alH = 0;
+        int size = getBufferSizeAndDimensions(width, height, format, alW, alH);
+        snprintf(dumpFilename, sizeof(dumpFilename), "/data/%s.%s.%dx%d.raw",
+            bufferName,
+            overlay::utils::getFormatString(utils::getMdpFormat(format)),
+            width, height);
+        FILE* fp = fopen(dumpFilename, "w+");
+        if (NULL != fp) {
+            bResult = (bool) fwrite((void*)ohnd->base, size, 1, fp);
+            fclose(fp);
+        }
+        ALOGD("Buffer[%s] Dump to %s: %s",
+        bufferName, dumpFilename, bResult ? "Success" : "Fail");
+    }
+}
+
+bool isGLESComp(hwc_context_t *ctx,
+                     hwc_display_contents_1_t* list) {
+    int numAppLayers = ctx->listStats[HWC_DISPLAY_PRIMARY].numAppLayers;
+    for(int index = 0; index < numAppLayers; index++) {
+        hwc_layer_1_t* layer = &(list->hwLayers[index]);
+        if(layer->compositionType == HWC_FRAMEBUFFER)
+            return true;
+    }
+    return false;
+}
+
+void setGPUHint(hwc_context_t* ctx, hwc_display_contents_1_t* list) {
+#ifdef QTI_BSP
+    struct gpu_hint_info *gpuHint = &ctx->mGPUHintInfo;
+    if(!gpuHint->mGpuPerfModeEnable || !ctx || !list)
+        return;
+
+    /* Set the GPU hint flag to high for MIXED/GPU composition only for
+       first frame after MDP -> GPU/MIXED mode transition. Set the GPU
+       hint to default if the previous composition is GPU or current GPU
+       composition is due to idle fallback */
+    if(!gpuHint->mEGLDisplay || !gpuHint->mEGLContext) {
+        gpuHint->mEGLDisplay = (*(ctx->mpfn_eglGetCurrentDisplay))();
+        if(!gpuHint->mEGLDisplay) {
+            ALOGW("%s Warning: EGL current display is NULL", __FUNCTION__);
+            return;
+        }
+        gpuHint->mEGLContext = (*(ctx->mpfn_eglGetCurrentContext))();
+        if(!gpuHint->mEGLContext) {
+            ALOGW("%s Warning: EGL current context is NULL", __FUNCTION__);
+            return;
+        }
+    }
+    if(isGLESComp(ctx, list)) {
+        if(gpuHint->mCompositionState != COMPOSITION_STATE_GPU
+            && !MDPComp::isIdleFallback()) {
+            EGLint attr_list[] = {EGL_GPU_HINT_1,
+                                  EGL_GPU_LEVEL_3,
+                                  EGL_NONE };
+            if((gpuHint->mCurrGPUPerfMode != EGL_GPU_LEVEL_3) &&
+                !((*(ctx->mpfn_eglGpuPerfHintQCOM))(gpuHint->mEGLDisplay,
+                                    gpuHint->mEGLContext, attr_list))) {
+                ALOGW("eglGpuPerfHintQCOM failed for Built in display");
+            } else {
+                gpuHint->mCurrGPUPerfMode = EGL_GPU_LEVEL_3;
+                gpuHint->mCompositionState = COMPOSITION_STATE_GPU;
+            }
+        } else {
+            EGLint attr_list[] = {EGL_GPU_HINT_1,
+                                  EGL_GPU_LEVEL_0,
+                                  EGL_NONE };
+            if((gpuHint->mCurrGPUPerfMode != EGL_GPU_LEVEL_0) &&
+                !((*(ctx->mpfn_eglGpuPerfHintQCOM))(gpuHint->mEGLDisplay,
+                                    gpuHint->mEGLContext, attr_list))) {
+                ALOGW("eglGpuPerfHintQCOM failed for Built in display");
+            } else {
+                gpuHint->mCurrGPUPerfMode = EGL_GPU_LEVEL_0;
+            }
+            if(MDPComp::isIdleFallback()) {
+                gpuHint->mCompositionState = COMPOSITION_STATE_IDLE_FALLBACK;
+            }
+        }
+    } else {
+        /* set the GPU hint flag to default for MDP composition */
+        EGLint attr_list[] = {EGL_GPU_HINT_1,
+                              EGL_GPU_LEVEL_0,
+                              EGL_NONE };
+        if((gpuHint->mCurrGPUPerfMode != EGL_GPU_LEVEL_0) &&
+                !((*(ctx->mpfn_eglGpuPerfHintQCOM))(gpuHint->mEGLDisplay,
+                                    gpuHint->mEGLContext, attr_list))) {
+            ALOGW("eglGpuPerfHintQCOM failed for Built in display");
+        } else {
+            gpuHint->mCurrGPUPerfMode = EGL_GPU_LEVEL_0;
+        }
+        gpuHint->mCompositionState = COMPOSITION_STATE_MDP;
+    }
+#endif
+}
+
+bool isPeripheral(const hwc_rect_t& rect1, const hwc_rect_t& rect2) {
+    // To be peripheral, 3 boundaries should match.
+    uint8_t eqBounds = 0;
+    if (rect1.left == rect2.left)
+        eqBounds++;
+    if (rect1.top == rect2.top)
+        eqBounds++;
+    if (rect1.right == rect2.right)
+        eqBounds++;
+    if (rect1.bottom == rect2.bottom)
+        eqBounds++;
+    return (eqBounds == 3);
+}
+
+void processBootAnimCompleted(hwc_context_t *ctx) {
+    char value[PROPERTY_VALUE_MAX];
+    int ret = -1;
+
+    // Applying default mode after bootanimation is finished
+    property_get("init.svc.bootanim", value, "running");
+
+    if (!strncmp(value,"stopped",strlen("stopped"))) {
+        ctx->mBootAnimCompleted = true;
+
+        //one-shot action check if bootanimation completed then apply
+        //default display mode.
+        qdcmApplyDefaultAfterBootAnimationDone(ctx);
+    }
+}
+
+void BwcPM::setBwc(const hwc_rect_t& crop, const hwc_rect_t& dst,
+        const int& transform,const int& downscale,
+        ovutils::eMdpFlags& mdpFlags) {
+    //BWC not supported with rot-downscale
+    if(downscale) return;
+
+    //Target doesnt support Bwc
+    qdutils::MDPVersion& mdpHw = qdutils::MDPVersion::getInstance();
+    if(!mdpHw.supportsBWC()) {
+        return;
+    }
+    int src_w = crop.right - crop.left;
+    int src_h = crop.bottom - crop.top;
+    int dst_w = dst.right - dst.left;
+    int dst_h = dst.bottom - dst.top;
+    if(transform & HAL_TRANSFORM_ROT_90) {
+        swap(src_w, src_h);
+    }
+    //src width > MAX mixer supported dim
+    if(src_w > (int) qdutils::MDPVersion::getInstance().getMaxMixerWidth()) {
+        return;
+    }
+    //Decimation necessary, cannot use BWC. H/W requirement.
+    if(qdutils::MDPVersion::getInstance().supportsDecimation()) {
+        uint8_t horzDeci = 0;
+        uint8_t vertDeci = 0;
+        ovutils::getDecimationFactor(src_w, src_h, dst_w, dst_h, horzDeci,
+                vertDeci);
+        if(horzDeci || vertDeci) return;
+    }
+    //Property
+    char value[PROPERTY_VALUE_MAX];
+    property_get("debug.disable.bwc", value, "0");
+     if(atoi(value)) return;
+
+    ovutils::setMdpFlags(mdpFlags, ovutils::OV_MDSS_MDP_BWC_EN);
+}
+
+void LayerRotMap::add(hwc_layer_1_t* layer, Rotator *rot) {
+    if(mCount >= RotMgr::MAX_ROT_SESS) return;
+    mLayer[mCount] = layer;
+    mRot[mCount] = rot;
+    mCount++;
+}
+
+void LayerRotMap::reset() {
+    for (int i = 0; i < RotMgr::MAX_ROT_SESS; i++) {
+        mLayer[i] = 0;
+        mRot[i] = 0;
+    }
+    mCount = 0;
+}
+
+void LayerRotMap::clear() {
+    RotMgr::getInstance()->markUnusedTop(mCount);
+    reset();
+}
+
+bool LayerRotMap::isRotCached(uint32_t index) const {
+    overlay::Rotator* rot = getRot(index);
+    hwc_layer_1_t* layer =  getLayer(index);
+
+    if(rot and layer and layer->handle) {
+        private_handle_t *hnd = (private_handle_t *)(layer->handle);
+        return (rot->isRotCached(hnd->fd,(uint32_t)(hnd->offset)));
+    }
+    return false;
+}
+
+void LayerRotMap::setReleaseFd(const int& fence) {
+    for(uint32_t i = 0; i < mCount; i++) {
+        if(mRot[i] and mLayer[i] and mLayer[i]->handle) {
+            /* Ensure that none of the above (Rotator-instance,
+             * layer and layer-handle) are NULL*/
+            if(isRotCached(i))
+                mRot[i]->setPrevBufReleaseFd(dup(fence));
+            else
+                mRot[i]->setCurrBufReleaseFd(dup(fence));
+        }
+    }
+}
+
+void resetROI(hwc_context_t *ctx, const int dpy) {
+    const int fbXRes = (int)ctx->dpyAttr[dpy].xres;
+    const int fbYRes = (int)ctx->dpyAttr[dpy].yres;
+    if(isDisplaySplit(ctx, dpy)) {
+        const int lSplit = getLeftSplit(ctx, dpy);
+        ctx->listStats[dpy].lRoi = (struct hwc_rect){0, 0, lSplit, fbYRes};
+        ctx->listStats[dpy].rRoi = (struct hwc_rect){lSplit, 0, fbXRes, fbYRes};
+    } else  {
+        ctx->listStats[dpy].lRoi = (struct hwc_rect){0, 0,fbXRes, fbYRes};
+        ctx->listStats[dpy].rRoi = (struct hwc_rect){0, 0, 0, 0};
+    }
+}
+
+hwc_rect_t getSanitizeROI(struct hwc_rect roi, hwc_rect boundary)
+{
+   if(!isValidRect(roi))
+      return roi;
+
+   struct hwc_rect t_roi = roi;
+
+   const int LEFT_ALIGN = qdutils::MDPVersion::getInstance().getLeftAlign();
+   const int WIDTH_ALIGN = qdutils::MDPVersion::getInstance().getWidthAlign();
+   const int TOP_ALIGN = qdutils::MDPVersion::getInstance().getTopAlign();
+   const int HEIGHT_ALIGN = qdutils::MDPVersion::getInstance().getHeightAlign();
+   const int MIN_WIDTH = qdutils::MDPVersion::getInstance().getMinROIWidth();
+   const int MIN_HEIGHT = qdutils::MDPVersion::getInstance().getMinROIHeight();
+
+   /* Align to minimum width recommended by the panel */
+   if((t_roi.right - t_roi.left) < MIN_WIDTH) {
+       if((t_roi.left + MIN_WIDTH) > boundary.right)
+           t_roi.left = t_roi.right - MIN_WIDTH;
+       else
+           t_roi.right = t_roi.left + MIN_WIDTH;
+   }
+
+  /* Align to minimum height recommended by the panel */
+   if((t_roi.bottom - t_roi.top) < MIN_HEIGHT) {
+       if((t_roi.top + MIN_HEIGHT) > boundary.bottom)
+           t_roi.top = t_roi.bottom - MIN_HEIGHT;
+       else
+           t_roi.bottom = t_roi.top + MIN_HEIGHT;
+   }
+
+   /* Align left and width to meet panel restrictions */
+   if(LEFT_ALIGN)
+       t_roi.left = t_roi.left - (t_roi.left % LEFT_ALIGN);
+
+   if(WIDTH_ALIGN) {
+       int width = t_roi.right - t_roi.left;
+       width = WIDTH_ALIGN * ((width + (WIDTH_ALIGN - 1)) / WIDTH_ALIGN);
+       t_roi.right = t_roi.left + width;
+
+       if(t_roi.right > boundary.right) {
+           t_roi.right = boundary.right;
+           t_roi.left = t_roi.right - width;
+
+           if(LEFT_ALIGN)
+               t_roi.left = t_roi.left - (t_roi.left % LEFT_ALIGN);
+       }
+   }
+
+
+   /* Align top and height to meet panel restrictions */
+   if(TOP_ALIGN)
+       t_roi.top = t_roi.top - (t_roi.top % TOP_ALIGN);
+
+   if(HEIGHT_ALIGN) {
+       int height = t_roi.bottom - t_roi.top;
+       height = HEIGHT_ALIGN *  ((height + (HEIGHT_ALIGN - 1)) / HEIGHT_ALIGN);
+       t_roi.bottom = t_roi.top  + height;
+
+       if(t_roi.bottom > boundary.bottom) {
+           t_roi.bottom = boundary.bottom;
+           t_roi.top = t_roi.bottom - height;
+
+           if(TOP_ALIGN)
+               t_roi.top = t_roi.top - (t_roi.top % TOP_ALIGN);
+       }
+   }
+
+
+   return t_roi;
+}
+
+void handle_pause(hwc_context_t* ctx, int dpy) {
+    if(ctx->dpyAttr[dpy].connected) {
+        ctx->mDrawLock.lock();
+        ctx->dpyAttr[dpy].isActive = true;
+        ctx->dpyAttr[dpy].isPause = true;
+        ctx->mDrawLock.unlock();
+        ctx->proc->invalidate(ctx->proc);
+
+        usleep(ctx->dpyAttr[HWC_DISPLAY_PRIMARY].vsync_period
+               * 2 / 1000);
+
+        // At this point all the pipes used by External have been
+        // marked as UNSET.
+        ctx->mDrawLock.lock();
+        // Perform commit to unstage the pipes.
+        if (!Overlay::displayCommit(ctx->dpyAttr[dpy].fd)) {
+            ALOGE("%s: display commit fail! for %d dpy",
+                  __FUNCTION__, dpy);
+        }
+        ctx->mDrawLock.unlock();
+        ctx->proc->invalidate(ctx->proc);
+    }
+    return;
+}
+
+void handle_resume(hwc_context_t* ctx, int dpy) {
+    if(ctx->dpyAttr[dpy].connected) {
+        ctx->mDrawLock.lock();
+        ctx->dpyAttr[dpy].isConfiguring = true;
+        ctx->dpyAttr[dpy].isActive = true;
+        ctx->mDrawLock.unlock();
+        ctx->proc->invalidate(ctx->proc);
+
+        usleep(ctx->dpyAttr[HWC_DISPLAY_PRIMARY].vsync_period
+               * 2 / 1000);
+
+        //At this point external has all the pipes it would need.
+        ctx->mDrawLock.lock();
+        ctx->dpyAttr[dpy].isPause = false;
+        ctx->mDrawLock.unlock();
+        ctx->proc->invalidate(ctx->proc);
+    }
+    return;
+}
+
+void clearPipeResources(hwc_context_t* ctx, int dpy) {
+    if(ctx->mOverlay) {
+        ctx->mOverlay->configBegin();
+        ctx->mOverlay->configDone();
+    }
+    if(ctx->mRotMgr) {
+        ctx->mRotMgr->clear();
+    }
+    // Call a display commit to ensure that pipes and associated
+    // fd's are cleaned up.
+    if(!Overlay::displayCommit(ctx->dpyAttr[dpy].fd)) {
+        ALOGE("%s: display commit failed for  %d", __FUNCTION__, dpy);
+    }
+}
+
+// Handles online events when HDMI is the primary display. In particular,
+// online events for hdmi connected before AND after boot up and HWC init.
+void handle_online(hwc_context_t* ctx, int dpy) {
+    // Close the current fd if it was opened earlier on when HWC
+    // was initialized.
+    if (ctx->dpyAttr[dpy].fd >= 0) {
+        close(ctx->dpyAttr[dpy].fd);
+        ctx->dpyAttr[dpy].fd = -1;
+    }
+    // TODO: If HDMI is connected after the display has booted up,
+    // and the best configuration is different from the default
+    // then we need to deal with this appropriately.
+    ctx->mHDMIDisplay->configure();
+    updateDisplayInfo(ctx, dpy);
+    initCompositionResources(ctx, dpy);
+    ctx->dpyAttr[dpy].connected = true;
+}
+
+// Handles offline events for HDMI. This can be used for offline events
+// initiated by the HDMI driver and the CEC framework.
+void handle_offline(hwc_context_t* ctx, int dpy) {
+    destroyCompositionResources(ctx, dpy);
+    // Clear all pipe resources and call a display commit to ensure
+    // that all the fd's are closed. This will ensure that the HDMI
+    // core turns off and that we receive an event the next time the
+    // cable is connected.
+    if (ctx->mHDMIDisplay->isHDMIPrimaryDisplay()) {
+        clearPipeResources(ctx, dpy);
+    }
+    ctx->mHDMIDisplay->teardown();
+    resetDisplayInfo(ctx, dpy);
+    ctx->dpyAttr[dpy].connected = false;
+    ctx->dpyAttr[dpy].isActive = false;
+}
+
+bool loadEglLib(hwc_context_t* ctx) {
+    bool success = false;
+#ifdef QTI_BSP
+    const char* error;
+    dlerror();
+
+    ctx->mEglLib = dlopen("libEGL_adreno.so", RTLD_NOW);
+    if(ctx->mEglLib) {
+        *(void **)&(ctx->mpfn_eglGpuPerfHintQCOM) = dlsym(ctx->mEglLib, "eglGpuPerfHintQCOM");
+        *(void **)&(ctx->mpfn_eglGetCurrentDisplay) = dlsym(ctx->mEglLib,"eglGetCurrentDisplay");
+        *(void **)&(ctx->mpfn_eglGetCurrentContext) = dlsym(ctx->mEglLib,"eglGetCurrentContext");
+        if (!ctx->mpfn_eglGpuPerfHintQCOM ||
+            !ctx->mpfn_eglGetCurrentDisplay ||
+            !ctx->mpfn_eglGetCurrentContext) {
+            ALOGE("Failed to load symbols from libEGL");
+            dlclose(ctx->mEglLib);
+            ctx->mEglLib = NULL;
+            return false;
+        }
+        success = true;
+        ALOGI("Successfully Loaded GPUPerfHint APIs");
+    } else {
+        ALOGE("Couldn't load libEGL: %s", dlerror());
+    }
+#endif
+    return success;
+}
+
+};//namespace qhwc
diff --git a/msm8909/libhwcomposer/hwc_utils.h b/msm8909/libhwcomposer/hwc_utils.h
new file mode 100644
index 0000000..235681a
--- /dev/null
+++ b/msm8909/libhwcomposer/hwc_utils.h
@@ -0,0 +1,718 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ * Copyright (C)2012-2015, The Linux Foundation. All rights reserved.
+ *
+ * Not a Contribution, Apache license notifications and license are retained
+ * for attribution purposes only.
+ *
+ * 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 HWC_UTILS_H
+#define HWC_UTILS_H
+
+#define DEBUG_MDPDOWNSCALE 0
+#define HWC_REMOVE_DEPRECATED_VERSIONS 1
+
+#include <fcntl.h>
+#include <math.h>
+#include <hardware/hwcomposer.h>
+#include <gr.h>
+#include <gralloc_priv.h>
+#include <utils/String8.h>
+#include "qdMetaData.h"
+#include "mdp_version.h"
+#include <overlayUtils.h>
+#include <overlayRotator.h>
+#include <EGL/egl.h>
+
+
+#define ALIGN_TO(x, align)     (((x) + ((align)-1)) & ~((align)-1))
+#define LIKELY( exp )       (__builtin_expect( (exp) != 0, true  ))
+#define UNLIKELY( exp )     (__builtin_expect( (exp) != 0, false ))
+#define MAX_NUM_APP_LAYERS 32
+#define MIN_DISPLAY_XRES 200
+#define MIN_DISPLAY_YRES 200
+#define HWC_WFDDISPSYNC_LOG 0
+#define STR(f) #f;
+// Max number of PTOR layers handled
+#define MAX_PTOR_LAYERS 2
+
+#ifdef QTI_BSP
+#include <exhwcomposer_defs.h>
+#endif
+
+//Fwrd decls
+struct hwc_context_t;
+
+namespace ovutils = overlay::utils;
+
+namespace qmode {
+class ModeManager;
+}
+
+namespace overlay {
+class Overlay;
+class Rotator;
+class RotMgr;
+}
+
+namespace qhwc {
+//fwrd decl
+class QueuedBufferStore;
+class HDMIDisplay;
+class VirtualDisplay;
+class IFBUpdate;
+class IVideoOverlay;
+class MDPComp;
+class CopyBit;
+class HwcDebug;
+class AssertiveDisplay;
+class HWCVirtualVDS;
+
+
+struct MDPInfo {
+    int version;
+    char panel;
+    bool hasOverlay;
+};
+
+struct DisplayAttributes {
+    uint32_t refreshRate;
+    uint32_t dynRefreshRate;
+    uint32_t vsync_period; //nanos
+    uint32_t xres;
+    uint32_t yres;
+    uint32_t stride;
+    float xdpi;
+    float ydpi;
+    uint32_t fbformat;
+    int fd;
+    bool connected; //Applies only to pluggable disp.
+    //Connected does not mean it ready to use.
+    //It should be active also. (UNBLANKED)
+    bool isActive;
+    // In pause state, composition is bypassed
+    // used for WFD displays and in QDCM calibration mode
+    bool isPause;
+    // To trigger padding round to clean up mdp
+    // pipes
+    bool isConfiguring;
+    // Indicates whether external/virtual display is in MDP scaling mode
+    bool mMDPScalingMode;
+    // Ext dst Rect
+    hwc_rect_t mDstRect;
+    //Action safe attributes
+    // Flag to indicate the presence of action safe dimensions for external
+    bool mActionSafePresent;
+    int mAsWidthRatio;
+    int mAsHeightRatio;
+
+    //If property fbsize set via adb shell debug.hwc.fbsize = XRESxYRES
+    //following fields are used.
+    bool customFBSize;
+    uint32_t xres_new;
+    uint32_t yres_new;
+
+};
+
+struct ListStats {
+    int numAppLayers; //Total - 1, excluding FB layer.
+    int skipCount;
+    int fbLayerIndex; //Always last for now. = numAppLayers
+    //Video specific
+    int yuvCount;
+    int yuvIndices[MAX_NUM_APP_LAYERS];
+    bool preMultipliedAlpha;
+    int yuv4k2kIndices[MAX_NUM_APP_LAYERS];
+    int yuv4k2kCount;
+    // Notifies hwcomposer about the start and end of animation
+    // This will be set to true during animation, otherwise false.
+    bool isDisplayAnimating;
+    bool secureUI; // Secure display layer
+    bool isSecurePresent;
+    hwc_rect_t lRoi;  //left ROI
+    hwc_rect_t rRoi;  //right ROI. Unused in single DSI panels.
+    //App Buffer Composition index
+    int  renderBufIndexforABC;
+    // Secure RGB specific
+    int secureRGBCount;
+    int secureRGBIndices[MAX_NUM_APP_LAYERS];
+    //dyn refresh rate-Client requested refreshrate
+    uint32_t refreshRateRequest;
+    // Flag related to windowboxing feature
+    bool mAIVVideoMode;
+};
+
+//PTOR Comp info
+struct PtorInfo {
+    int count;
+    int layerIndex[MAX_PTOR_LAYERS];
+    hwc_rect_t displayFrame[MAX_PTOR_LAYERS];
+    bool isActive() { return (count>0); }
+    int getPTORArrayIndex(int index) {
+        int idx = -1;
+        for(int i = 0; i < count; i++) {
+            if(index == layerIndex[i])
+                idx = i;
+        }
+        return idx;
+    }
+};
+
+struct LayerProp {
+    uint32_t mFlags; //qcom specific layer flags
+    LayerProp():mFlags(0){};
+};
+
+struct VsyncState {
+    bool enable;
+    bool fakevsync;
+    bool debug;
+};
+
+struct BwcPM {
+    static void setBwc(const hwc_rect_t& crop, const hwc_rect_t& dst,
+            const int& transform, const int& downscale,
+            ovutils::eMdpFlags& mdpFlags);
+};
+
+// LayerProp::flag values
+enum {
+    HWC_MDPCOMP = 0x00000001,
+    HWC_COPYBIT = 0x00000002,
+};
+
+// AIV specific flags
+enum {
+    HWC_AIV_VIDEO = 0x80000000,
+    HWC_AIV_CC    = 0x40000000,
+};
+
+// HAL specific features
+enum {
+    HWC_COLOR_FILL = 0x00000008,
+    HWC_FORMAT_RB_SWAP = 0x00000040,
+};
+
+/* External Display states */
+enum {
+    EXTERNAL_OFFLINE = 0,
+    EXTERNAL_ONLINE,
+    EXTERNAL_PAUSE,
+    EXTERNAL_RESUME,
+    EXTERNAL_MAXSTATES
+};
+
+class LayerRotMap {
+public:
+    LayerRotMap() { reset(); }
+    void add(hwc_layer_1_t* layer, overlay::Rotator *rot);
+    //Resets the mapping of layer to rotator
+    void reset();
+    //Clears mappings and existing rotator fences
+    //Intended to be used during errors
+    void clear();
+    uint32_t getCount() const;
+    hwc_layer_1_t* getLayer(uint32_t index) const;
+    overlay::Rotator* getRot(uint32_t index) const;
+    bool isRotCached(uint32_t index) const;
+    void setReleaseFd(const int& fence);
+private:
+    hwc_layer_1_t* mLayer[overlay::RotMgr::MAX_ROT_SESS];
+    overlay::Rotator* mRot[overlay::RotMgr::MAX_ROT_SESS];
+    uint32_t mCount;
+};
+
+inline uint32_t LayerRotMap::getCount() const {
+    return mCount;
+}
+
+inline hwc_layer_1_t* LayerRotMap::getLayer(uint32_t index) const {
+    if(index >= mCount) return NULL;
+    return mLayer[index];
+}
+
+inline overlay::Rotator* LayerRotMap::getRot(uint32_t index) const {
+    if(index >= mCount) return NULL;
+    return mRot[index];
+}
+
+inline hwc_rect_t integerizeSourceCrop(const hwc_frect_t& cropF) {
+    hwc_rect_t cropI = {0,0,0,0};
+    cropI.left = int(ceilf(cropF.left));
+    cropI.top = int(ceilf(cropF.top));
+    cropI.right = int(floorf(cropF.right));
+    cropI.bottom = int(floorf(cropF.bottom));
+    return cropI;
+}
+
+inline bool isNonIntegralSourceCrop(const hwc_frect_t& cropF) {
+    if(cropF.left - roundf(cropF.left)     ||
+       cropF.top - roundf(cropF.top)       ||
+       cropF.right - roundf(cropF.right)   ||
+       cropF.bottom - roundf(cropF.bottom))
+        return true;
+    else
+        return false;
+}
+
+// -----------------------------------------------------------------------------
+// Utility functions - implemented in hwc_utils.cpp
+void dumpLayer(hwc_layer_1_t const* l);
+void setListStats(hwc_context_t *ctx, hwc_display_contents_1_t *list,
+        int dpy);
+void initContext(hwc_context_t *ctx);
+void closeContext(hwc_context_t *ctx);
+//Crops source buffer against destination and FB boundaries
+void calculate_crop_rects(hwc_rect_t& crop, hwc_rect_t& dst,
+                         const hwc_rect_t& scissor, int orient);
+void getNonWormholeRegion(hwc_display_contents_1_t* list,
+                              hwc_rect_t& nwr);
+bool isSecuring(hwc_context_t* ctx, hwc_layer_1_t const* layer);
+bool isSecureModePolicy(int mdpVersion);
+// Returns true, if the input layer format is supported by rotator
+bool isRotatorSupportedFormat(private_handle_t *hnd);
+//Returns true, if the layer is YUV or the layer has been rendered by CPU
+bool isRotationDoable(hwc_context_t *ctx, private_handle_t *hnd);
+bool isExternalActive(hwc_context_t* ctx);
+bool isAlphaScaled(hwc_layer_1_t const* layer);
+bool needsScaling(hwc_layer_1_t const* layer);
+bool isDownscaleRequired(hwc_layer_1_t const* layer);
+bool needsScalingWithSplit(hwc_context_t* ctx, hwc_layer_1_t const* layer,
+                           const int& dpy);
+void sanitizeSourceCrop(hwc_rect_t& cropL, hwc_rect_t& cropR,
+                        private_handle_t *hnd);
+bool isAlphaPresent(hwc_layer_1_t const* layer);
+bool isAlphaPresentinFB(hwc_context_t* ctx, int dpy);
+int hwc_vsync_control(hwc_context_t* ctx, int dpy, int enable);
+int getBlending(int blending);
+bool isGLESOnlyComp(hwc_context_t *ctx, const int& dpy);
+void reset_layer_prop(hwc_context_t* ctx, int dpy, int numAppLayers);
+bool isAbcInUse(hwc_context_t *ctx);
+
+void dumpBuffer(private_handle_t *ohnd, char *bufferName);
+void updateDisplayInfo(hwc_context_t* ctx, int dpy);
+void resetDisplayInfo(hwc_context_t* ctx, int dpy);
+void initCompositionResources(hwc_context_t* ctx, int dpy);
+void destroyCompositionResources(hwc_context_t* ctx, int dpy);
+void clearPipeResources(hwc_context_t* ctx, int dpy);
+
+//Helper function to dump logs
+void dumpsys_log(android::String8& buf, const char* fmt, ...);
+
+int getExtOrientation(hwc_context_t* ctx);
+bool isValidRect(const hwc_rect_t& rect);
+hwc_rect_t deductRect(const hwc_rect_t& rect1, const hwc_rect_t& rect2);
+bool isSameRect(const hwc_rect& rect1, const hwc_rect& rect2);
+hwc_rect_t moveRect(const hwc_rect_t& rect, const int& x_off, const int& y_off);
+hwc_rect_t getIntersection(const hwc_rect_t& rect1, const hwc_rect_t& rect2);
+hwc_rect_t getUnion(const hwc_rect_t& rect1, const hwc_rect_t& rect2);
+void optimizeLayerRects(const hwc_display_contents_1_t *list);
+bool areLayersIntersecting(const hwc_layer_1_t* layer1,
+        const hwc_layer_1_t* layer2);
+bool operator ==(const hwc_rect_t& lhs, const hwc_rect_t& rhs);
+bool layerUpdating(const hwc_layer_1_t* layer);
+/* Calculates the dirtyRegion for the given layer */
+hwc_rect_t calculateDirtyRect(const hwc_layer_1_t* layer,
+                                       hwc_rect_t& scissor);
+
+
+// returns true if Action safe dimensions are set and target supports Actionsafe
+bool isActionSafePresent(hwc_context_t *ctx, int dpy);
+
+/* Calculates the destination position based on the action safe rectangle */
+void getActionSafePosition(hwc_context_t *ctx, int dpy, hwc_rect_t& dst);
+
+void getAspectRatioPosition(hwc_context_t* ctx, int dpy, int extOrientation,
+                                hwc_rect_t& inRect, hwc_rect_t& outRect);
+
+uint32_t getRefreshRate(hwc_context_t* ctx, uint32_t requestedRefreshRate);
+
+uint32_t roundOff(uint32_t refreshRate);
+
+void setRefreshRate(hwc_context_t *ctx, int dpy, uint32_t refreshRate);
+
+bool isPrimaryPortrait(hwc_context_t *ctx);
+
+bool isOrientationPortrait(hwc_context_t *ctx);
+
+void calcExtDisplayPosition(hwc_context_t *ctx,
+                               private_handle_t *hnd,
+                               int dpy,
+                               hwc_rect_t& sourceCrop,
+                               hwc_rect_t& displayFrame,
+                               int& transform,
+                               ovutils::eTransform& orient);
+
+// Returns the orientation that needs to be set on external for
+// BufferMirrirMode(Sidesync)
+int getMirrorModeOrientation(hwc_context_t *ctx);
+
+/* Get External State names */
+const char* getExternalDisplayState(uint32_t external_state);
+
+// Resets display ROI to full panel resoluion
+void resetROI(hwc_context_t *ctx, const int dpy);
+
+// Aligns updating ROI to panel restrictions
+hwc_rect_t getSanitizeROI(struct hwc_rect roi, hwc_rect boundary);
+
+// Handles wfd Pause and resume events
+void handle_pause(hwc_context_t *ctx, int dpy);
+void handle_resume(hwc_context_t *ctx, int dpy);
+
+// Handle ONLINE/OFFLINE for HDMI display
+void handle_online(hwc_context_t* ctx, int dpy);
+void handle_offline(hwc_context_t* ctx, int dpy);
+
+//Close acquireFenceFds of all layers of incoming list
+void closeAcquireFds(hwc_display_contents_1_t* list);
+
+//Sync point impl.
+int hwc_sync(hwc_context_t *ctx, hwc_display_contents_1_t* list, int dpy,
+        int fd);
+
+//Sets appropriate mdp flags for a layer.
+void setMdpFlags(hwc_context_t *ctx, hwc_layer_1_t *layer,
+        ovutils::eMdpFlags &mdpFlags,
+        int rotDownscale, int transform);
+
+int configRotator(overlay::Rotator *rot, ovutils::Whf& whf,
+        hwc_rect_t& crop, const ovutils::eMdpFlags& mdpFlags,
+        const ovutils::eTransform& orient, const int& downscale);
+
+int configMdp(overlay::Overlay *ov, const ovutils::PipeArgs& parg,
+        const ovutils::eTransform& orient, const hwc_rect_t& crop,
+        const hwc_rect_t& pos, const MetaData_t *metadata,
+        const ovutils::eDest& dest);
+
+int configColorLayer(hwc_context_t *ctx, hwc_layer_1_t *layer, const int& dpy,
+        ovutils::eMdpFlags& mdpFlags, ovutils::eZorder& z,
+        const ovutils::eDest& dest);
+
+void updateSource(ovutils::eTransform& orient, ovutils::Whf& whf,
+        hwc_rect_t& crop, overlay::Rotator *rot);
+
+bool isZoomModeEnabled(hwc_rect_t crop);
+void updateCropAIVVideoMode(hwc_context_t *ctx, hwc_rect_t& crop, int dpy);
+void updateDestAIVVideoMode(hwc_context_t *ctx, hwc_rect_t& dst, int dpy);
+void updateCoordinates(hwc_context_t *ctx, hwc_rect_t& crop,
+                           hwc_rect_t& dst, int dpy);
+
+//Routine to configure low resolution panels (<= 2048 width)
+int configureNonSplit(hwc_context_t *ctx, hwc_layer_1_t *layer, const int& dpy,
+        ovutils::eMdpFlags& mdpFlags, ovutils::eZorder& z,
+        const ovutils::eDest& dest,
+        overlay::Rotator **rot);
+
+//Routine to configure high resolution panels (> 2048 width)
+int configureSplit(hwc_context_t *ctx, hwc_layer_1_t *layer, const int& dpy,
+        ovutils::eMdpFlags& mdpFlags, ovutils::eZorder& z,
+        const ovutils::eDest& lDest,
+        const ovutils::eDest& rDest, overlay::Rotator **rot);
+
+//Routine to split and configure high resolution YUV layer (> 2048 width)
+int configureSourceSplit(hwc_context_t *ctx, hwc_layer_1_t *layer,
+        const int& dpy,
+        ovutils::eMdpFlags& mdpFlags, ovutils::eZorder& z,
+        const ovutils::eDest& lDest,
+        const ovutils::eDest& rDest, overlay::Rotator **rot);
+
+//On certain targets DMA pipes are used for rotation and they won't be available
+//for line operations. On a per-target basis we can restrict certain use cases
+//from using rotator, since we know before-hand that such scenarios can lead to
+//extreme unavailability of pipes. This can also be done via hybrid calculations
+//also involving many more variables like number of write-back interfaces etc,
+//but the variety of scenarios is too high to warrant that.
+bool canUseRotator(hwc_context_t *ctx, int dpy);
+
+int getLeftSplit(hwc_context_t *ctx, const int& dpy);
+
+bool isDisplaySplit(hwc_context_t* ctx, int dpy);
+
+int getRotDownscale(hwc_context_t *ctx, const hwc_layer_1_t *layer);
+
+// Set the GPU hint flag to high for MIXED/GPU composition only for
+// first frame after MDP to GPU/MIXED mode transition.
+// Set the GPU hint to default if the current composition type is GPU
+// due to idle fallback or MDP composition.
+void setGPUHint(hwc_context_t* ctx, hwc_display_contents_1_t* list);
+
+bool loadEglLib(hwc_context_t* ctx);
+
+// Returns true if rect1 is peripheral to rect2, false otherwise.
+bool isPeripheral(const hwc_rect_t& rect1, const hwc_rect_t& rect2);
+
+// Checks if boot animation has completed and applies default mode
+void processBootAnimCompleted(hwc_context_t *ctx);
+
+// Inline utility functions
+static inline bool isSkipLayer(const hwc_layer_1_t* l) {
+    return (UNLIKELY(l && (l->flags & HWC_SKIP_LAYER)));
+}
+
+static inline bool isAIVVideoLayer(const hwc_layer_1_t* l) {
+    return (UNLIKELY(l && (l->flags & HWC_AIV_VIDEO)));
+}
+
+static inline bool isAIVCCLayer(const hwc_layer_1_t* l) {
+    return (UNLIKELY(l && (l->flags & HWC_AIV_CC)));
+}
+
+// Returns true if the buffer is yuv
+static inline bool isYuvBuffer(const private_handle_t* hnd) {
+    return (hnd && (hnd->bufferType == BUFFER_TYPE_VIDEO));
+}
+
+// Returns true if the buffer is yuv and exceeds the mixer width
+static inline bool isYUVSplitNeeded(const private_handle_t* hnd) {
+    int maxMixerWidth = qdutils::MDPVersion::getInstance().getMaxMixerWidth();
+    return (hnd && (hnd->bufferType == BUFFER_TYPE_VIDEO) &&
+            (hnd->width > maxMixerWidth));
+}
+
+// Returns true if the buffer is secure
+static inline bool isSecureBuffer(const private_handle_t* hnd) {
+    return (hnd && (private_handle_t::PRIV_FLAGS_SECURE_BUFFER & hnd->flags));
+}
+
+static inline bool isTileRendered(const private_handle_t* hnd) {
+    return (hnd && (private_handle_t::PRIV_FLAGS_TILE_RENDERED & hnd->flags));
+}
+
+static inline bool isCPURendered(const private_handle_t* hnd) {
+    return (hnd && (private_handle_t::PRIV_FLAGS_CPU_RENDERED & hnd->flags));
+}
+
+//Return true if the buffer is intended for Secure Display
+static inline bool isSecureDisplayBuffer(const private_handle_t* hnd) {
+    return (hnd && (hnd->flags & private_handle_t::PRIV_FLAGS_SECURE_DISPLAY));
+}
+
+static inline int getWidth(const private_handle_t* hnd) {
+    MetaData_t *metadata = reinterpret_cast<MetaData_t*>(hnd->base_metadata);
+    if(metadata && metadata->operation & UPDATE_BUFFER_GEOMETRY) {
+        return metadata->bufferDim.sliceWidth;
+    }
+    return hnd->width;
+}
+
+static inline int getHeight(const private_handle_t* hnd) {
+    MetaData_t *metadata = reinterpret_cast<MetaData_t*>(hnd->base_metadata);
+    if(metadata && metadata->operation & UPDATE_BUFFER_GEOMETRY) {
+        return metadata->bufferDim.sliceHeight;
+    }
+    return hnd->height;
+}
+
+template<typename T> inline T max(T a, T b) { return (a > b) ? a : b; }
+template<typename T> inline T min(T a, T b) { return (a < b) ? a : b; }
+
+// Initialize uevent thread
+void init_uevent_thread(hwc_context_t* ctx);
+// Initialize vsync thread
+void init_vsync_thread(hwc_context_t* ctx);
+
+inline void getLayerResolution(const hwc_layer_1_t* layer,
+                               int& width, int& height) {
+    hwc_rect_t displayFrame  = layer->displayFrame;
+    width = displayFrame.right - displayFrame.left;
+    height = displayFrame.bottom - displayFrame.top;
+}
+
+static inline int openFb(int dpy) {
+    int fd = -1;
+    const char *devtmpl = "/dev/graphics/fb%u";
+    char name[64] = {0};
+    snprintf(name, 64, devtmpl, dpy);
+    fd = open(name, O_RDWR);
+    return fd;
+}
+
+template <class T>
+inline void swap(T& a, T& b) {
+    T tmp = a;
+    a = b;
+    b = tmp;
+}
+
+}; //qhwc namespace
+
+enum eAnimationState{
+    ANIMATION_STOPPED,
+    ANIMATION_STARTED,
+};
+
+enum eCompositionState {
+    COMPOSITION_STATE_MDP = 0,        // Set if composition type is MDP
+    COMPOSITION_STATE_GPU,            // Set if composition type is GPU or MIXED
+    COMPOSITION_STATE_IDLE_FALLBACK,  // Set if it is idlefallback
+};
+
+// Structure holds the information about the GPU hint.
+struct gpu_hint_info {
+    // system level flag to enable gpu_perf_mode
+    bool mGpuPerfModeEnable;
+    // Stores the current GPU performance mode DEFAULT/HIGH
+    bool mCurrGPUPerfMode;
+    // Stores the compositon state GPU, MDP or IDLE_FALLBACK
+    bool mCompositionState;
+    // Stores the EGLContext of current process
+    EGLContext mEGLContext;
+    // Stores the EGLDisplay of current process
+    EGLDisplay mEGLDisplay;
+};
+
+//struct holds the information about libmm-qdcm.so
+struct qdcm_info {
+    qmode::ModeManager *mQdcmMode;
+    void *mQdcmLib;
+    bool  mBootAnimCompleted;
+};
+
+// -----------------------------------------------------------------------------
+// HWC context
+// This structure contains overall state
+struct hwc_context_t {
+    hwc_composer_device_1_t device;
+    const hwc_procs_t* proc;
+
+    //CopyBit objects
+    qhwc::CopyBit *mCopyBit[HWC_NUM_DISPLAY_TYPES];
+
+    //Overlay object - NULL for non overlay devices
+    overlay::Overlay *mOverlay;
+    //Holds a few rot objects
+    overlay::RotMgr *mRotMgr;
+
+    //Primary and external FB updater
+    qhwc::IFBUpdate *mFBUpdate[HWC_NUM_DISPLAY_TYPES];
+    // HDMI display related object. Used to configure/teardown
+    // HDMI when it is connected as primary or external.
+    qhwc::HDMIDisplay *mHDMIDisplay;
+    qhwc::MDPInfo mMDP;
+    qhwc::VsyncState vstate;
+    qhwc::DisplayAttributes dpyAttr[HWC_NUM_DISPLAY_TYPES];
+    qhwc::ListStats listStats[HWC_NUM_DISPLAY_TYPES];
+    qhwc::LayerProp *layerProp[HWC_NUM_DISPLAY_TYPES];
+    qhwc::MDPComp *mMDPComp[HWC_NUM_DISPLAY_TYPES];
+    qhwc::HwcDebug *mHwcDebug[HWC_NUM_DISPLAY_TYPES];
+    hwc_rect_t mViewFrame[HWC_NUM_DISPLAY_TYPES];
+    qhwc::AssertiveDisplay *mAD;
+    eAnimationState mAnimationState[HWC_NUM_DISPLAY_TYPES];
+    qhwc::HWCVirtualVDS *mHWCVirtual;
+
+    // stores the #numHwLayers of the previous frame
+    // for each display device
+    int mPrevHwLayerCount[HWC_NUM_DISPLAY_TYPES];
+
+    // stores the primary device orientation
+    int deviceOrientation;
+    //Securing in progress indicator
+    bool mSecuring;
+    //Display in secure mode indicator
+    bool mSecureMode;
+    //Lock to protect drawing data structures
+    mutable Locker mDrawLock;
+    //Drawing round when we use GPU
+    bool isPaddingRound;
+    // External Orientation
+    int mExtOrientation;
+    //Flags the transition of a video session
+    bool mVideoTransFlag;
+    //Used for SideSync feature
+    //which overrides the mExtOrientation
+    bool mBufferMirrorMode;
+    // Used to synchronize between WFD and Display modules
+    mutable Locker mWfdSyncLock;
+
+    qhwc::LayerRotMap *mLayerRotMap[HWC_NUM_DISPLAY_TYPES];
+    // Panel reset flag will be set if BTA check fails
+    bool mPanelResetStatus;
+    // number of active Displays
+    int numActiveDisplays;
+#ifdef QTI_BSP
+    void *mEglLib;
+    EGLBoolean (*mpfn_eglGpuPerfHintQCOM)(EGLDisplay, EGLContext, EGLint *);
+    EGLDisplay (*mpfn_eglGetCurrentDisplay)();
+    EGLContext (*mpfn_eglGetCurrentContext)();
+    struct gpu_hint_info mGPUHintInfo;
+#endif
+    //App Buffer Composition
+    bool enableABC;
+    // PTOR Info
+    qhwc::PtorInfo mPtorInfo;
+    //Running in Thermal burst mode
+    bool mThermalBurstMode;
+    //Layers out of ROI
+    bool copybitDrop[MAX_NUM_APP_LAYERS];
+    // Flag related to windowboxing feature
+    bool mWindowboxFeature;
+    // This denotes the tolerance between video layer and external display
+    // aspect ratio
+    float mAspectRatioToleranceLevel;
+    //Used to notify that boot has completed
+    bool mBootAnimCompleted;
+    // Provides a way for OEM's to disable setting dynfps via metadata.
+    bool mUseMetaDataRefreshRate;
+    //struct holds the information about display tuning service library.
+    struct qdcm_info mQdcmInfo;
+};
+
+namespace qhwc {
+static inline bool isSkipPresent (hwc_context_t *ctx, int dpy) {
+    return  ctx->listStats[dpy].skipCount;
+}
+
+static inline bool isYuvPresent (hwc_context_t *ctx, int dpy) {
+    return  ctx->listStats[dpy].yuvCount;
+}
+
+static inline bool has90Transform(hwc_layer_1_t const* layer) {
+    return ((layer->transform & HWC_TRANSFORM_ROT_90) &&
+            !(layer->flags & HWC_COLOR_FILL));
+}
+
+inline bool isSecurePresent(hwc_context_t *ctx, int dpy) {
+    return ctx->listStats[dpy].isSecurePresent;
+}
+
+static inline bool isSecondaryConfiguring(hwc_context_t* ctx) {
+    return (ctx->dpyAttr[HWC_DISPLAY_EXTERNAL].isConfiguring ||
+            ctx->dpyAttr[HWC_DISPLAY_VIRTUAL].isConfiguring);
+}
+
+static inline bool isSecondaryConnected(hwc_context_t* ctx) {
+    return (ctx->dpyAttr[HWC_DISPLAY_EXTERNAL].connected ||
+            ctx->dpyAttr[HWC_DISPLAY_VIRTUAL].connected);
+}
+
+static inline bool isSecondaryAnimating(hwc_context_t* ctx) {
+    return (ctx->dpyAttr[HWC_DISPLAY_EXTERNAL].connected &&
+            (!ctx->dpyAttr[HWC_DISPLAY_EXTERNAL].isPause) &&
+            ctx->listStats[HWC_DISPLAY_EXTERNAL].isDisplayAnimating)
+            ||
+           (ctx->dpyAttr[HWC_DISPLAY_VIRTUAL].connected &&
+            (!ctx->dpyAttr[HWC_DISPLAY_VIRTUAL].isPause) &&
+            ctx->listStats[HWC_DISPLAY_VIRTUAL].isDisplayAnimating);
+}
+
+/* Return Virtual Display connection status */
+static inline bool isVDConnected(hwc_context_t* ctx) {
+    return ctx->dpyAttr[HWC_DISPLAY_VIRTUAL].connected;
+}
+
+};
+
+#endif //HWC_UTILS_H
diff --git a/msm8909/libhwcomposer/hwc_virtual.cpp b/msm8909/libhwcomposer/hwc_virtual.cpp
new file mode 100644
index 0000000..2bfb5e7
--- /dev/null
+++ b/msm8909/libhwcomposer/hwc_virtual.cpp
@@ -0,0 +1,236 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ * Copyright (C) 2012-2014, The Linux Foundation. All rights reserved.
+ *
+ * Not a Contribution, Apache license notifications and license are retained
+ * for attribution purposes only.
+ *
+ * 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 <fcntl.h>
+#include <errno.h>
+
+#include <cutils/log.h>
+#include <overlayWriteback.h>
+#include "hwc_utils.h"
+#include "hwc_fbupdate.h"
+#include "hwc_mdpcomp.h"
+#include "hwc_dump_layers.h"
+#include "hwc_copybit.h"
+#include "hwc_virtual.h"
+#include "sync/sync.h"
+#include <utils/Trace.h>
+
+#define HWCVIRTUAL_LOG 0
+
+using namespace qhwc;
+using namespace overlay;
+
+bool HWCVirtualVDS::sVDDumpEnabled = false;
+
+void HWCVirtualVDS::init(hwc_context_t *ctx) {
+    const int dpy = HWC_DISPLAY_VIRTUAL;
+    mScalingWidth = 0, mScalingHeight = 0;
+    initCompositionResources(ctx, dpy);
+
+    if(ctx->mFBUpdate[dpy])
+        ctx->mFBUpdate[dpy]->reset();
+    if(ctx->mMDPComp[dpy])
+        ctx->mMDPComp[dpy]->reset();
+}
+
+void HWCVirtualVDS::destroy(hwc_context_t *ctx, size_t /*numDisplays*/,
+                       hwc_display_contents_1_t** displays) {
+    int dpy = HWC_DISPLAY_VIRTUAL;
+
+    //Cleanup virtual display objs, since there is no explicit disconnect
+    if(ctx->dpyAttr[dpy].connected && (displays[dpy] == NULL)) {
+        ctx->dpyAttr[dpy].connected = false;
+        ctx->dpyAttr[dpy].isPause = false;
+
+        destroyCompositionResources(ctx, dpy);
+
+        // signal synclock to indicate successful wfd teardown
+        ctx->mWfdSyncLock.lock();
+        ctx->mWfdSyncLock.signal();
+        ctx->mWfdSyncLock.unlock();
+    }
+}
+
+int HWCVirtualVDS::prepare(hwc_composer_device_1 *dev,
+        hwc_display_contents_1_t *list) {
+    ATRACE_CALL();
+    //XXX: Fix when framework support is added
+    hwc_context_t* ctx = (hwc_context_t*)(dev);
+    const int dpy = HWC_DISPLAY_VIRTUAL;
+
+    if (list && list->outbuf && list->numHwLayers > 0) {
+        reset_layer_prop(ctx, dpy, (int)list->numHwLayers - 1);
+        uint32_t last = (uint32_t)list->numHwLayers - 1;
+        hwc_layer_1_t *fbLayer = &list->hwLayers[last];
+        int fbWidth = 0, fbHeight = 0;
+        getLayerResolution(fbLayer, fbWidth, fbHeight);
+        ctx->dpyAttr[dpy].xres = fbWidth;
+        ctx->dpyAttr[dpy].yres = fbHeight;
+
+        if(ctx->dpyAttr[dpy].connected == false) {
+            ctx->dpyAttr[dpy].connected = true;
+            ctx->dpyAttr[dpy].isPause = false;
+            // We set the vsync period to the primary refresh rate, leaving
+            // it up to the consumer to decide how fast to consume frames.
+            ctx->dpyAttr[dpy].vsync_period
+                              = ctx->dpyAttr[HWC_DISPLAY_PRIMARY].vsync_period;
+            ctx->dpyAttr[dpy].fbformat = HAL_PIXEL_FORMAT_RGBA_8888;
+            init(ctx);
+            // Do one padding round for cases where primary has all pipes
+            // The virtual composition falls back to GPU in such cases.
+            ctx->isPaddingRound = true;
+        }
+        if(!ctx->dpyAttr[dpy].isPause) {
+            ctx->dpyAttr[dpy].isConfiguring = false;
+            ctx->dpyAttr[dpy].fd = Writeback::getInstance()->getFbFd();
+            private_handle_t *ohnd = (private_handle_t *)list->outbuf;
+
+            setMDPScalingMode(ctx, ohnd, dpy);
+
+            mScalingWidth = getWidth(ohnd);
+            mScalingHeight = getHeight(ohnd);
+
+            Writeback::getInstance()->configureDpyInfo(mScalingWidth,
+                                                        mScalingHeight);
+            setListStats(ctx, list, dpy);
+
+            if(ctx->mMDPComp[dpy]->prepare(ctx, list) < 0) {
+                const int fbZ = 0;
+                if(not ctx->mFBUpdate[dpy]->prepareAndValidate(ctx, list, fbZ))
+                {
+                    ctx->mOverlay->clear(dpy);
+                    ctx->mLayerRotMap[dpy]->clear();
+                }
+            }
+        } else {
+            /* Virtual Display is in Pause state.
+             * Mark all application layers as OVERLAY so that
+             * GPU will not compose.
+             */
+            Writeback::getInstance(); //Ensure that WB is active during pause
+            for(size_t i = 0 ;i < (size_t)(list->numHwLayers - 1); i++) {
+                hwc_layer_1_t *layer = &list->hwLayers[i];
+                layer->compositionType = HWC_OVERLAY;
+            }
+        }
+    }
+    return 0;
+}
+
+int HWCVirtualVDS::set(hwc_context_t *ctx, hwc_display_contents_1_t *list) {
+    ATRACE_CALL();
+    int ret = 0;
+    const int dpy = HWC_DISPLAY_VIRTUAL;
+
+    if (list && list->outbuf && list->numHwLayers > 0) {
+        uint32_t last = (uint32_t)list->numHwLayers - 1;
+        hwc_layer_1_t *fbLayer = &list->hwLayers[last];
+
+        if(ctx->dpyAttr[dpy].connected
+                && (!ctx->dpyAttr[dpy].isPause))
+        {
+            private_handle_t *ohnd = (private_handle_t *)list->outbuf;
+            int format = ohnd->format;
+            if (format == HAL_PIXEL_FORMAT_RGBA_8888)
+                format = HAL_PIXEL_FORMAT_RGBX_8888;
+            Writeback::getInstance()->setOutputFormat(
+                                    utils::getMdpFormat(format));
+
+            // Configure WB secure mode based on output buffer handle
+            if(! Writeback::getInstance()->setSecure(isSecureBuffer(ohnd)))
+            {
+                ALOGE("Failed to set WB secure mode: %d for virtual display",
+                    isSecureBuffer(ohnd));
+                return false;
+            }
+
+            int fd = -1; //FenceFD from the Copybit
+            hwc_sync(ctx, list, dpy, fd);
+
+            // Dump the layers for virtual
+            if(ctx->mHwcDebug[dpy])
+                ctx->mHwcDebug[dpy]->dumpLayers(list);
+
+            if (!ctx->mMDPComp[dpy]->draw(ctx, list)) {
+                ALOGE("%s: MDPComp draw failed", __FUNCTION__);
+                ret = -1;
+            }
+            // We need an FB layer handle check to cater for this usecase:
+            // Video is playing in landscape on primary, then launch
+            // ScreenRecord app.
+            // In this scenario, the first VDS draw call will have HWC
+            // composition and VDS does nit involve GPU to get eglSwapBuffer
+            // to get valid fb handle.
+            if (fbLayer->handle && !ctx->mFBUpdate[dpy]->draw(ctx,
+                        (private_handle_t *)fbLayer->handle)) {
+                ALOGE("%s: FBUpdate::draw fail!", __FUNCTION__);
+                ret = -1;
+            }
+
+            Writeback::getInstance()->queueBuffer(ohnd->fd,
+                                        (uint32_t)ohnd->offset);
+            if(!Overlay::displayCommit(ctx->dpyAttr[dpy].fd)) {
+                ALOGE("%s: display commit fail!", __FUNCTION__);
+                ret = -1;
+            }
+
+            if(sVDDumpEnabled) {
+                char bufferName[128];
+                // Dumping frame buffer
+                sync_wait(fbLayer->acquireFenceFd, 1000);
+                snprintf(bufferName, sizeof(bufferName), "vds.fb");
+                dumpBuffer((private_handle_t *)fbLayer->handle, bufferName);
+                // Dumping WB output for non-secure session
+                if(!isSecureBuffer(ohnd)) {
+                    sync_wait(list->retireFenceFd, 1000);
+                    snprintf(bufferName, sizeof(bufferName), "vds.wb");
+                    dumpBuffer(ohnd, bufferName);
+                }
+            }
+        } else if(list->outbufAcquireFenceFd >= 0) {
+            //If we dont handle the frame, set retireFenceFd to outbufFenceFd,
+            //which will make sure, the framework waits on it and closes it.
+            //The other way is to wait on outbufFenceFd ourselves, close it and
+            //set retireFenceFd to -1. Since we want hwc to be async, choosing
+            //the former.
+            //Also dup because, the closeAcquireFds() will close the outbufFence
+            list->retireFenceFd = dup(list->outbufAcquireFenceFd);
+        }
+    }
+
+    closeAcquireFds(list);
+    return ret;
+}
+
+/* We set scaling mode on the VD if the output handle width and height
+   differs from the virtual frame buffer width and height. */
+void HWCVirtualVDS::setMDPScalingMode(hwc_context_t* ctx,
+        private_handle_t* ohnd, int dpy) {
+    bool scalingMode = false;
+    int fbWidth = ctx->dpyAttr[dpy].xres;
+    int fbHeight =  ctx->dpyAttr[dpy].yres;
+    if((getWidth(ohnd) != fbWidth) || (getHeight(ohnd) != fbHeight)) {
+        scalingMode = true;
+    }
+    ctx->dpyAttr[dpy].mMDPScalingMode = scalingMode;
+
+    ALOGD_IF(HWCVIRTUAL_LOG, "%s fb(%dx%d) outputBuffer(%dx%d) scalingMode=%d",
+            __FUNCTION__, fbWidth, fbHeight,
+            getWidth(ohnd), getHeight(ohnd), scalingMode);
+}
diff --git a/msm8909/libhwcomposer/hwc_virtual.h b/msm8909/libhwcomposer/hwc_virtual.h
new file mode 100644
index 0000000..bd1833c
--- /dev/null
+++ b/msm8909/libhwcomposer/hwc_virtual.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ * Copyright (C) 2012-2014, The Linux Foundation. All rights reserved.
+ *
+ * Not a Contribution, Apache license notifications and license are retained
+ * for attribution purposes only.
+ *
+ * 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 HWC_VIRTUAL
+#define HWC_VIRTUAL
+
+#include <hwc_utils.h>
+
+namespace qhwc {
+
+class HWCVirtualVDS {
+public:
+    HWCVirtualVDS(){};
+    ~HWCVirtualVDS(){};
+    // Chooses composition type and configures pipe for each layer in virtual
+    // display list
+    int prepare(hwc_composer_device_1 *dev,
+                          hwc_display_contents_1_t* list);
+    // Queues the buffer for each layer in virtual display list and call display
+    // commit.
+    int set(hwc_context_t *ctx, hwc_display_contents_1_t *list);
+    // instantiates mdpcomp, copybit and fbupdate objects and initialize those
+    // objects for virtual display during virtual display connect.
+    void init(hwc_context_t *ctx);
+    // Destroys mdpcomp, copybit and fbupdate objects and for virtual display
+    // during virtual display disconnect.
+    void destroy(hwc_context_t *ctx, size_t numDisplays,
+                       hwc_display_contents_1_t** displays);
+    int getScalingHeight() const { return mScalingHeight; };
+    int getScalingWidth() const { return mScalingWidth; };
+    // We can dump the frame buffer and WB
+    // output buffer by dynamically enabling
+    // dumping via a binder call:
+    // adb shell service call display.qservice 15 i32 3 i32 1
+    static bool sVDDumpEnabled;
+    static void dynamicDebug(bool enable) {sVDDumpEnabled = enable;};
+
+private:
+    // These variables store the resolution that WB is being configured to
+    // in the current draw cycle.
+    int mScalingWidth, mScalingHeight;
+    void setMDPScalingMode(hwc_context_t* ctx,
+            private_handle_t* ohnd, int dpy);
+};
+
+}; //namespace
+#endif
diff --git a/msm8909/libhwcomposer/hwc_vsync.cpp b/msm8909/libhwcomposer/hwc_vsync.cpp
new file mode 100644
index 0000000..b876e0f
--- /dev/null
+++ b/msm8909/libhwcomposer/hwc_vsync.cpp
@@ -0,0 +1,236 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ * Copyright (C) 2012-2014, The Linux Foundation. All rights reserved.
+ *
+ * Not a Contribution, Apache license notifications and license are
+ * retained for attribution purposes only.
+
+ * 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/properties.h>
+#include <utils/Log.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <linux/msm_mdp.h>
+#include <sys/resource.h>
+#include <sys/prctl.h>
+#include <poll.h>
+#include "hwc_utils.h"
+#include "hdmi.h"
+#include "qd_utils.h"
+#include "string.h"
+#include "overlay.h"
+#define __STDC_FORMAT_MACROS 1
+#include <inttypes.h>
+
+using namespace qdutils;
+namespace qhwc {
+
+#define HWC_VSYNC_THREAD_NAME "hwcVsyncThread"
+#define PANEL_ON_STR "panel_power_on ="
+#define ARRAY_LENGTH(array) (sizeof((array))/sizeof((array)[0]))
+#define MAX_THERMAL_LEVEL 3
+const int MAX_DATA = 64;
+
+int hwc_vsync_control(hwc_context_t* ctx, int dpy, int enable)
+{
+    int ret = 0;
+    if(!ctx->vstate.fakevsync &&
+       ioctl(ctx->dpyAttr[dpy].fd, MSMFB_OVERLAY_VSYNC_CTRL,
+             &enable) < 0) {
+        ALOGE("%s: vsync control failed. Dpy=%d, enable=%d : %s",
+              __FUNCTION__, dpy, enable, strerror(errno));
+        ret = -errno;
+    }
+    return ret;
+}
+
+static void handle_vsync_event(hwc_context_t* ctx, int dpy, char *data)
+{
+    // extract timestamp
+    uint64_t timestamp = 0;
+    if (!strncmp(data, "VSYNC=", strlen("VSYNC="))) {
+        timestamp = strtoull(data + strlen("VSYNC="), NULL, 0);
+    }
+    // send timestamp to SurfaceFlinger
+    ALOGD_IF (ctx->vstate.debug, "%s: timestamp %" PRIu64 " sent to SF for dpy=%d",
+            __FUNCTION__, timestamp, dpy);
+    ctx->proc->vsync(ctx->proc, dpy, timestamp);
+}
+
+static void handle_blank_event(hwc_context_t* ctx, int dpy, char *data)
+{
+    if (!strncmp(data, PANEL_ON_STR, strlen(PANEL_ON_STR))) {
+        unsigned long int poweron = strtoul(data + strlen(PANEL_ON_STR), NULL, 0);
+        ALOGI("%s: dpy:%d panel power state: %ld", __FUNCTION__, dpy, poweron);
+        if (!ctx->mHDMIDisplay->isHDMIPrimaryDisplay()) {
+            ctx->dpyAttr[dpy].isActive = poweron ? true: false;
+        }
+    }
+}
+
+static void handle_thermal_event(hwc_context_t* ctx, int dpy, char *data)
+{
+    // extract thermal level
+    uint64_t thermalLevel = 0;
+    if (!strncmp(data, "thermal_level=", strlen("thermal_level="))) {
+        thermalLevel = strtoull(data + strlen("thermal_level="), NULL, 0);
+    }
+
+    if (thermalLevel >= MAX_THERMAL_LEVEL) {
+        ALOGD("%s: dpy:%d thermal_level=%" PRIu64 "",__FUNCTION__,dpy,thermalLevel);
+        ctx->mThermalBurstMode = true;
+    } else
+        ctx->mThermalBurstMode = false;
+}
+
+struct event {
+    const char* name;
+    void (*callback)(hwc_context_t* ctx, int dpy, char *data);
+};
+
+struct event event_list[] =  {
+    { "vsync_event", handle_vsync_event },
+    { "show_blank_event", handle_blank_event },
+    { "msm_fb_thermal_level", handle_thermal_event },
+};
+
+#define num_events ARRAY_LENGTH(event_list)
+
+static void *vsync_loop(void *param)
+{
+    hwc_context_t * ctx = reinterpret_cast<hwc_context_t *>(param);
+
+    char thread_name[64] = HWC_VSYNC_THREAD_NAME;
+    prctl(PR_SET_NAME, (unsigned long) &thread_name, 0, 0, 0);
+    setpriority(PRIO_PROCESS, 0, HAL_PRIORITY_URGENT_DISPLAY +
+                android::PRIORITY_MORE_FAVORABLE);
+
+    char vdata[MAX_DATA];
+    //Number of physical displays
+    //We poll on all the nodes.
+    int num_displays = HWC_NUM_DISPLAY_TYPES - 1;
+    struct pollfd pfd[num_displays][num_events];
+
+    char property[PROPERTY_VALUE_MAX];
+    if(property_get("debug.hwc.fakevsync", property, NULL) > 0) {
+        if(atoi(property) == 1)
+            ctx->vstate.fakevsync = true;
+    }
+
+    char node_path[MAX_SYSFS_FILE_PATH];
+
+    for (int dpy = HWC_DISPLAY_PRIMARY; dpy < num_displays; dpy++) {
+        for(size_t ev = 0; ev < num_events; ev++) {
+            snprintf(node_path, sizeof(node_path),
+                    "/sys/class/graphics/fb%d/%s",
+                    dpy == HWC_DISPLAY_PRIMARY ? 0 :
+                    overlay::Overlay::getInstance()->
+                    getFbForDpy(HWC_DISPLAY_EXTERNAL),
+                    event_list[ev].name);
+
+            ALOGI("%s: Reading event %zu for dpy %d from %s", __FUNCTION__,
+                    ev, dpy, node_path);
+            pfd[dpy][ev].fd = open(node_path, O_RDONLY);
+
+            if (dpy == HWC_DISPLAY_PRIMARY && pfd[dpy][ev].fd < 0) {
+                // Make sure fb device is opened before starting
+                // this thread so this never happens.
+                ALOGE ("%s:unable to open event node for dpy=%d event=%zu, %s",
+                        __FUNCTION__, dpy, ev, strerror(errno));
+                if (ev == 0) {
+                    ctx->vstate.fakevsync = true;
+                    //XXX: Blank events don't work with fake vsync,
+                    //but we shouldn't be running on fake vsync anyway.
+                    break;
+                }
+            }
+
+            memset(&vdata, '\0', sizeof(vdata));
+            // Read once from the fds to clear the first notify
+            pread(pfd[dpy][ev].fd, vdata , MAX_DATA - 1, 0);
+            if (pfd[dpy][ev].fd >= 0)
+                pfd[dpy][ev].events = POLLPRI | POLLERR;
+        }
+    }
+
+    if (LIKELY(!ctx->vstate.fakevsync)) {
+        do {
+            int err = poll(*pfd, (int)(num_displays * num_events), -1);
+            if(err > 0) {
+                for (int dpy = HWC_DISPLAY_PRIMARY; dpy < num_displays; dpy++) {
+                    for(size_t ev = 0; ev < num_events; ev++) {
+                        if (pfd[dpy][ev].revents & POLLPRI) {
+                            // Clear vdata before writing into it
+                            memset(&vdata, '\0', sizeof(vdata));
+                            ssize_t len = pread(pfd[dpy][ev].fd, vdata,
+                                                MAX_DATA - 1, 0);
+                            if (UNLIKELY(len < 0)) {
+                                // If the read was just interrupted - it is not
+                                // a fatal error. Just continue in this case
+                                ALOGE ("%s: Unable to read event:%zu for \
+                                        dpy=%d : %s",
+                                        __FUNCTION__, ev, dpy, strerror(errno));
+                                continue;
+                            }
+                            vdata[len] = '\0';
+                            event_list[ev].callback(ctx, dpy, vdata);
+                        }
+                    }
+                }
+            } else {
+                ALOGE("%s: poll failed errno: %s", __FUNCTION__,
+                        strerror(errno));
+                continue;
+            }
+        } while (true);
+
+    } else {
+
+        //Fake vsync is used only when set explicitly through a property or when
+        //the vsync timestamp node cannot be opened at bootup. There is no
+        //fallback to fake vsync from the true vsync loop, ever, as the
+        //condition can easily escape detection.
+        //Also, fake vsync is delivered only for the primary display.
+        do {
+            usleep(16666);
+            uint64_t timestamp = systemTime();
+            ctx->proc->vsync(ctx->proc, HWC_DISPLAY_PRIMARY, timestamp);
+
+        } while (true);
+    }
+
+    for (int dpy = HWC_DISPLAY_PRIMARY; dpy <= HWC_DISPLAY_EXTERNAL; dpy++ ) {
+        for( size_t event = 0; event < num_events; event++) {
+            if(pfd[dpy][event].fd >= 0)
+                close (pfd[dpy][event].fd);
+        }
+    }
+
+    return NULL;
+}
+
+void init_vsync_thread(hwc_context_t* ctx)
+{
+    int ret;
+    pthread_t vsync_thread;
+    ALOGI("Initializing VSYNC Thread");
+    ret = pthread_create(&vsync_thread, NULL, vsync_loop, (void*) ctx);
+    if (ret) {
+        ALOGE("%s: failed to create %s: %s", __FUNCTION__,
+              HWC_VSYNC_THREAD_NAME, strerror(ret));
+    }
+}
+
+}; //namespace
diff --git a/msm8909/liblight/Android.mk b/msm8909/liblight/Android.mk
new file mode 100644
index 0000000..977fc55
--- /dev/null
+++ b/msm8909/liblight/Android.mk
@@ -0,0 +1,27 @@
+# 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 stored in
+# hw/<COPYPIX_HARDWARE_MODULE_ID>.<ro.board.platform>.so
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := lights.c
+LOCAL_MODULE_RELATIVE_PATH := hw
+LOCAL_SHARED_LIBRARIES := liblog
+LOCAL_CFLAGS := $(common_flags) -DLOG_TAG=\"qdlights\"
+LOCAL_MODULE := lights.$(TARGET_BOARD_PLATFORM)
+LOCAL_MODULE_TAGS := optional
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/msm8909/liblight/NOTICE b/msm8909/liblight/NOTICE
new file mode 100644
index 0000000..7340b9e
--- /dev/null
+++ b/msm8909/liblight/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/msm8909/liblight/lights.c b/msm8909/liblight/lights.c
new file mode 100644
index 0000000..cf24d50
--- /dev/null
+++ b/msm8909/liblight/lights.c
@@ -0,0 +1,353 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * Copyright (C) 2014 The  Linux Foundation. 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_NDEBUG 0
+
+#include <cutils/log.h>
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <pthread.h>
+
+#include <sys/ioctl.h>
+#include <sys/types.h>
+
+#include <hardware/lights.h>
+
+/******************************************************************************/
+
+static pthread_once_t g_init = PTHREAD_ONCE_INIT;
+static pthread_mutex_t g_lock = PTHREAD_MUTEX_INITIALIZER;
+static struct light_state_t g_notification;
+static struct light_state_t g_battery;
+static int g_attention = 0;
+
+char const*const RED_LED_FILE
+        = "/sys/class/leds/red/brightness";
+
+char const*const GREEN_LED_FILE
+        = "/sys/class/leds/green/brightness";
+
+char const*const BLUE_LED_FILE
+        = "/sys/class/leds/blue/brightness";
+
+char const*const BLUETOOTH_LED_FILE
+        = "/sys/class/leds/bt/brightness";
+
+char const*const LCD_FILE
+        = "/sys/class/leds/lcd-backlight/brightness";
+
+char const*const BUTTON_FILE
+        = "/sys/class/leds/button-backlight/brightness";
+
+char const*const RED_BLINK_FILE
+        = "/sys/class/leds/red/blink";
+
+char const*const GREEN_BLINK_FILE
+        = "/sys/class/leds/green/blink";
+
+char const*const BLUE_BLINK_FILE
+        = "/sys/class/leds/blue/blink";
+
+/**
+ * device methods
+ */
+
+void init_globals(void)
+{
+    // init the mutex
+    pthread_mutex_init(&g_lock, NULL);
+}
+
+static int
+write_int(char const* path, int value)
+{
+    int fd;
+    static int already_warned = 0;
+
+    fd = open(path, O_RDWR);
+    if (fd >= 0) {
+        char buffer[20];
+        int bytes = snprintf(buffer, sizeof(buffer), "%d\n", value);
+        ssize_t amt = write(fd, buffer, (size_t)bytes);
+        close(fd);
+        return amt == -1 ? -errno : 0;
+    } else {
+        if (already_warned == 0) {
+            ALOGE("write_int failed to open %s\n", path);
+            already_warned = 1;
+        }
+        return -errno;
+    }
+}
+
+static int
+is_lit(struct light_state_t const* state)
+{
+    return state->color & 0x00ffffff;
+}
+
+static int
+rgb_to_brightness(struct light_state_t const* state)
+{
+    int color = state->color & 0x00ffffff;
+    return ((77*((color>>16)&0x00ff))
+            + (150*((color>>8)&0x00ff)) + (29*(color&0x00ff))) >> 8;
+}
+
+static int
+set_light_backlight(struct light_device_t* dev,
+        struct light_state_t const* state)
+{
+    int err = 0;
+    int brightness = rgb_to_brightness(state);
+    if(!dev) {
+        return -1;
+    }
+    pthread_mutex_lock(&g_lock);
+    err = write_int(LCD_FILE, brightness);
+    pthread_mutex_unlock(&g_lock);
+    return err;
+}
+
+static int
+set_speaker_light_locked(struct light_device_t* dev,
+        struct light_state_t const* state)
+{
+    int red, green, blue;
+    int blink;
+    int onMS, offMS;
+    unsigned int colorRGB;
+
+    if(!dev) {
+        return -1;
+    }
+
+    switch (state->flashMode) {
+        case LIGHT_FLASH_TIMED:
+            onMS = state->flashOnMS;
+            offMS = state->flashOffMS;
+            break;
+        case LIGHT_FLASH_NONE:
+        default:
+            onMS = 0;
+            offMS = 0;
+            break;
+    }
+
+    colorRGB = state->color;
+
+#if 0
+    ALOGD("set_speaker_light_locked mode %d, colorRGB=%08X, onMS=%d, offMS=%d\n",
+            state->flashMode, colorRGB, onMS, offMS);
+#endif
+
+    red = (colorRGB >> 16) & 0xFF;
+    green = (colorRGB >> 8) & 0xFF;
+    blue = colorRGB & 0xFF;
+
+    if (onMS > 0 && offMS > 0) {
+        /*
+         * if ON time == OFF time
+         *   use blink mode 2
+         * else
+         *   use blink mode 1
+         */
+        if (onMS == offMS)
+            blink = 2;
+        else
+            blink = 1;
+    } else {
+        blink = 0;
+    }
+
+    if (blink) {
+        if (red) {
+            if (write_int(RED_BLINK_FILE, blink))
+                write_int(RED_LED_FILE, 0);
+	}
+        if (green) {
+            if (write_int(GREEN_BLINK_FILE, blink))
+                write_int(GREEN_LED_FILE, 0);
+	}
+        if (blue) {
+            if (write_int(BLUE_BLINK_FILE, blink))
+                write_int(BLUE_LED_FILE, 0);
+	}
+    } else {
+        write_int(RED_LED_FILE, red);
+        write_int(GREEN_LED_FILE, green);
+        write_int(BLUE_LED_FILE, blue);
+    }
+
+    return 0;
+}
+
+static void
+handle_speaker_battery_locked(struct light_device_t* dev)
+{
+    if (is_lit(&g_battery)) {
+        set_speaker_light_locked(dev, &g_battery);
+    } else {
+        set_speaker_light_locked(dev, &g_notification);
+    }
+}
+
+static int
+set_light_battery(struct light_device_t* dev,
+        struct light_state_t const* state)
+{
+    pthread_mutex_lock(&g_lock);
+    g_battery = *state;
+    handle_speaker_battery_locked(dev);
+    pthread_mutex_unlock(&g_lock);
+    return 0;
+}
+
+static int
+set_light_notifications(struct light_device_t* dev,
+        struct light_state_t const* state)
+{
+    pthread_mutex_lock(&g_lock);
+    g_notification = *state;
+    handle_speaker_battery_locked(dev);
+    pthread_mutex_unlock(&g_lock);
+    return 0;
+}
+
+static int
+set_light_attention(struct light_device_t* dev,
+        struct light_state_t const* state)
+{
+    pthread_mutex_lock(&g_lock);
+    if (state->flashMode == LIGHT_FLASH_HARDWARE) {
+        g_attention = state->flashOnMS;
+    } else if (state->flashMode == LIGHT_FLASH_NONE) {
+        g_attention = 0;
+    }
+    handle_speaker_battery_locked(dev);
+    pthread_mutex_unlock(&g_lock);
+    return 0;
+}
+
+static int
+set_light_buttons(struct light_device_t* dev,
+        struct light_state_t const* state)
+{
+    int err = 0;
+    if(!dev) {
+        return -1;
+    }
+    pthread_mutex_lock(&g_lock);
+    err = write_int(BUTTON_FILE, state->color & 0xFF);
+    pthread_mutex_unlock(&g_lock);
+    return err;
+}
+
+static int
+set_light_bluetooth(struct light_device_t* dev,
+        struct light_state_t const* state)
+{
+    int err = 0;
+    if(!dev) {
+        return -1;
+    }
+    pthread_mutex_lock(&g_lock);
+    err = write_int(BLUETOOTH_LED_FILE, state->color & 0xFF);
+    pthread_mutex_unlock(&g_lock);
+    return err;
+}
+
+/** Close the lights device */
+static int
+close_lights(struct light_device_t *dev)
+{
+    if (dev) {
+        free(dev);
+    }
+    return 0;
+}
+
+
+/******************************************************************************/
+
+/**
+ * module methods
+ */
+
+/** Open a new instance of a lights device using name */
+static int open_lights(const struct hw_module_t* module, char const* name,
+        struct hw_device_t** device)
+{
+    int (*set_light)(struct light_device_t* dev,
+            struct light_state_t const* state);
+
+    if (0 == strcmp(LIGHT_ID_BACKLIGHT, name))
+        set_light = set_light_backlight;
+    else if (0 == strcmp(LIGHT_ID_BATTERY, name))
+        set_light = set_light_battery;
+    else if (0 == strcmp(LIGHT_ID_NOTIFICATIONS, name))
+        set_light = set_light_notifications;
+    else if (0 == strcmp(LIGHT_ID_BUTTONS, name))
+        set_light = set_light_buttons;
+    else if (0 == strcmp(LIGHT_ID_ATTENTION, name))
+        set_light = set_light_attention;
+    else if (0 == strcmp(LIGHT_ID_BLUETOOTH, name))
+        set_light = set_light_bluetooth;
+    else
+        return -EINVAL;
+
+    pthread_once(&g_init, init_globals);
+
+    struct light_device_t *dev = malloc(sizeof(struct light_device_t));
+
+    if(!dev)
+        return -ENOMEM;
+
+    memset(dev, 0, sizeof(*dev));
+
+    dev->common.tag = HARDWARE_DEVICE_TAG;
+    dev->common.version = 0;
+    dev->common.module = (struct hw_module_t*)module;
+    dev->common.close = (int (*)(struct hw_device_t*))close_lights;
+    dev->set_light = set_light;
+
+    *device = (struct hw_device_t*)dev;
+    return 0;
+}
+
+static struct hw_module_methods_t lights_module_methods = {
+    .open =  open_lights,
+};
+
+/*
+ * The lights Module
+ */
+struct hw_module_t HAL_MODULE_INFO_SYM = {
+    .tag = HARDWARE_MODULE_TAG,
+    .version_major = 1,
+    .version_minor = 0,
+    .id = LIGHTS_HARDWARE_MODULE_ID,
+    .name = "lights Module",
+    .author = "Google, Inc.",
+    .methods = &lights_module_methods,
+};
diff --git a/msm8909/libmemtrack/Android.mk b/msm8909/libmemtrack/Android.mk
new file mode 100644
index 0000000..3ed37a3
--- /dev/null
+++ b/msm8909/libmemtrack/Android.mk
@@ -0,0 +1,27 @@
+# Copyright (C) 2013 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 stored in
+# hw/<POWERS_HARDWARE_MODULE_ID>.<ro.hardware>.so
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_RELATIVE_PATH := hw
+LOCAL_C_INCLUDES += hardware/libhardware/include
+LOCAL_CFAGS := -Wconversion -Wall -Werror
+LOCAL_SHARED_LIBRARIES := liblog
+LOCAL_SRC_FILES := memtrack_msm.c kgsl.c
+LOCAL_MODULE := memtrack.$(TARGET_BOARD_PLATFORM)
+include $(BUILD_SHARED_LIBRARY)
diff --git a/msm8909/libmemtrack/kgsl.c b/msm8909/libmemtrack/kgsl.c
new file mode 100644
index 0000000..22bd0c2
--- /dev/null
+++ b/msm8909/libmemtrack/kgsl.c
@@ -0,0 +1,132 @@
+/*
+ * Copyright (C) 2013 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 <errno.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/mman.h>
+
+#include <hardware/memtrack.h>
+
+#include "memtrack_msm.h"
+
+#define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0]))
+#define min(x, y) ((x) < (y) ? (x) : (y))
+
+struct memtrack_record record_templates[] = {
+    {
+        .flags = MEMTRACK_FLAG_SMAPS_ACCOUNTED |
+                 MEMTRACK_FLAG_PRIVATE |
+                 MEMTRACK_FLAG_NONSECURE,
+    },
+    {
+        .flags = MEMTRACK_FLAG_SMAPS_UNACCOUNTED |
+                 MEMTRACK_FLAG_PRIVATE |
+                 MEMTRACK_FLAG_NONSECURE,
+    },
+};
+
+int kgsl_memtrack_get_memory(pid_t pid, enum memtrack_type type,
+                             struct memtrack_record *records,
+                             size_t *num_records)
+{
+    size_t allocated_records = min(*num_records, ARRAY_SIZE(record_templates));
+    int i;
+    FILE *fp;
+    char line[1024];
+    char tmp[128];
+    bool is_surfaceflinger = false;
+    size_t accounted_size = 0;
+    size_t unaccounted_size = 0;
+    unsigned long smaps_addr = 0;
+
+    *num_records = ARRAY_SIZE(record_templates);
+
+    /* fastpath to return the necessary number of records */
+    if (allocated_records == 0) {
+        return 0;
+    }
+
+    snprintf(tmp, sizeof(tmp), "/proc/%d/cmdline", pid);
+    fp = fopen(tmp, "r");
+    if (fp != NULL) {
+        if (fgets(line, sizeof(line), fp)) {
+            if (strcmp(line, "/system/bin/surfaceflinger") == 0)
+                is_surfaceflinger = true;
+        }
+        fclose(fp);
+    }
+
+    memcpy(records, record_templates,
+           sizeof(struct memtrack_record) * allocated_records);
+
+    snprintf(tmp, sizeof(tmp), "/d/kgsl/proc/%d/mem", pid);
+    fp = fopen(tmp, "r");
+    if (fp == NULL) {
+        return -errno;
+    }
+
+    /* Go through each line of <pid>/mem file and for every entry of type "gpumem"
+     * check if the gpubuffer entry is usermapped or not. If the entry is usermapped
+     * count the entry as accounted else count the entry as unaccounted.
+     */
+    while (1) {
+        unsigned long size;
+        char line_type[7];
+        char flags[7];
+        char line_usage[19];
+        int ret;
+
+        if (fgets(line, sizeof(line), fp) == NULL) {
+            break;
+        }
+
+        /* Format:
+         *  gpuaddr useraddr     size    id flags       type            usage sglen
+         * 545ba000 545ba000     4096     1 ----pY     gpumem      arraybuffer     1
+         */
+        ret = sscanf(line, "%*x %*x %lu %*d %6s %6s %18s %*d\n",
+                     &size, flags, line_type, line_usage);
+        if (ret != 4) {
+            continue;
+        }
+
+        if (type == MEMTRACK_TYPE_GL && strcmp(line_type, "gpumem") == 0) {
+
+            if (flags[5] == 'Y')
+                accounted_size += size;
+            else
+                unaccounted_size += size;
+
+        } else if (type == MEMTRACK_TYPE_GRAPHICS && strcmp(line_type, "ion") == 0) {
+            if (!is_surfaceflinger || strcmp(line_usage, "egl_image") != 0) {
+                unaccounted_size += size;
+            }
+        }
+    }
+
+    if (allocated_records > 0) {
+        records[0].size_in_bytes = accounted_size;
+    }
+    if (allocated_records > 1) {
+        records[1].size_in_bytes = unaccounted_size;
+    }
+
+    fclose(fp);
+
+    return 0;
+}
diff --git a/msm8909/libmemtrack/memtrack_msm.c b/msm8909/libmemtrack/memtrack_msm.c
new file mode 100644
index 0000000..8adff96
--- /dev/null
+++ b/msm8909/libmemtrack/memtrack_msm.c
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2013 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 <errno.h>
+
+#include <hardware/memtrack.h>
+
+#include "memtrack_msm.h"
+
+int msm_memtrack_init(const struct memtrack_module *module)
+{
+    if(!module)
+        return -1;
+    return 0;
+}
+
+int msm_memtrack_get_memory(const struct memtrack_module *module,
+                                pid_t pid,
+                                int type,
+                                struct memtrack_record *records,
+                                size_t *num_records)
+{
+    if(!module)
+        return -1;
+    if (type == MEMTRACK_TYPE_GL || type == MEMTRACK_TYPE_GRAPHICS) {
+        return kgsl_memtrack_get_memory(pid, type, records, num_records);
+    }
+
+    return -EINVAL;
+}
+
+static struct hw_module_methods_t memtrack_module_methods = {
+    .open = NULL,
+};
+
+struct memtrack_module HAL_MODULE_INFO_SYM = {
+    common: {
+        tag: HARDWARE_MODULE_TAG,
+        module_api_version: MEMTRACK_MODULE_API_VERSION_0_1,
+        hal_api_version: HARDWARE_HAL_API_VERSION,
+        id: MEMTRACK_HARDWARE_MODULE_ID,
+        name: "MSM Memory Tracker HAL",
+        author: "The Android Open Source Project",
+        methods: &memtrack_module_methods,
+    },
+
+    init: msm_memtrack_init,
+    getMemory: msm_memtrack_get_memory,
+};
+
diff --git a/msm8909/libmemtrack/memtrack_msm.h b/msm8909/libmemtrack/memtrack_msm.h
new file mode 100644
index 0000000..74aa576
--- /dev/null
+++ b/msm8909/libmemtrack/memtrack_msm.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2013 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 _MEMTRACK_MSM_H_
+#define _MEMTRACK_MSM_H_
+
+int kgsl_memtrack_get_memory(pid_t pid, enum memtrack_type type,
+                             struct memtrack_record *records,
+                             size_t *num_records);
+
+#endif
diff --git a/msm8909/liboverlay/Android.mk b/msm8909/liboverlay/Android.mk
new file mode 100644
index 0000000..aa1ea24
--- /dev/null
+++ b/msm8909/liboverlay/Android.mk
@@ -0,0 +1,22 @@
+LOCAL_PATH := $(call my-dir)
+include $(LOCAL_PATH)/../common.mk
+include $(CLEAR_VARS)
+
+LOCAL_MODULE                  := liboverlay
+LOCAL_MODULE_TAGS             := optional
+LOCAL_C_INCLUDES              := $(common_includes) $(kernel_includes)
+LOCAL_SHARED_LIBRARIES        := $(common_libs) libqdutils libmemalloc \
+                                 libsync libdl
+LOCAL_CFLAGS                  := $(common_flags) -DLOG_TAG=\"qdoverlay\"
+LOCAL_ADDITIONAL_DEPENDENCIES := $(common_deps)
+LOCAL_SRC_FILES := \
+      overlay.cpp \
+      overlayUtils.cpp \
+      overlayMdp.cpp \
+      overlayRotator.cpp \
+      overlayMdpRot.cpp \
+      overlayMdssRot.cpp \
+      overlayWriteback.cpp \
+      pipes/overlayGenPipe.cpp
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/msm8909/liboverlay/mdpWrapper.h b/msm8909/liboverlay/mdpWrapper.h
new file mode 100644
index 0000000..f689e45
--- /dev/null
+++ b/msm8909/liboverlay/mdpWrapper.h
@@ -0,0 +1,388 @@
+/*
+* Copyright (c) 2011, The Linux Foundation. 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 The Linux Foundation 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 MDP_WRAPPER_H
+#define MDP_WRAPPER_H
+
+#define ATRACE_TAG (ATRACE_TAG_GRAPHICS | ATRACE_TAG_HAL)
+
+/*
+* In order to make overlay::mdp_wrapper shorter, please do something like:
+* namespace mdpwrap = overlay::mdp_wrapper;
+* */
+
+#include <linux/msm_mdp.h>
+#include <linux/msm_rotator.h>
+#include <sys/ioctl.h>
+#include <utils/Log.h>
+#include <utils/Trace.h>
+#include <errno.h>
+#include "overlayUtils.h"
+#include "overlay.h"
+
+#define IOCTL_DEBUG 0
+#define LIKELY( exp )       (__builtin_expect( (exp) != 0, true  ))
+#define UNLIKELY( exp )     (__builtin_expect( (exp) != 0, false ))
+
+namespace overlay{
+
+namespace mdp_wrapper{
+/* FBIOGET_FSCREENINFO */
+bool getFScreenInfo(int fd, fb_fix_screeninfo& finfo);
+
+/* FBIOGET_VSCREENINFO */
+bool getVScreenInfo(int fd, fb_var_screeninfo& vinfo);
+
+/* FBIOPUT_VSCREENINFO */
+bool setVScreenInfo(int fd, fb_var_screeninfo& vinfo);
+
+/* MSM_ROTATOR_IOCTL_START */
+bool startRotator(int fd, msm_rotator_img_info& rot);
+
+/* MSM_ROTATOR_IOCTL_ROTATE */
+bool rotate(int fd, msm_rotator_data_info& rot);
+
+/* MSMFB_OVERLAY_SET */
+bool setOverlay(int fd, mdp_overlay& ov);
+
+/* MSMFB_OVERLAY_PREPARE */
+int validateAndSet(const int& fd, mdp_overlay_list& list);
+
+/* MSM_ROTATOR_IOCTL_FINISH */
+bool endRotator(int fd, int sessionId);
+
+/* MSMFB_OVERLAY_UNSET */
+bool unsetOverlay(int fd, int ovId);
+
+/* MSMFB_OVERLAY_GET */
+bool getOverlay(int fd, mdp_overlay& ov);
+
+/* MSMFB_OVERLAY_PLAY */
+bool play(int fd, msmfb_overlay_data& od);
+
+/* MSMFB_DISPLAY_COMMIT */
+bool displayCommit(int fd);
+
+/* MSMFB_WRITEBACK_INIT, MSMFB_WRITEBACK_START */
+bool wbInitStart(int fbfd);
+
+/* MSMFB_WRITEBACK_STOP, MSMFB_WRITEBACK_TERMINATE */
+bool wbStopTerminate(int fbfd);
+
+/* MSMFB_WRITEBACK_QUEUE_BUFFER */
+bool wbQueueBuffer(int fbfd, struct msmfb_data& fbData);
+
+/* MSMFB_WRITEBACK_DEQUEUE_BUFFER */
+bool wbDequeueBuffer(int fbfd, struct msmfb_data& fbData);
+
+/* the following are helper functions for dumping
+ * msm_mdp and friends*/
+void dump(const char* const s, const msmfb_overlay_data& ov);
+void dump(const char* const s, const msmfb_data& ov);
+void dump(const char* const s, const mdp_overlay& ov);
+void dump(const char* const s, const uint32_t u[], uint32_t cnt);
+void dump(const char* const s, const msmfb_img& ov);
+void dump(const char* const s, const mdp_rect& ov);
+
+/* and rotator */
+void dump(const char* const s, const msm_rotator_img_info& rot);
+void dump(const char* const s, const msm_rotator_data_info& rot);
+
+/* info */
+void dump(const char* const s, const fb_fix_screeninfo& finfo);
+void dump(const char* const s, const fb_var_screeninfo& vinfo);
+
+//---------------Inlines -------------------------------------
+
+inline bool getFScreenInfo(int fd, fb_fix_screeninfo& finfo) {
+    ATRACE_CALL();
+    if (ioctl(fd, FBIOGET_FSCREENINFO, &finfo) < 0) {
+        ALOGE("Failed to call ioctl FBIOGET_FSCREENINFO err=%s",
+                strerror(errno));
+        return false;
+    }
+    return true;
+}
+
+inline bool getVScreenInfo(int fd, fb_var_screeninfo& vinfo) {
+    ATRACE_CALL();
+    if (ioctl(fd, FBIOGET_VSCREENINFO, &vinfo) < 0) {
+        ALOGE("Failed to call ioctl FBIOGET_VSCREENINFO err=%s",
+                strerror(errno));
+        return false;
+    }
+    return true;
+}
+
+inline bool setVScreenInfo(int fd, fb_var_screeninfo& vinfo) {
+    ATRACE_CALL();
+    if (ioctl(fd, FBIOPUT_VSCREENINFO, &vinfo) < 0) {
+        ALOGE("Failed to call ioctl FBIOPUT_VSCREENINFO err=%s",
+                strerror(errno));
+        return false;
+    }
+    return true;
+}
+
+inline bool startRotator(int fd, msm_rotator_img_info& rot) {
+    ATRACE_CALL();
+    if (ioctl(fd, MSM_ROTATOR_IOCTL_START, &rot) < 0){
+        ALOGE("Failed to call ioctl MSM_ROTATOR_IOCTL_START err=%s",
+                strerror(errno));
+        return false;
+    }
+    return true;
+}
+
+inline bool rotate(int fd, msm_rotator_data_info& rot) {
+    ATRACE_CALL();
+    if (ioctl(fd, MSM_ROTATOR_IOCTL_ROTATE, &rot) < 0) {
+        ALOGE("Failed to call ioctl MSM_ROTATOR_IOCTL_ROTATE err=%s",
+                strerror(errno));
+        return false;
+    }
+    return true;
+}
+
+inline bool setOverlay(int fd, mdp_overlay& ov) {
+    ATRACE_CALL();
+    if (ioctl(fd, MSMFB_OVERLAY_SET, &ov) < 0) {
+        ALOGE("Failed to call ioctl MSMFB_OVERLAY_SET err=%s",
+                strerror(errno));
+        return false;
+    }
+    return true;
+}
+
+inline int validateAndSet(const int& fd, mdp_overlay_list& list) {
+    ATRACE_CALL();
+    uint32_t id = 0;
+    if(UNLIKELY(Overlay::isDebugPipeLifecycle())) {
+        for(uint32_t i = 0; i < list.num_overlays; i++) {
+            if(list.overlay_list[i]->id != (uint32_t)MSMFB_NEW_REQUEST) {
+                id |= list.overlay_list[i]->id;
+            }
+        }
+
+        ALOGD("%s Total pipes needed: %d, Exisiting pipe mask 0x%04x",
+                __FUNCTION__, list.num_overlays, id);
+        id = 0;
+    }
+
+    if (ioctl(fd, MSMFB_OVERLAY_PREPARE, &list) < 0) {
+        ALOGD_IF(IOCTL_DEBUG, "Failed to call ioctl MSMFB_OVERLAY_PREPARE "
+                "err=%s", strerror(errno));
+        return errno;
+    }
+
+    if(UNLIKELY(Overlay::isDebugPipeLifecycle())) {
+        for(uint32_t i = 0; i < list.num_overlays; i++) {
+            id |= list.overlay_list[i]->id;
+        }
+
+        ALOGD("%s Pipe mask after OVERLAY_PREPARE 0x%04x", __FUNCTION__, id);
+    }
+
+    return 0;
+}
+
+inline bool endRotator(int fd, uint32_t sessionId) {
+    ATRACE_CALL();
+    if (ioctl(fd, MSM_ROTATOR_IOCTL_FINISH, &sessionId) < 0) {
+        ALOGE("Failed to call ioctl MSM_ROTATOR_IOCTL_FINISH err=%s",
+                strerror(errno));
+        return false;
+    }
+    return true;
+}
+
+inline bool unsetOverlay(int fd, int ovId) {
+    ATRACE_CALL();
+    ALOGD_IF(Overlay::isDebugPipeLifecycle(), "%s Unsetting pipe 0x%04x",
+            __FUNCTION__, ovId);
+
+    if (ioctl(fd, MSMFB_OVERLAY_UNSET, &ovId) < 0) {
+        ALOGE("Failed to call ioctl MSMFB_OVERLAY_UNSET err=%s",
+                strerror(errno));
+        return false;
+    }
+    return true;
+}
+
+inline bool getOverlay(int fd, mdp_overlay& ov) {
+    ATRACE_CALL();
+    if (ioctl(fd, MSMFB_OVERLAY_GET, &ov) < 0) {
+        ALOGE("Failed to call ioctl MSMFB_OVERLAY_GET err=%s",
+                strerror(errno));
+        return false;
+    }
+    return true;
+}
+
+inline bool play(int fd, msmfb_overlay_data& od) {
+    ATRACE_CALL();
+    if (ioctl(fd, MSMFB_OVERLAY_PLAY, &od) < 0) {
+        ALOGE("Failed to call ioctl MSMFB_OVERLAY_PLAY err=%s",
+                strerror(errno));
+        return false;
+    }
+    return true;
+}
+
+inline bool displayCommit(int fd, mdp_display_commit& info) {
+    ATRACE_CALL();
+    ALOGD_IF(Overlay::isDebugPipeLifecycle(), "%s", __FUNCTION__);
+
+    if(ioctl(fd, MSMFB_DISPLAY_COMMIT, &info) == -1) {
+        ALOGE("Failed to call ioctl MSMFB_DISPLAY_COMMIT err=%s",
+                strerror(errno));
+        return false;
+    }
+    return true;
+}
+
+inline bool wbInitStart(int fbfd) {
+    ATRACE_CALL();
+    if(ioctl(fbfd, MSMFB_WRITEBACK_INIT, NULL) < 0) {
+        ALOGE("Failed to call ioctl MSMFB_WRITEBACK_INIT err=%s",
+                strerror(errno));
+        return false;
+    }
+    if(ioctl(fbfd, MSMFB_WRITEBACK_START, NULL) < 0) {
+        ALOGE("Failed to call ioctl MSMFB_WRITEBACK_START err=%s",
+                strerror(errno));
+        return false;
+    }
+    return true;
+}
+
+inline bool wbStopTerminate(int fbfd) {
+    ATRACE_CALL();
+    if(ioctl(fbfd, MSMFB_WRITEBACK_STOP, NULL) < 0) {
+        ALOGE("Failed to call ioctl MSMFB_WRITEBACK_STOP err=%s",
+                strerror(errno));
+        return false;
+    }
+    if(ioctl(fbfd, MSMFB_WRITEBACK_TERMINATE, NULL) < 0) {
+        ALOGE("Failed to call ioctl MSMFB_WRITEBACK_TERMINATE err=%s",
+                strerror(errno));
+        return false;
+    }
+    return true;
+}
+
+inline bool wbQueueBuffer(int fbfd, struct msmfb_data& fbData) {
+    ATRACE_CALL();
+    if(ioctl(fbfd, MSMFB_WRITEBACK_QUEUE_BUFFER, &fbData) < 0) {
+        ALOGE("Failed to call ioctl MSMFB_WRITEBACK_QUEUE_BUFFER err=%s",
+                strerror(errno));
+        return false;
+    }
+    return true;
+}
+
+inline bool wbDequeueBuffer(int fbfd, struct msmfb_data& fbData) {
+    ATRACE_CALL();
+    if(ioctl(fbfd, MSMFB_WRITEBACK_DEQUEUE_BUFFER, &fbData) < 0) {
+        ALOGE("Failed to call ioctl MSMFB_WRITEBACK_DEQUEUE_BUFFER err=%s",
+                strerror(errno));
+        return false;
+    }
+    return true;
+}
+
+/* dump funcs */
+inline void dump(const char* const s, const msmfb_overlay_data& ov) {
+    ALOGE("%s msmfb_overlay_data id=%d",
+            s, ov.id);
+    dump("data", ov.data);
+}
+inline void dump(const char* const s, const msmfb_data& ov) {
+    ALOGE("%s msmfb_data offset=%d memid=%d id=%d flags=0x%x priv=%d",
+            s, ov.offset, ov.memory_id, ov.id, ov.flags, ov.priv);
+}
+inline void dump(const char* const s, const mdp_overlay& ov) {
+    ALOGE("%s mdp_overlay z=%d alpha=%d mask=%d flags=0x%x id=%d",
+            s, ov.z_order, ov.alpha,
+            ov.transp_mask, ov.flags, ov.id);
+    dump("src", ov.src);
+    dump("src_rect", ov.src_rect);
+    dump("dst_rect", ov.dst_rect);
+    /*
+    Commented off to prevent verbose logging, since user_data could have 8 or so
+    fields which are mostly 0
+    dump("user_data", ov.user_data,
+            sizeof(ov.user_data)/sizeof(ov.user_data[0]));
+    */
+}
+inline void dump(const char* const s, const msmfb_img& ov) {
+    ALOGE("%s msmfb_img w=%d h=%d format=%d %s",
+            s, ov.width, ov.height, ov.format,
+            overlay::utils::getFormatString(ov.format));
+}
+inline void dump(const char* const s, const mdp_rect& ov) {
+    ALOGE("%s mdp_rect x=%d y=%d w=%d h=%d",
+            s, ov.x, ov.y, ov.w, ov.h);
+}
+
+inline void dump(const char* const s, const uint32_t u[], uint32_t cnt) {
+    ALOGE("%s user_data cnt=%d", s, cnt);
+    for(uint32_t i=0; i < cnt; ++i) {
+        ALOGE("i=%d val=%d", i, u[i]);
+    }
+}
+inline void dump(const char* const s, const msm_rotator_img_info& rot) {
+    ALOGE("%s msm_rotator_img_info sessid=%u dstx=%d dsty=%d rot=%d, ena=%d scale=%d",
+            s, rot.session_id, rot.dst_x, rot.dst_y,
+            rot.rotations, rot.enable, rot.downscale_ratio);
+    dump("src", rot.src);
+    dump("dst", rot.dst);
+    dump("src_rect", rot.src_rect);
+}
+inline void dump(const char* const s, const msm_rotator_data_info& rot) {
+    ALOGE("%s msm_rotator_data_info sessid=%u verkey=%d",
+            s, rot.session_id, rot.version_key);
+    dump("src", rot.src);
+    dump("dst", rot.dst);
+    dump("src_chroma", rot.src_chroma);
+    dump("dst_chroma", rot.dst_chroma);
+}
+inline void dump(const char* const s, const fb_fix_screeninfo& finfo) {
+    ALOGE("%s fb_fix_screeninfo type=%d", s, finfo.type);
+}
+inline void dump(const char* const s, const fb_var_screeninfo& vinfo) {
+    ALOGE("%s fb_var_screeninfo xres=%d yres=%d",
+            s, vinfo.xres, vinfo.yres);
+}
+
+} // mdp_wrapper
+
+} // overlay
+
+#endif // MDP_WRAPPER_H
diff --git a/msm8909/liboverlay/overlay.cpp b/msm8909/liboverlay/overlay.cpp
new file mode 100644
index 0000000..1a4bf03
--- /dev/null
+++ b/msm8909/liboverlay/overlay.cpp
@@ -0,0 +1,582 @@
+/*
+* Copyright (c) 2011-2014, The Linux Foundation. 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 The Linux Foundation 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.
+*/
+
+#include <dlfcn.h>
+#include "overlay.h"
+#include "pipes/overlayGenPipe.h"
+#include "mdp_version.h"
+#include "qdMetaData.h"
+#include "qd_utils.h"
+
+namespace overlay {
+using namespace utils;
+using namespace qdutils;
+
+Overlay::Overlay() {
+    int numPipes = qdutils::MDPVersion::getInstance().getTotalPipes();
+    PipeBook::NUM_PIPES = (numPipes <= utils::OV_MAX)? numPipes : utils::OV_MAX;
+    for(int i = 0; i < PipeBook::NUM_PIPES; i++) {
+        mPipeBook[i].init();
+    }
+
+    initScalar();
+    setDMAMultiplexingSupported();
+}
+
+Overlay::~Overlay() {
+    for(int i = 0; i < PipeBook::NUM_PIPES; i++) {
+        mPipeBook[i].destroy();
+    }
+    destroyScalar();
+}
+
+void Overlay::configBegin() {
+    for(int i = 0; i < PipeBook::NUM_PIPES; i++) {
+        //Mark as available for this round.
+        PipeBook::resetUse(i);
+        PipeBook::resetAllocation(i);
+    }
+}
+
+void Overlay::configDone() {
+    for(int i = 0; i < PipeBook::NUM_PIPES; i++) {
+        if((PipeBook::isNotUsed(i) && !sessionInProgress((eDest)i)) ||
+                    isSessionEnded((eDest)i)) {
+            //Forces UNSET on pipes, flushes rotator memory and session, closes
+            //fds
+            mPipeBook[i].destroy();
+        }
+    }
+    PipeBook::save();
+}
+
+int Overlay::getPipeId(utils::eDest dest) {
+    return mPipeBook[(int)dest].mPipe->getPipeId();
+}
+
+eDest Overlay::getDest(int pipeid) {
+    eDest dest = OV_INVALID;
+    // finding the dest corresponding to the given pipe
+    for(int i=0; i < PipeBook::NUM_PIPES; ++i) {
+        if(mPipeBook[i].valid() && mPipeBook[i].mPipe->getPipeId() == pipeid) {
+            return (eDest)i;
+        }
+    }
+    return dest;
+}
+
+eDest Overlay::reservePipe(int pipeid) {
+    eDest dest = getDest(pipeid);
+    PipeBook::setAllocation((int)dest);
+    return dest;
+}
+
+eDest Overlay::nextPipe(eMdpPipeType type, const PipeSpecs& pipeSpecs) {
+    eDest dest = OV_INVALID;
+    int dpy = pipeSpecs.dpy;
+    int mixer = pipeSpecs.mixer;
+    int formatType = pipeSpecs.formatClass;
+    for(int i = 0; i < PipeBook::NUM_PIPES; i++) {
+        if( (type == OV_MDP_PIPE_ANY || //Pipe type match
+             type == PipeBook::getPipeType((eDest)i)) &&
+            (mPipeBook[i].mDisplay == DPY_UNUSED || //Free or same display
+             mPipeBook[i].mDisplay == dpy) &&
+            (mPipeBook[i].mMixer == MIXER_UNUSED || //Free or same mixer
+             mPipeBook[i].mMixer == mixer) &&
+            (mPipeBook[i].mFormatType == FORMAT_NONE || //Free or same format
+             mPipeBook[i].mFormatType == formatType) &&
+            PipeBook::isNotAllocated(i) && //Free pipe
+            ( (sDMAMultiplexingSupported && dpy) ||
+              !(sDMAMode == DMA_BLOCK_MODE && //DMA pipe in Line mode
+               PipeBook::getPipeType((eDest)i) == OV_MDP_PIPE_DMA)) ){
+              //DMA-Multiplexing is only supported for WB on 8x26
+            dest = (eDest)i;
+            PipeBook::setAllocation(i);
+            break;
+        }
+    }
+
+    if(dest != OV_INVALID) {
+        int index = (int)dest;
+        mPipeBook[index].mDisplay = dpy;
+        mPipeBook[index].mMixer = mixer;
+        mPipeBook[index].mFormatType = formatType;
+        if(not mPipeBook[index].valid()) {
+            mPipeBook[index].mPipe = new GenericPipe(dpy);
+            mPipeBook[index].mSession = PipeBook::NONE;
+        }
+    }
+
+    return dest;
+}
+
+utils::eDest Overlay::getPipe(const PipeSpecs& pipeSpecs) {
+    if(MDPVersion::getInstance().is8x26()) {
+        return getPipe_8x26(pipeSpecs);
+    } else if(MDPVersion::getInstance().is8x16()) {
+        return getPipe_8x16(pipeSpecs);
+    } else if(MDPVersion::getInstance().is8x39()) {
+        return getPipe_8x39(pipeSpecs);
+    } else if(MDPVersion::getInstance().is8994()) {
+        return getPipe_8994(pipeSpecs);
+    }
+
+    eDest dest = OV_INVALID;
+
+    //The default behavior is to assume RGB and VG pipes have scalars
+    if(pipeSpecs.formatClass == FORMAT_YUV) {
+        return nextPipe(OV_MDP_PIPE_VG, pipeSpecs);
+    } else if(pipeSpecs.fb == false) { //RGB App layers
+        if(not pipeSpecs.needsScaling) {
+            dest = nextPipe(OV_MDP_PIPE_DMA, pipeSpecs);
+        }
+        if(dest == OV_INVALID) {
+            dest = nextPipe(OV_MDP_PIPE_RGB, pipeSpecs);
+        }
+        if(dest == OV_INVALID) {
+            dest = nextPipe(OV_MDP_PIPE_VG, pipeSpecs);
+        }
+    } else { //FB layer
+        dest = nextPipe(OV_MDP_PIPE_RGB, pipeSpecs);
+        if(dest == OV_INVALID) {
+            dest = nextPipe(OV_MDP_PIPE_VG, pipeSpecs);
+        }
+        //Some features can cause FB to have scaling as well.
+        //If we ever come to this block with FB needing scaling,
+        //the screen will be black for a frame, since the FB won't get a pipe
+        //but atleast this will prevent a hang
+        if(dest == OV_INVALID and (not pipeSpecs.needsScaling)) {
+            dest = nextPipe(OV_MDP_PIPE_DMA, pipeSpecs);
+        }
+    }
+    return dest;
+}
+
+utils::eDest Overlay::getPipe_8x26(const PipeSpecs& pipeSpecs) {
+    //Use this to hide all the 8x26 requirements that cannot be humanly
+    //described in a generic way
+    eDest dest = OV_INVALID;
+    if(pipeSpecs.formatClass == FORMAT_YUV) { //video
+        return nextPipe(OV_MDP_PIPE_VG, pipeSpecs);
+    } else if(pipeSpecs.fb == false) { //RGB app layers
+        if((not pipeSpecs.needsScaling) and
+          (not (pipeSpecs.numActiveDisplays > 1 &&
+                pipeSpecs.dpy == DPY_PRIMARY))) {
+            dest = nextPipe(OV_MDP_PIPE_DMA, pipeSpecs);
+        }
+        if(dest == OV_INVALID) {
+            dest = nextPipe(OV_MDP_PIPE_RGB, pipeSpecs);
+        }
+        if(dest == OV_INVALID) {
+            dest = nextPipe(OV_MDP_PIPE_VG, pipeSpecs);
+        }
+    } else { //FB layer
+        //For 8x26 Secondary we use DMA always for FB for inline rotation
+        if(pipeSpecs.dpy == DPY_PRIMARY) {
+            dest = nextPipe(OV_MDP_PIPE_RGB, pipeSpecs);
+            if(dest == OV_INVALID) {
+                dest = nextPipe(OV_MDP_PIPE_VG, pipeSpecs);
+            }
+        }
+        if(dest == OV_INVALID and (not pipeSpecs.needsScaling) and
+          (not (pipeSpecs.numActiveDisplays > 1 &&
+                pipeSpecs.dpy == DPY_PRIMARY))) {
+            dest = nextPipe(OV_MDP_PIPE_DMA, pipeSpecs);
+        }
+    }
+    return dest;
+}
+
+utils::eDest Overlay::getPipe_8x16(const PipeSpecs& pipeSpecs) {
+    //Having such functions help keeping the interface generic but code specific
+    //and rife with assumptions
+    eDest dest = OV_INVALID;
+    if(pipeSpecs.formatClass == FORMAT_YUV or pipeSpecs.needsScaling) {
+        return nextPipe(OV_MDP_PIPE_VG, pipeSpecs);
+    } else {
+        //Since this is a specific func, we can assume stuff like RGB pipe not
+        //having scalar blocks
+        dest = nextPipe(OV_MDP_PIPE_RGB, pipeSpecs);
+        if(dest == OV_INVALID) {
+            dest = nextPipe(OV_MDP_PIPE_DMA, pipeSpecs);
+        }
+        if(dest == OV_INVALID) {
+            dest = nextPipe(OV_MDP_PIPE_VG, pipeSpecs);
+        }
+    }
+    return dest;
+}
+
+utils::eDest Overlay::getPipe_8x39(const PipeSpecs& pipeSpecs) {
+    //8x16 & 8x36 has same number of pipes, pipe-types & scaling capabilities.
+    //Rely on 8x16 until we see a need to change.
+    return getPipe_8x16(pipeSpecs);
+}
+
+utils::eDest Overlay::getPipe_8994(const PipeSpecs& pipeSpecs) {
+    //If DMA pipes need to be used in block mode for downscale, there could be
+    //cases where consecutive rounds need separate modes, which cannot be
+    //supported since we at least need 1 round in between where the DMA is
+    //unused
+    eDest dest = OV_INVALID;
+    if(pipeSpecs.formatClass == FORMAT_YUV) {
+        return nextPipe(OV_MDP_PIPE_VG, pipeSpecs);
+    } else {
+        dest = nextPipe(OV_MDP_PIPE_RGB, pipeSpecs);
+        if(dest == OV_INVALID) {
+            dest = nextPipe(OV_MDP_PIPE_VG, pipeSpecs);
+        }
+        if(dest == OV_INVALID and not pipeSpecs.needsScaling) {
+            dest = nextPipe(OV_MDP_PIPE_DMA, pipeSpecs);
+        }
+    }
+    return dest;
+}
+
+void Overlay::endAllSessions() {
+    for(int i = 0; i < PipeBook::NUM_PIPES; i++) {
+        if(mPipeBook[i].valid() && mPipeBook[i].mSession==PipeBook::START)
+            mPipeBook[i].mSession = PipeBook::END;
+    }
+}
+
+bool Overlay::isPipeTypeAttached(eMdpPipeType type) {
+    for(int i = 0; i < PipeBook::NUM_PIPES; i++) {
+        if(type == PipeBook::getPipeType((eDest)i) &&
+                mPipeBook[i].mDisplay != DPY_UNUSED) {
+            return true;
+        }
+    }
+    return false;
+}
+
+int Overlay::comparePipePriority(utils::eDest pipe1Index,
+        utils::eDest pipe2Index) {
+    validate((int)pipe1Index);
+    validate((int)pipe2Index);
+    uint8_t pipe1Prio = mPipeBook[(int)pipe1Index].mPipe->getPriority();
+    uint8_t pipe2Prio = mPipeBook[(int)pipe2Index].mPipe->getPriority();
+    if(pipe1Prio > pipe2Prio)
+        return -1;
+    if(pipe1Prio < pipe2Prio)
+        return 1;
+    return 0;
+}
+
+bool Overlay::commit(utils::eDest dest) {
+    bool ret = false;
+    validate((int)dest);
+
+    if(mPipeBook[dest].mPipe->commit()) {
+        ret = true;
+        PipeBook::setUse((int)dest);
+    } else {
+        clear(mPipeBook[dest].mDisplay);
+    }
+    return ret;
+}
+
+bool Overlay::queueBuffer(int fd, uint32_t offset,
+        utils::eDest dest) {
+    bool ret = false;
+    validate((int)dest);
+    //Queue only if commit() has succeeded (and the bit set)
+    if(PipeBook::isUsed((int)dest)) {
+        ret = mPipeBook[dest].mPipe->queueBuffer(fd, offset);
+    }
+    return ret;
+}
+
+void Overlay::setCrop(const utils::Dim& d,
+        utils::eDest dest) {
+    validate((int)dest);
+    mPipeBook[dest].mPipe->setCrop(d);
+}
+
+void Overlay::setColor(const uint32_t color,
+        utils::eDest dest) {
+    validate((int)dest);
+    mPipeBook[dest].mPipe->setColor(color);
+}
+
+void Overlay::setPosition(const utils::Dim& d,
+        utils::eDest dest) {
+    validate((int)dest);
+    mPipeBook[dest].mPipe->setPosition(d);
+}
+
+void Overlay::setTransform(const int orient,
+        utils::eDest dest) {
+    validate((int)dest);
+
+    utils::eTransform transform =
+            static_cast<utils::eTransform>(orient);
+    mPipeBook[dest].mPipe->setTransform(transform);
+
+}
+
+void Overlay::setSource(const utils::PipeArgs args,
+        utils::eDest dest) {
+    validate((int)dest);
+
+    setPipeType(dest, PipeBook::getPipeType(dest));
+    mPipeBook[dest].mPipe->setSource(args);
+}
+
+void Overlay::setVisualParams(const MetaData_t& metadata, utils::eDest dest) {
+    validate((int)dest);
+    mPipeBook[dest].mPipe->setVisualParams(metadata);
+}
+
+void Overlay::setPipeType(utils::eDest pipeIndex,
+        const utils::eMdpPipeType pType) {
+    mPipeBook[pipeIndex].mPipe->setPipeType(pType);
+}
+
+Overlay* Overlay::getInstance() {
+    if(sInstance == NULL) {
+        sInstance = new Overlay();
+    }
+    return sInstance;
+}
+
+// Clears any VG pipes allocated to the fb devices
+// Generates a LUT for pipe types.
+int Overlay::initOverlay() {
+    int mdpVersion = qdutils::MDPVersion::getInstance().getMDPVersion();
+    int numPipesXType[OV_MDP_PIPE_ANY] = {0};
+    numPipesXType[OV_MDP_PIPE_RGB] =
+            qdutils::MDPVersion::getInstance().getRGBPipes();
+    numPipesXType[OV_MDP_PIPE_VG] =
+            qdutils::MDPVersion::getInstance().getVGPipes();
+    numPipesXType[OV_MDP_PIPE_DMA] =
+            qdutils::MDPVersion::getInstance().getDMAPipes();
+
+    int index = 0;
+    for(int X = 0; X < (int)OV_MDP_PIPE_ANY; X++) { //iterate over types
+        for(int j = 0; j < numPipesXType[X]; j++) { //iterate over num
+            PipeBook::pipeTypeLUT[index] = (utils::eMdpPipeType)X;
+            index++;
+        }
+    }
+
+    if (mdpVersion < qdutils::MDSS_V5 && mdpVersion > qdutils::MDP_V3_0_5) {
+        msmfb_mixer_info_req  req;
+        mdp_mixer_info *minfo = NULL;
+        char name[64];
+        int fd = -1;
+        for(int i = 0; i < MAX_FB_DEVICES; i++) {
+            snprintf(name, 64, FB_DEVICE_TEMPLATE, i);
+            ALOGD("initoverlay:: opening the device:: %s", name);
+            fd = ::open(name, O_RDWR, 0);
+            if(fd < 0) {
+                ALOGE("cannot open framebuffer(%d)", i);
+                return -1;
+            }
+            //Get the mixer configuration */
+            req.mixer_num = i;
+            if (ioctl(fd, MSMFB_MIXER_INFO, &req) == -1) {
+                ALOGE("ERROR: MSMFB_MIXER_INFO ioctl failed");
+                close(fd);
+                return -1;
+            }
+            minfo = req.info;
+            for (int j = 0; j < req.cnt; j++) {
+                ALOGD("ndx=%d num=%d z_order=%d", minfo->pndx, minfo->pnum,
+                      minfo->z_order);
+                // except the RGB base layer with z_order of -1, clear any
+                // other pipes connected to mixer.
+                if((minfo->z_order) != -1) {
+                    int index = minfo->pndx;
+                    ALOGD("Unset overlay with index: %d at mixer %d", index, i);
+                    if(ioctl(fd, MSMFB_OVERLAY_UNSET, &index) == -1) {
+                        ALOGE("ERROR: MSMFB_OVERLAY_UNSET failed");
+                        close(fd);
+                        return -1;
+                    }
+                }
+                minfo++;
+            }
+            close(fd);
+            fd = -1;
+        }
+    }
+
+    FILE *displayDeviceFP = NULL;
+    char fbType[MAX_FRAME_BUFFER_NAME_SIZE];
+    char msmFbTypePath[MAX_FRAME_BUFFER_NAME_SIZE];
+    const char *strDtvPanel = "dtv panel";
+    const char *strWbPanel = "writeback panel";
+
+    for(int num = 1; num < MAX_FB_DEVICES; num++) {
+        snprintf (msmFbTypePath, sizeof(msmFbTypePath),
+                "/sys/class/graphics/fb%d/msm_fb_type", num);
+        displayDeviceFP = fopen(msmFbTypePath, "r");
+
+        if(displayDeviceFP){
+            fread(fbType, sizeof(char), MAX_FRAME_BUFFER_NAME_SIZE,
+                    displayDeviceFP);
+
+            if(strncmp(fbType, strDtvPanel, strlen(strDtvPanel)) == 0) {
+                sDpyFbMap[DPY_EXTERNAL] = num;
+            } else if(strncmp(fbType, strWbPanel, strlen(strWbPanel)) == 0) {
+                sDpyFbMap[DPY_WRITEBACK] = num;
+            }
+
+            fclose(displayDeviceFP);
+        }
+    }
+
+    return 0;
+}
+
+bool Overlay::displayCommit(const int& fd) {
+    utils::Dim lRoi, rRoi;
+    return displayCommit(fd, lRoi, rRoi);
+}
+
+bool Overlay::displayCommit(const int& fd, const utils::Dim& lRoi,
+        const utils::Dim& rRoi) {
+    //Commit
+    struct mdp_display_commit info;
+    memset(&info, 0, sizeof(struct mdp_display_commit));
+    info.flags = MDP_DISPLAY_COMMIT_OVERLAY;
+    info.l_roi.x = lRoi.x;
+    info.l_roi.y = lRoi.y;
+    info.l_roi.w = lRoi.w;
+    info.l_roi.h = lRoi.h;
+    info.r_roi.x = rRoi.x;
+    info.r_roi.y = rRoi.y;
+    info.r_roi.w = rRoi.w;
+    info.r_roi.h = rRoi.h;
+
+    if(!mdp_wrapper::displayCommit(fd, info)) {
+        ALOGE("%s: commit failed", __func__);
+        return false;
+    }
+    return true;
+}
+
+void Overlay::getDump(char *buf, size_t len) {
+    int totalPipes = 0;
+    const char *str = "\nOverlay State\n\n";
+    strlcat(buf, str, len);
+    for(int i = 0; i < PipeBook::NUM_PIPES; i++) {
+        if(mPipeBook[i].valid()) {
+            mPipeBook[i].mPipe->getDump(buf, len);
+            char str[64] = {'\0'};
+            snprintf(str, 64, "Display=%d\n\n", mPipeBook[i].mDisplay);
+            strlcat(buf, str, len);
+            totalPipes++;
+        }
+    }
+    char str_pipes[64] = {'\0'};
+    snprintf(str_pipes, 64, "Pipes=%d\n\n", totalPipes);
+    strlcat(buf, str_pipes, len);
+}
+
+void Overlay::clear(int dpy) {
+    for(int i = 0; i < PipeBook::NUM_PIPES; i++) {
+        if (mPipeBook[i].mDisplay == dpy) {
+            // Mark as available for this round
+            PipeBook::resetUse(i);
+            PipeBook::resetAllocation(i);
+            if(getPipeId((utils::eDest)i) == -1) {
+                mPipeBook[i].destroy();
+            }
+        }
+    }
+}
+
+bool Overlay::validateAndSet(const int& dpy, const int& fbFd) {
+    GenericPipe* pipeArray[PipeBook::NUM_PIPES];
+    memset(pipeArray, 0, sizeof(GenericPipe*)*(PipeBook::NUM_PIPES));
+
+    int num = 0;
+    for(int i = 0; i < PipeBook::NUM_PIPES; i++) {
+        if(PipeBook::isUsed(i) && mPipeBook[i].valid() &&
+                mPipeBook[i].mDisplay == dpy) {
+            pipeArray[num++] = mPipeBook[i].mPipe;
+        }
+    }
+
+    //Protect against misbehaving clients
+    return num ? GenericPipe::validateAndSet(pipeArray, num, fbFd) : true;
+}
+
+void Overlay::initScalar() {
+    if(sLibScaleHandle == NULL) {
+        sLibScaleHandle = dlopen("libscale.so", RTLD_NOW);
+        if(sLibScaleHandle) {
+            *(void **) &sFnProgramScale =
+                    dlsym(sLibScaleHandle, "programScale");
+        }
+    }
+}
+
+void Overlay::destroyScalar() {
+    if(sLibScaleHandle) {
+        dlclose(sLibScaleHandle);
+        sLibScaleHandle = NULL;
+    }
+}
+
+void Overlay::PipeBook::init() {
+    mPipe = NULL;
+    mDisplay = DPY_UNUSED;
+    mMixer = MIXER_UNUSED;
+    mFormatType = FORMAT_NONE;
+}
+
+void Overlay::PipeBook::destroy() {
+    if(mPipe) {
+        delete mPipe;
+        mPipe = NULL;
+    }
+    mDisplay = DPY_UNUSED;
+    mMixer = MIXER_UNUSED;
+    mFormatType = FORMAT_NONE;
+    mSession = NONE;
+}
+
+Overlay* Overlay::sInstance = 0;
+int Overlay::sDpyFbMap[DPY_MAX] = {0, -1, -1, -1};
+int Overlay::sDMAMode = DMA_LINE_MODE;
+bool Overlay::sDMAMultiplexingSupported = false;
+bool Overlay::sDebugPipeLifecycle = false;
+int Overlay::PipeBook::NUM_PIPES = 0;
+int Overlay::PipeBook::sPipeUsageBitmap = 0;
+int Overlay::PipeBook::sLastUsageBitmap = 0;
+int Overlay::PipeBook::sAllocatedBitmap = 0;
+utils::eMdpPipeType Overlay::PipeBook::pipeTypeLUT[utils::OV_MAX] =
+    {utils::OV_MDP_PIPE_ANY};
+void *Overlay::sLibScaleHandle = NULL;
+int (*Overlay::sFnProgramScale)(struct mdp_overlay_list *) = NULL;
+
+}; // namespace overlay
diff --git a/msm8909/liboverlay/overlay.h b/msm8909/liboverlay/overlay.h
new file mode 100644
index 0000000..5c93b23
--- /dev/null
+++ b/msm8909/liboverlay/overlay.h
@@ -0,0 +1,428 @@
+/*
+* Copyright (c) 2011-2013, The Linux Foundation. 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 The Linux Foundation. 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 OVERLAY_H
+#define OVERLAY_H
+
+#include "overlayUtils.h"
+#include "mdp_version.h"
+#include "utils/threads.h"
+
+struct MetaData_t;
+
+namespace overlay {
+class GenericPipe;
+
+class Overlay : utils::NoCopy {
+public:
+    enum { DMA_BLOCK_MODE, DMA_LINE_MODE };
+    //Abstract Display types. Each backed by a LayerMixer,
+    //represented by a fb node.
+    //High res panels can be backed by 2 layer mixers and a single fb node.
+    enum { DPY_PRIMARY, DPY_EXTERNAL, DPY_TERTIARY, DPY_WRITEBACK, DPY_UNUSED };
+    enum { DPY_MAX = DPY_UNUSED };
+    enum { MIXER_LEFT, MIXER_RIGHT, MIXER_UNUSED };
+    enum { MIXER_DEFAULT = MIXER_LEFT, MIXER_MAX = MIXER_UNUSED };
+    enum { MAX_FB_DEVICES = DPY_MAX };
+    enum { FORMAT_YUV, FORMAT_RGB , FORMAT_NONE };
+
+    struct PipeSpecs {
+        PipeSpecs() : formatClass(FORMAT_RGB), needsScaling(false), fb(false),
+                dpy(DPY_PRIMARY), mixer(MIXER_DEFAULT), numActiveDisplays(1) {}
+        int formatClass;
+        bool needsScaling;
+        bool fb;
+        int dpy;
+        int mixer;
+        int numActiveDisplays;
+    };
+
+    /* dtor close */
+    ~Overlay();
+
+    /* Marks the beginning of a drawing round, resets usage bits on pipes
+     * Should be called when drawing begins before any pipe config is done.
+     */
+    void configBegin();
+
+    /* Marks the end of config for this drawing round
+     * Will do garbage collection of pipe objects and thus calling UNSETs,
+     * closing FDs, removing rotator objects and memory, if allocated.
+     * Should be called after all pipe configs are done.
+     */
+    void configDone();
+
+    /* Get a pipe that supported the specified format class (yuv, rgb) and has
+     * scaling capabilities.
+     */
+    utils::eDest getPipe(const PipeSpecs& pipeSpecs);
+    /* Returns the eDest corresponding to an already allocated pipeid.
+     * Useful for the reservation case, when libvpu reserves the pipe at its
+     * end, and expect the overlay to allocate a given pipe for a layer.
+     */
+    utils::eDest reservePipe(int pipeid);
+    /* getting dest for the given pipeid */
+    utils::eDest getDest(int pipeid);
+    /* getting overlay.pipeid for the given dest */
+    int getPipeId(utils::eDest dest);
+
+    void setSource(const utils::PipeArgs args, utils::eDest dest);
+    void setCrop(const utils::Dim& d, utils::eDest dest);
+    void setColor(const uint32_t color, utils::eDest dest);
+    void setTransform(const int orientation, utils::eDest dest);
+    void setPosition(const utils::Dim& dim, utils::eDest dest);
+    void setVisualParams(const MetaData_t& data, utils::eDest dest);
+    bool commit(utils::eDest dest);
+    bool queueBuffer(int fd, uint32_t offset, utils::eDest dest);
+
+    /* pipe reservation session is running */
+    bool sessionInProgress(utils::eDest dest);
+    /* pipe reservation session has ended*/
+    bool isSessionEnded(utils::eDest dest);
+    /* start session for the pipe reservation */
+    void startSession(utils::eDest dest);
+    /* end all started sesisons */
+    void endAllSessions();
+    /* Returns available ("unallocated") pipes for a display's mixer */
+    int availablePipes(int dpy, int mixer);
+    /* Returns available ("unallocated") pipes for a display */
+    int availablePipes(int dpy);
+    /* Returns available ("unallocated") pipe of given type for a display */
+    int availablePipes(int dpy, utils::eMdpPipeType type);
+    /* Returns if any of the requested pipe type is attached to any of the
+     * displays
+     */
+    bool isPipeTypeAttached(utils::eMdpPipeType type);
+    /* Compare pipe priorities and return
+     * 1 if 1st pipe has a higher priority
+     * 0 if both have the same priority
+     *-1 if 2nd pipe has a higher priority
+     */
+    int comparePipePriority(utils::eDest pipe1Index, utils::eDest pipe2Index);
+    /* Returns pipe dump. Expects a NULL terminated buffer of big enough size
+     * to populate.
+     */
+    /* Returns if DMA pipe multiplexing is supported by the mdss driver */
+    static bool isDMAMultiplexingSupported();
+    /* Returns if UI scaling on external is supported on the targets */
+    static bool isUIScalingOnExternalSupported();
+    void getDump(char *buf, size_t len);
+    /* Reset usage and allocation bits on all pipes for given display */
+    void clear(int dpy);
+    /* Validate the set of pipes for a display and set them in driver */
+    bool validateAndSet(const int& dpy, const int& fbFd);
+
+    /* Closes open pipes, called during startup */
+    static int initOverlay();
+    /* Returns the singleton instance of overlay */
+    static Overlay* getInstance();
+    static void setDMAMode(const int& mode);
+    static int getDMAMode();
+    /* Returns the framebuffer node backing up the display */
+    static int getFbForDpy(const int& dpy);
+
+    static bool displayCommit(const int& fd);
+    /* Overloads display commit with ROI's of each halves.
+     * Single interface panels will only update left ROI. */
+    static bool displayCommit(const int& fd, const utils::Dim& lRoi,
+                              const utils::Dim& rRoi);
+    /* Logs pipe lifecycle events like set, unset, commit when enabled */
+    static void debugPipeLifecycle(const bool& enable);
+    /* Returns true if pipe life cycle logging is enabled */
+    static bool isDebugPipeLifecycle();
+
+private:
+    /* Ctor setup */
+    explicit Overlay();
+    /*Validate index range, abort if invalid */
+    void validate(int index);
+    static void setDMAMultiplexingSupported();
+    /* Returns an available pipe based on the type of pipe requested. When ANY
+     * is requested, the first available VG or RGB is returned. If no pipe is
+     * available for the display "dpy" then INV is returned. Note: If a pipe is
+     * assigned to a certain display, then it cannot be assigned to another
+     * display without being garbage-collected once. To add if a pipe is
+     * asisgned to a mixer within a display it cannot be reused for another
+     * mixer without being UNSET once*/
+    utils::eDest nextPipe(utils::eMdpPipeType, const PipeSpecs& pipeSpecs);
+    /* Helpers that enfore target specific policies while returning pipes */
+    utils::eDest getPipe_8x26(const PipeSpecs& pipeSpecs);
+    utils::eDest getPipe_8x16(const PipeSpecs& pipeSpecs);
+    utils::eDest getPipe_8x39(const PipeSpecs& pipeSpecs);
+    utils::eDest getPipe_8994(const PipeSpecs& pipeSpecs);
+
+    /* Returns the handle to libscale.so's programScale function */
+    static int (*getFnProgramScale())(struct mdp_overlay_list *);
+    /* Creates a scalar object using libscale.so */
+    static void initScalar();
+    /* Destroys the scalar object using libscale.so */
+    static void destroyScalar();
+    /* Sets the pipe type RGB/VG/DMA*/
+    void setPipeType(utils::eDest pipeIndex, const utils::eMdpPipeType pType);
+
+    /* Just like a Facebook for pipes, but much less profile info */
+    struct PipeBook {
+        void init();
+        void destroy();
+        /* Check if pipe exists and return true, false otherwise */
+        bool valid();
+
+        /* Hardware pipe wrapper */
+        GenericPipe *mPipe;
+        /* Display using this pipe. Refer to enums above */
+        int mDisplay;
+        /* Mixer within a split display this pipe is attached to */
+        int mMixer;
+        /* Format for which this pipe is attached to the mixer*/
+        int mFormatType;
+
+        /* operations on bitmap */
+        static bool pipeUsageUnchanged();
+        static void setUse(int index);
+        static void resetUse(int index);
+        static bool isUsed(int index);
+        static bool isNotUsed(int index);
+        static void save();
+
+        static void setAllocation(int index);
+        static void resetAllocation(int index);
+        static bool isAllocated(int index);
+        static bool isNotAllocated(int index);
+
+        static utils::eMdpPipeType getPipeType(utils::eDest dest);
+        static const char* getDestStr(utils::eDest dest);
+
+        static int NUM_PIPES;
+        static utils::eMdpPipeType pipeTypeLUT[utils::OV_MAX];
+        /* Session for reserved pipes */
+        enum Session {
+            NONE,
+            START,
+            END
+        };
+        Session mSession;
+
+    private:
+        //usage tracks if a successful commit happened. So a pipe could be
+        //allocated to a display, but it may not end up using it for various
+        //reasons. If one display actually uses a pipe then it amy not be
+        //used by another display, without an UNSET in between.
+        static int sPipeUsageBitmap;
+        static int sLastUsageBitmap;
+        //Tracks which pipe objects are allocated. This does not imply that they
+        //will actually be used. For example, a display might choose to acquire
+        //3 pipe objects in one shot and proceed with config only if it gets all
+        //3. The bitmap helps allocate different pipe objects on each request.
+        static int sAllocatedBitmap;
+    };
+
+    PipeBook mPipeBook[utils::OV_INVALID]; //Used as max
+
+    /* Singleton Instance*/
+    static Overlay *sInstance;
+    static int sDpyFbMap[DPY_MAX];
+    static int sDMAMode;
+    static bool sDMAMultiplexingSupported;
+    static void *sLibScaleHandle;
+    static int (*sFnProgramScale)(struct mdp_overlay_list *);
+    static bool sDebugPipeLifecycle;
+
+    friend class MdpCtrl;
+};
+
+inline void Overlay::validate(int index) {
+    OVASSERT(index >=0 && index < PipeBook::NUM_PIPES, \
+        "%s, Index out of bounds: %d", __FUNCTION__, index);
+    OVASSERT(mPipeBook[index].valid(), "Pipe does not exist %s",
+            PipeBook::getDestStr((utils::eDest)index));
+}
+
+inline int Overlay::availablePipes(int dpy, int mixer) {
+    int avail = 0;
+    for(int i = 0; i < PipeBook::NUM_PIPES; i++) {
+        if( (mPipeBook[i].mDisplay == DPY_UNUSED ||
+             mPipeBook[i].mDisplay == dpy) &&
+            (mPipeBook[i].mMixer == MIXER_UNUSED ||
+             mPipeBook[i].mMixer == mixer) &&
+            PipeBook::isNotAllocated(i) &&
+            !(Overlay::getDMAMode() == Overlay::DMA_BLOCK_MODE &&
+              PipeBook::getPipeType((utils::eDest)i) ==
+              utils::OV_MDP_PIPE_DMA)) {
+            avail++;
+        }
+    }
+    return avail;
+}
+
+inline int Overlay::availablePipes(int dpy) {
+    int avail = 0;
+    for(int i = 0; i < PipeBook::NUM_PIPES; i++) {
+        if( (mPipeBook[i].mDisplay == DPY_UNUSED ||
+             mPipeBook[i].mDisplay == dpy) &&
+            PipeBook::isNotAllocated(i) &&
+            !(Overlay::getDMAMode() == Overlay::DMA_BLOCK_MODE &&
+              PipeBook::getPipeType((utils::eDest)i) ==
+              utils::OV_MDP_PIPE_DMA)) {
+            avail++;
+        }
+    }
+    return avail;
+}
+
+inline int Overlay::availablePipes(int dpy, utils::eMdpPipeType type) {
+    int avail = 0;
+    for(int i = 0; i < PipeBook::NUM_PIPES; i++) {
+        if((mPipeBook[i].mDisplay == DPY_UNUSED ||
+            mPipeBook[i].mDisplay == dpy) &&
+            PipeBook::isNotAllocated(i) &&
+            type == PipeBook::getPipeType((utils::eDest)i)) {
+            avail++;
+        }
+    }
+    return avail;
+}
+
+inline void Overlay::setDMAMode(const int& mode) {
+    if(mode == DMA_LINE_MODE || mode == DMA_BLOCK_MODE)
+        sDMAMode = mode;
+}
+
+inline void Overlay::setDMAMultiplexingSupported() {
+    sDMAMultiplexingSupported = false;
+    if(qdutils::MDPVersion::getInstance().is8x26())
+        sDMAMultiplexingSupported = true;
+}
+
+inline bool Overlay::isDMAMultiplexingSupported() {
+    return sDMAMultiplexingSupported;
+}
+
+inline bool Overlay::isUIScalingOnExternalSupported() {
+    if(qdutils::MDPVersion::getInstance().is8x26() or
+       qdutils::MDPVersion::getInstance().is8x16() or
+       qdutils::MDPVersion::getInstance().is8x39()) {
+        return false;
+    }
+    return true;
+}
+
+inline int Overlay::getDMAMode() {
+    return sDMAMode;
+}
+
+inline int Overlay::getFbForDpy(const int& dpy) {
+    OVASSERT(dpy >= 0 && dpy < DPY_MAX, "Invalid dpy %d", dpy);
+    return sDpyFbMap[dpy];
+}
+
+inline int (*Overlay::getFnProgramScale())(struct mdp_overlay_list *) {
+    return sFnProgramScale;
+}
+
+inline void Overlay::debugPipeLifecycle(const bool& enable) {
+    sDebugPipeLifecycle = enable;
+}
+
+inline bool Overlay::isDebugPipeLifecycle() {
+    return sDebugPipeLifecycle;
+}
+
+inline bool Overlay::PipeBook::valid() {
+    return (mPipe != NULL);
+}
+
+inline bool Overlay::PipeBook::pipeUsageUnchanged() {
+    return (sPipeUsageBitmap == sLastUsageBitmap);
+}
+
+inline void Overlay::PipeBook::setUse(int index) {
+    sPipeUsageBitmap |= (1 << index);
+}
+
+inline void Overlay::PipeBook::resetUse(int index) {
+    sPipeUsageBitmap &= ~(1 << index);
+}
+
+inline bool Overlay::PipeBook::isUsed(int index) {
+    return sPipeUsageBitmap & (1 << index);
+}
+
+inline bool Overlay::PipeBook::isNotUsed(int index) {
+    return !isUsed(index);
+}
+
+inline void Overlay::PipeBook::save() {
+    sLastUsageBitmap = sPipeUsageBitmap;
+}
+
+inline void Overlay::PipeBook::setAllocation(int index) {
+    sAllocatedBitmap |= (1 << index);
+}
+
+inline void Overlay::PipeBook::resetAllocation(int index) {
+    sAllocatedBitmap &= ~(1 << index);
+}
+
+inline bool Overlay::PipeBook::isAllocated(int index) {
+    return sAllocatedBitmap & (1 << index);
+}
+
+inline bool Overlay::PipeBook::isNotAllocated(int index) {
+    return !isAllocated(index);
+}
+
+inline utils::eMdpPipeType Overlay::PipeBook::getPipeType(utils::eDest dest) {
+    return pipeTypeLUT[(int)dest];
+}
+
+inline void Overlay::startSession(utils::eDest dest) {
+    mPipeBook[(int)dest].mSession = PipeBook::START;
+}
+
+inline bool Overlay::sessionInProgress(utils::eDest dest) {
+    return (mPipeBook[(int)dest].mSession == PipeBook::START);
+}
+
+inline bool Overlay::isSessionEnded(utils::eDest dest) {
+    return (mPipeBook[(int)dest].mSession == PipeBook::END);
+}
+
+inline const char* Overlay::PipeBook::getDestStr(utils::eDest dest) {
+    switch(getPipeType(dest)) {
+        case utils::OV_MDP_PIPE_RGB: return "RGB";
+        case utils::OV_MDP_PIPE_VG: return "VG";
+        case utils::OV_MDP_PIPE_DMA: return "DMA";
+        default: return "Invalid";
+    }
+    return "Invalid";
+}
+
+}; // overlay
+
+#endif // OVERLAY_H
diff --git a/msm8909/liboverlay/overlayCtrlData.h b/msm8909/liboverlay/overlayCtrlData.h
new file mode 100644
index 0000000..2eec98c
--- /dev/null
+++ b/msm8909/liboverlay/overlayCtrlData.h
@@ -0,0 +1,249 @@
+/*
+* Copyright (c) 2012-2013, The Linux Foundation. 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 The Linux Foundation 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 OVERLAY_CTRLDATA_H
+#define OVERLAY_CTRLDATA_H
+
+#include "overlayUtils.h"
+#include "overlayMdp.h"
+#include "gralloc_priv.h" // INTERLACE_MASK
+
+namespace ovutils = overlay::utils;
+
+namespace overlay {
+
+/*
+* Sequence to use:
+* init
+* start
+* setXXX
+* close
+* */
+class Ctrl : utils::NoCopy {
+public:
+
+    /* ctor */
+    explicit Ctrl(const int& dpy);
+    /* dtor close */
+    ~Ctrl();
+
+    /* set source using whf, orient and wait flag */
+    void setSource(const utils::PipeArgs& args);
+    /* set crop info and pass it down to mdp */
+    void setCrop(const utils::Dim& d);
+    /* set color for mdp pipe */
+    void setColor(const uint32_t color);
+    /* set orientation */
+    void setTransform(const utils::eTransform& p);
+    /* set mdp position using dim */
+    void setPosition(const utils::Dim& dim);
+    /* set mdp visual params using metadata */
+    bool setVisualParams(const MetaData_t &metadata);
+    /* set pipe type RGB/DMA/VG */
+    void setPipeType(const utils::eMdpPipeType& pType);
+    /* mdp set overlay/commit changes */
+    bool commit();
+
+    /* ctrl id */
+    int  getPipeId() const;
+    /* ctrl fd */
+    int  getFd() const;
+    /* retrieve crop data */
+    utils::Dim getCrop() const;
+    utils::Dim getPosition() const;
+    /* Update the src format based on rotator's dest */
+    void updateSrcFormat(const uint32_t& rotDstFormat);
+    /* return pipe priority */
+    uint8_t getPriority() const;
+    /* dump the state of the object */
+    void dump() const;
+    /* Return the dump in the specified buffer */
+    void getDump(char *buf, size_t len);
+
+    static bool validateAndSet(Ctrl* ctrlArray[], const int& count,
+            const int& fbFd);
+private:
+    // mdp ctrl struct(info e.g.)
+    MdpCtrl *mMdp;
+};
+
+
+class Data : utils::NoCopy {
+public:
+    /* init, reset */
+    explicit Data(const int& dpy);
+    /* calls close */
+    ~Data();
+    /* set overlay pipe id in the mdp struct */
+    void setPipeId(int id);
+    /* get overlay id in the mdp struct */
+    int getPipeId() const;
+    /* queue buffer to the overlay */
+    bool queueBuffer(int fd, uint32_t offset);
+    /* sump the state of the obj */
+    void dump() const;
+    /* Return the dump in the specified buffer */
+    void getDump(char *buf, size_t len);
+
+private:
+    // mdp data struct
+    MdpData *mMdp;
+};
+
+//-------------Inlines-------------------------------
+
+inline Ctrl::Ctrl(const int& dpy) : mMdp(new MdpCtrl(dpy)) {
+}
+
+inline Ctrl::~Ctrl() {
+    delete mMdp;
+}
+
+inline void Ctrl::setSource(const utils::PipeArgs& args)
+{
+    mMdp->setSource(args);
+}
+
+inline void Ctrl::setPosition(const utils::Dim& dim)
+{
+    mMdp->setPosition(dim);
+}
+
+inline void Ctrl::setTransform(const utils::eTransform& orient)
+{
+    mMdp->setTransform(orient);
+}
+
+inline void Ctrl::setCrop(const utils::Dim& d)
+{
+    mMdp->setCrop(d);
+}
+
+inline void Ctrl::setColor(const uint32_t color)
+{
+    mMdp->setColor(color);
+}
+
+inline bool Ctrl::setVisualParams(const MetaData_t &metadata)
+{
+    if (!mMdp->setVisualParams(metadata)) {
+        ALOGE("Ctrl setVisualParams failed in MDP setVisualParams");
+        return false;
+    }
+    return true;
+}
+
+inline void Ctrl::setPipeType(const utils::eMdpPipeType& pType)
+{
+    mMdp->setPipeType(pType);
+}
+
+inline void Ctrl::dump() const {
+    ALOGE("== Dump Ctrl start ==");
+    mMdp->dump();
+    ALOGE("== Dump Ctrl end ==");
+}
+
+inline bool Ctrl::commit() {
+    if(!mMdp->set()) {
+        ALOGE("Ctrl commit failed set overlay");
+        return false;
+    }
+    return true;
+}
+
+inline int Ctrl::getPipeId() const {
+    return mMdp->getPipeId();
+}
+
+inline int Ctrl::getFd() const {
+    return mMdp->getFd();
+}
+
+inline void Ctrl::updateSrcFormat(const uint32_t& rotDstFmt) {
+    mMdp->updateSrcFormat(rotDstFmt);
+}
+
+inline bool Ctrl::validateAndSet(Ctrl* ctrlArray[], const int& count,
+        const int& fbFd) {
+    MdpCtrl* mdpCtrlArray[count];
+    memset(&mdpCtrlArray, 0, sizeof(mdpCtrlArray));
+
+    for(int i = 0; i < count; i++) {
+        mdpCtrlArray[i] = ctrlArray[i]->mMdp;
+    }
+
+    bool ret = MdpCtrl::validateAndSet(mdpCtrlArray, count, fbFd);
+    return ret;
+}
+
+inline utils::Dim Ctrl::getCrop() const {
+    return mMdp->getSrcRectDim();
+}
+
+inline utils::Dim Ctrl::getPosition() const {
+    return mMdp->getDstRectDim();
+}
+
+inline uint8_t Ctrl::getPriority() const {
+    return mMdp->getPriority();
+}
+
+inline void Ctrl::getDump(char *buf, size_t len) {
+    mMdp->getDump(buf, len);
+}
+
+inline Data::Data(const int& dpy) : mMdp(new MdpData(dpy)) {
+}
+
+inline Data::~Data() {
+    delete mMdp;
+}
+
+inline void Data::setPipeId(int id) { mMdp->setPipeId(id); }
+
+inline int Data::getPipeId() const { return mMdp->getPipeId(); }
+
+inline bool Data::queueBuffer(int fd, uint32_t offset) {
+    return mMdp->play(fd, offset);
+}
+
+inline void Data::dump() const {
+    ALOGE("== Dump Data MDP start ==");
+    mMdp->dump();
+    ALOGE("== Dump Data MDP end ==");
+}
+
+inline void Data::getDump(char *buf, size_t len) {
+    mMdp->getDump(buf, len);
+}
+
+} // overlay
+
+#endif
diff --git a/msm8909/liboverlay/overlayMdp.cpp b/msm8909/liboverlay/overlayMdp.cpp
new file mode 100644
index 0000000..ee8d762
--- /dev/null
+++ b/msm8909/liboverlay/overlayMdp.cpp
@@ -0,0 +1,397 @@
+/*
+* Copyright (C) 2008 The Android Open Source Project
+* Copyright (c) 2010-2014, The Linux Foundation. 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 <math.h>
+#include <mdp_version.h>
+#include "overlayUtils.h"
+#include "overlayMdp.h"
+#include "mdp_version.h"
+#include <overlay.h>
+
+#define HSIC_SETTINGS_DEBUG 0
+
+using namespace qdutils;
+
+static inline bool isEqual(float f1, float f2) {
+        return ((int)(f1*100) == (int)(f2*100)) ? true : false;
+}
+
+namespace ovutils = overlay::utils;
+namespace overlay {
+
+bool MdpCtrl::init(const int& dpy) {
+    int fbnum = Overlay::getFbForDpy(dpy);
+    if( fbnum < 0 ) {
+        ALOGE("%s: Invalid FB for the display: %d",__FUNCTION__, dpy);
+        return false;
+    }
+
+    // FD init
+    if(!utils::openDev(mFd, fbnum,
+                Res::fbPath, O_RDWR)){
+        ALOGE("Ctrl failed to init fbnum=%d", fbnum);
+        return false;
+    }
+    mDpy = dpy;
+    return true;
+}
+
+void MdpCtrl::reset() {
+    utils::memset0(mOVInfo);
+    mOVInfo.id = MSMFB_NEW_REQUEST;
+    mOrientation = utils::OVERLAY_TRANSFORM_0;
+    mDpy = 0;
+#ifdef USES_POST_PROCESSING
+    memset(&mParams, 0, sizeof(struct compute_params));
+    mParams.params.conv_params.order = hsic_order_hsc_i;
+    mParams.params.conv_params.interface = interface_rec601;
+    mParams.params.conv_params.cc_matrix[0][0] = 1;
+    mParams.params.conv_params.cc_matrix[1][1] = 1;
+    mParams.params.conv_params.cc_matrix[2][2] = 1;
+#endif
+}
+
+bool MdpCtrl::close() {
+    bool result = true;
+    if(MSMFB_NEW_REQUEST != static_cast<int>(mOVInfo.id)) {
+        if(!mdp_wrapper::unsetOverlay(mFd.getFD(), mOVInfo.id)) {
+            ALOGE("MdpCtrl close error in unset");
+            result = false;
+        }
+    }
+#ifdef USES_POST_PROCESSING
+    /* free allocated memory in PP */
+    if (mOVInfo.overlay_pp_cfg.igc_cfg.c0_c1_data)
+            free(mOVInfo.overlay_pp_cfg.igc_cfg.c0_c1_data);
+#endif
+    reset();
+
+    if(!mFd.close()) {
+        result = false;
+    }
+
+    return result;
+}
+
+void MdpCtrl::setSource(const utils::PipeArgs& args) {
+    setSrcWhf(args.whf);
+
+    //TODO These are hardcoded. Can be moved out of setSource.
+    mOVInfo.transp_mask = 0xffffffff;
+
+    //TODO These calls should ideally be a part of setPipeParams API
+    setFlags(args.mdpFlags);
+    setZ(args.zorder);
+    setPlaneAlpha(args.planeAlpha);
+    setBlending(args.blending);
+}
+
+void MdpCtrl::setCrop(const utils::Dim& d) {
+    setSrcRectDim(d);
+}
+
+void MdpCtrl::setColor(const uint32_t color) {
+    mOVInfo.bg_color = color;
+}
+
+void MdpCtrl::setPosition(const overlay::utils::Dim& d) {
+    setDstRectDim(d);
+}
+
+void MdpCtrl::setTransform(const utils::eTransform& orient) {
+    int rot = utils::getMdpOrient(orient);
+    setUserData(rot);
+    mOrientation = static_cast<utils::eTransform>(rot);
+}
+
+void MdpCtrl::setPipeType(const utils::eMdpPipeType& pType){
+    switch((int) pType){
+        case utils::OV_MDP_PIPE_RGB:
+            mOVInfo.pipe_type = PIPE_TYPE_RGB;
+            break;
+        case utils::OV_MDP_PIPE_VG:
+            mOVInfo.pipe_type = PIPE_TYPE_VIG;
+            break;
+        case utils::OV_MDP_PIPE_DMA:
+            mOVInfo.pipe_type = PIPE_TYPE_DMA;
+            break;
+        default:
+            mOVInfo.pipe_type = PIPE_TYPE_AUTO;
+            break;
+    }
+}
+
+void MdpCtrl::doTransform() {
+    setRotationFlags();
+    utils::Whf whf = getSrcWhf();
+    utils::Dim dim = getSrcRectDim();
+    utils::preRotateSource(mOrientation, whf, dim);
+    setSrcWhf(whf);
+    setSrcRectDim(dim);
+}
+
+void MdpCtrl::doDownscale() {
+    if(MDPVersion::getInstance().supportsDecimation()) {
+        utils::getDecimationFactor(mOVInfo.src_rect.w, mOVInfo.src_rect.h,
+                mOVInfo.dst_rect.w, mOVInfo.dst_rect.h, mOVInfo.horz_deci,
+                mOVInfo.vert_deci);
+    }
+}
+
+bool MdpCtrl::set() {
+    int mdpVersion = MDPVersion::getInstance().getMDPVersion();
+    //deferred calcs, so APIs could be called in any order.
+    doTransform();
+    utils::Whf whf = getSrcWhf();
+    if(utils::isYuv(whf.format)) {
+        utils::normalizeCrop(mOVInfo.src_rect.x, mOVInfo.src_rect.w);
+        utils::normalizeCrop(mOVInfo.src_rect.y, mOVInfo.src_rect.h);
+        if(mdpVersion < MDSS_V5) {
+            utils::even_floor(mOVInfo.dst_rect.w);
+            utils::even_floor(mOVInfo.dst_rect.h);
+        } else if (mOVInfo.flags & MDP_DEINTERLACE) {
+            // For interlaced, crop.h should be 4-aligned
+            if (!(mOVInfo.flags & MDP_SOURCE_ROTATED_90) &&
+                (mOVInfo.src_rect.h % 4))
+                mOVInfo.src_rect.h = utils::aligndown(mOVInfo.src_rect.h, 4);
+            // For interlaced, width must be multiple of 4 when rotated 90deg.
+            else if ((mOVInfo.flags & MDP_SOURCE_ROTATED_90) &&
+                (mOVInfo.src_rect.w % 4))
+                mOVInfo.src_rect.w = utils::aligndown(mOVInfo.src_rect.w, 4);
+        }
+    } else {
+        // On 8974 and 8x26, there is a limitation of 1-pixel down-scaling
+        if (mdpVersion >= MDSS_V5) {
+            if(qdutils::MDPVersion::getInstance().is8x74v2() ||
+                    qdutils::MDPVersion::getInstance().is8x26()) {
+                if (mOVInfo.src_rect.w - mOVInfo.dst_rect.w == 1)
+                    mOVInfo.src_rect.w -= 1;
+                if (mOVInfo.src_rect.h - mOVInfo.dst_rect.h == 1)
+                    mOVInfo.src_rect.h -= 1;
+            }
+        }
+    }
+
+    doDownscale();
+    return true;
+}
+
+//Update src format based on rotator's destination format.
+void MdpCtrl::updateSrcFormat(const uint32_t& rotDestFmt) {
+    utils::Whf whf = getSrcWhf();
+    whf.format =  rotDestFmt;
+    setSrcWhf(whf);
+}
+
+void MdpCtrl::dump() const {
+    ALOGE("== Dump MdpCtrl start ==");
+    mFd.dump();
+    mdp_wrapper::dump("mOVInfo", mOVInfo);
+    ALOGE("== Dump MdpCtrl end ==");
+}
+
+void MdpCtrl::getDump(char *buf, size_t len) {
+    ovutils::getDump(buf, len, "Ctrl", mOVInfo);
+}
+
+void MdpData::dump() const {
+    ALOGE("== Dump MdpData start ==");
+    mFd.dump();
+    mdp_wrapper::dump("mOvData", mOvData);
+    ALOGE("== Dump MdpData end ==");
+}
+
+void MdpData::getDump(char *buf, size_t len) {
+    ovutils::getDump(buf, len, "Data", mOvData);
+}
+
+bool MdpCtrl::setVisualParams(const MetaData_t& data) {
+    ALOGD_IF(0, "In %s: data.operation = %d", __FUNCTION__, data.operation);
+
+    // Set Color Space for MDP to configure CSC matrix
+    mOVInfo.color_space = ITU_R_601;
+    if (data.operation & UPDATE_COLOR_SPACE) {
+        mOVInfo.color_space = data.colorSpace;
+    }
+
+#ifdef USES_POST_PROCESSING
+    bool needUpdate = false;
+    /* calculate the data */
+    if (data.operation & PP_PARAM_HSIC) {
+        if (mParams.params.pa_params.hue != data.hsicData.hue) {
+            ALOGD_IF(HSIC_SETTINGS_DEBUG,
+                "Hue has changed from %d to %d",
+                mParams.params.pa_params.hue,data.hsicData.hue);
+            needUpdate = true;
+        }
+
+        if (!isEqual(mParams.params.pa_params.sat,
+            data.hsicData.saturation)) {
+            ALOGD_IF(HSIC_SETTINGS_DEBUG,
+                "Saturation has changed from %f to %f",
+                mParams.params.pa_params.sat,
+                data.hsicData.saturation);
+            needUpdate = true;
+        }
+
+        if (mParams.params.pa_params.intensity != data.hsicData.intensity) {
+            ALOGD_IF(HSIC_SETTINGS_DEBUG,
+                "Intensity has changed from %d to %d",
+                mParams.params.pa_params.intensity,
+                data.hsicData.intensity);
+            needUpdate = true;
+        }
+
+        if (!isEqual(mParams.params.pa_params.contrast,
+            data.hsicData.contrast)) {
+            ALOGD_IF(HSIC_SETTINGS_DEBUG,
+                "Contrast has changed from %f to %f",
+                mParams.params.pa_params.contrast,
+                data.hsicData.contrast);
+            needUpdate = true;
+        }
+
+        if (needUpdate) {
+            mParams.params.pa_params.hue = data.hsicData.hue;
+            mParams.params.pa_params.sat = data.hsicData.saturation;
+            mParams.params.pa_params.intensity = data.hsicData.intensity;
+            mParams.params.pa_params.contrast = data.hsicData.contrast;
+            mParams.params.pa_params.ops = MDP_PP_OPS_WRITE | MDP_PP_OPS_ENABLE;
+            mParams.operation |= PP_OP_PA;
+        }
+    }
+
+    if (data.operation & PP_PARAM_SHARP2) {
+        if (mParams.params.sharp_params.strength != data.Sharp2Data.strength) {
+            needUpdate = true;
+        }
+        if (mParams.params.sharp_params.edge_thr != data.Sharp2Data.edge_thr) {
+            needUpdate = true;
+        }
+        if (mParams.params.sharp_params.smooth_thr !=
+                data.Sharp2Data.smooth_thr) {
+            needUpdate = true;
+        }
+        if (mParams.params.sharp_params.noise_thr !=
+                data.Sharp2Data.noise_thr) {
+            needUpdate = true;
+        }
+
+        if (needUpdate) {
+            mParams.params.sharp_params.strength = data.Sharp2Data.strength;
+            mParams.params.sharp_params.edge_thr = data.Sharp2Data.edge_thr;
+            mParams.params.sharp_params.smooth_thr =
+                data.Sharp2Data.smooth_thr;
+            mParams.params.sharp_params.noise_thr = data.Sharp2Data.noise_thr;
+            mParams.params.sharp_params.ops =
+                MDP_PP_OPS_WRITE | MDP_PP_OPS_ENABLE;
+            mParams.operation |= PP_OP_SHARP;
+        }
+    }
+
+    if (data.operation & PP_PARAM_IGC) {
+        if (mOVInfo.overlay_pp_cfg.igc_cfg.c0_c1_data == NULL){
+            uint32_t *igcData
+                = (uint32_t *)malloc(2 * MAX_IGC_LUT_ENTRIES * sizeof(uint32_t));
+            if (!igcData) {
+                ALOGE("IGC storage allocated failed");
+                return false;
+            }
+            mOVInfo.overlay_pp_cfg.igc_cfg.c0_c1_data = igcData;
+            mOVInfo.overlay_pp_cfg.igc_cfg.c2_data
+                = igcData + MAX_IGC_LUT_ENTRIES;
+        }
+
+        memcpy(mParams.params.igc_lut_params.c0,
+            data.igcData.c0, sizeof(uint16_t) * MAX_IGC_LUT_ENTRIES);
+        memcpy(mParams.params.igc_lut_params.c1,
+            data.igcData.c1, sizeof(uint16_t) * MAX_IGC_LUT_ENTRIES);
+        memcpy(mParams.params.igc_lut_params.c2,
+            data.igcData.c2, sizeof(uint16_t) * MAX_IGC_LUT_ENTRIES);
+
+        mParams.params.igc_lut_params.ops
+            = MDP_PP_OPS_WRITE | MDP_PP_OPS_ENABLE;
+        mParams.operation |= PP_OP_IGC;
+        needUpdate = true;
+    }
+
+    if (data.operation & PP_PARAM_VID_INTFC) {
+        mParams.params.conv_params.interface =
+            (interface_type) data.video_interface;
+        needUpdate = true;
+    }
+
+    if (needUpdate) {
+        display_pp_compute_params(&mParams, &mOVInfo.overlay_pp_cfg);
+    }
+#endif
+    return true;
+}
+
+bool MdpCtrl::validateAndSet(MdpCtrl* mdpCtrlArray[], const int& count,
+        const int& fbFd) {
+    mdp_overlay* ovArray[count];
+    memset(&ovArray, 0, sizeof(ovArray));
+
+    for(int i = 0; i < count; i++) {
+        ovArray[i] = &mdpCtrlArray[i]->mOVInfo;
+    }
+
+    struct mdp_overlay_list list;
+    memset(&list, 0, sizeof(struct mdp_overlay_list));
+    list.num_overlays = count;
+    list.overlay_list = ovArray;
+
+   int (*fnProgramScale)(struct mdp_overlay_list *) =
+        Overlay::getFnProgramScale();
+    if(fnProgramScale) {
+        fnProgramScale(&list);
+    }
+
+    // Error value is based on file errno-base.h
+    // 0 - indicates no error.
+    int errVal = mdp_wrapper::validateAndSet(fbFd, list);
+    if(errVal) {
+        /* No dump for failure due to insufficient resource */
+        if(errVal != E2BIG) {
+            mdp_wrapper::dump("Bad ov dump: ",
+                *list.overlay_list[list.processed_overlays]);
+        }
+        return false;
+    }
+
+    return true;
+}
+
+
+//// MdpData ////////////
+bool MdpData::init(const int& dpy) {
+    int fbnum = Overlay::getFbForDpy(dpy);
+    if( fbnum < 0 ) {
+        ALOGE("%s: Invalid FB for the display: %d",__FUNCTION__, dpy);
+        return false;
+    }
+
+    // FD init
+    if(!utils::openDev(mFd, fbnum, Res::fbPath, O_RDWR)){
+        ALOGE("Ctrl failed to init fbnum=%d", fbnum);
+        return false;
+    }
+    return true;
+}
+
+} // overlay
diff --git a/msm8909/liboverlay/overlayMdp.h b/msm8909/liboverlay/overlayMdp.h
new file mode 100644
index 0000000..d415b9d
--- /dev/null
+++ b/msm8909/liboverlay/overlayMdp.h
@@ -0,0 +1,317 @@
+/*
+* Copyright (C) 2008 The Android Open Source Project
+* Copyright (c) 2010-2013, The Linux Foundation. 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 OVERLAY_MDP_H
+#define OVERLAY_MDP_H
+
+#include <linux/msm_mdp.h>
+
+#include "overlayUtils.h"
+#include "mdpWrapper.h"
+#include "qdMetaData.h"
+#ifdef USES_POST_PROCESSING
+#include "lib-postproc.h"
+#endif
+
+namespace overlay{
+
+/*
+* Mdp Ctrl holds corresponding fd and MDP related struct.
+* It is simple wrapper to MDP services
+* */
+class MdpCtrl {
+public:
+    /* ctor reset */
+    explicit MdpCtrl(const int& dpy);
+    /* dtor close */
+    ~MdpCtrl();
+    /* init underlying device using fbnum for dpy */
+    bool init(const int& dpy);
+    /* unset overlay, reset and close fd */
+    bool close();
+    /* reset and set ov id to -1 / MSMFB_NEW_REQUEST */
+    void reset();
+    /* calls overlay set
+     * Set would always consult last good known ov instance.
+     * Only if it is different, set would actually exectue ioctl.
+     * On a sucess ioctl. last good known ov instance is updated */
+    bool set();
+    /* Sets the source total width, height, format */
+    void setSource(const utils::PipeArgs& pargs);
+    /*
+     * Sets ROI, the unpadded region, for source buffer.
+     * Dim - ROI dimensions.
+     */
+    void setCrop(const utils::Dim& d);
+    /* set color for mdp pipe */
+    void setColor(const uint32_t color);
+    void setTransform(const utils::eTransform& orient);
+    /* given a dim and w/h, set overlay dim */
+    void setPosition(const utils::Dim& dim);
+    /* using user_data, sets/unsets roationvalue in mdp flags */
+    void setRotationFlags();
+    /* Update the src format with rotator's dest*/
+    void updateSrcFormat(const uint32_t& rotDstFormat);
+    /* dump state of the object */
+    void dump() const;
+    /* Return the dump in the specified buffer */
+    void getDump(char *buf, size_t len);
+    /* returns session id */
+    int getPipeId() const;
+    /* returns the fd associated to ctrl*/
+    int getFd() const;
+    /* returns a copy ro dst rect dim */
+    utils::Dim getDstRectDim() const;
+    /* returns a copy to src rect dim */
+    utils::Dim getSrcRectDim() const;
+    /* return pipe priority */
+    uint8_t getPriority() const;
+    /* setVisualParam */
+    bool setVisualParams(const MetaData_t& data);
+    /* sets pipe type RGB/DMA/VG */
+    void setPipeType(const utils::eMdpPipeType& pType);
+
+    static bool validateAndSet(MdpCtrl* mdpCtrlArray[], const int& count,
+            const int& fbFd);
+private:
+    /* Perform transformation calculations */
+    void doTransform();
+    void doDownscale();
+    /* get orient / user_data[0] */
+    int getOrient() const;
+    /* returns flags from mdp structure */
+    int getFlags() const;
+    /* set flags to mdp structure */
+    void setFlags(int f);
+    /* set z order */
+    void setZ(utils::eZorder z);
+    /* return a copy of src whf*/
+    utils::Whf getSrcWhf() const;
+    /* set plane alpha */
+    void setPlaneAlpha(int planeAlpha);
+    /* set blending method */
+    void setBlending(overlay::utils::eBlending blending);
+
+    /* set src whf */
+    void setSrcWhf(const utils::Whf& whf);
+    /* set src/dst rect dim */
+    void setSrcRectDim(const utils::Dim d);
+    void setDstRectDim(const utils::Dim d);
+    /* returns user_data[0]*/
+    int getUserData() const;
+    /* sets user_data[0] */
+    void setUserData(int v);
+
+    utils::eTransform mOrientation; //Holds requested orientation
+    /* Actual overlay mdp structure */
+    mdp_overlay   mOVInfo;
+    /* FD for the mdp fbnum */
+    OvFD          mFd;
+    int mDpy;
+
+#ifdef USES_POST_PROCESSING
+    /* PP Compute Params */
+    struct compute_params mParams;
+#endif
+};
+
+/* MDP data */
+class MdpData {
+public:
+    /* ctor reset data */
+    explicit MdpData(const int& dpy);
+    /* dtor close*/
+    ~MdpData();
+    /* init FD */
+    bool init(const int& dpy);
+    /* memset0 the underlying mdp object */
+    void reset();
+    /* close fd, and reset */
+    bool close();
+    /* set id of mdp data */
+    void setPipeId(int id);
+    /* return ses id of data */
+    int getPipeId() const;
+    /* get underlying fd*/
+    int getFd() const;
+    /* get memory_id */
+    int getSrcMemoryId() const;
+    /* calls wrapper play */
+    bool play(int fd, uint32_t offset);
+    /* dump state of the object */
+    void dump() const;
+    /* Return the dump in the specified buffer */
+    void getDump(char *buf, size_t len);
+
+private:
+
+    /* actual overlay mdp data */
+    msmfb_overlay_data mOvData;
+    /* fd to mdp fbnum */
+    OvFD mFd;
+};
+
+//--------------Inlines---------------------------------
+
+/////   MdpCtrl  //////
+
+inline MdpCtrl::MdpCtrl(const int& dpy) {
+    reset();
+    init(dpy);
+}
+
+inline MdpCtrl::~MdpCtrl() {
+    close();
+}
+
+inline int MdpCtrl::getOrient() const {
+    return getUserData();
+}
+
+inline int MdpCtrl::getPipeId() const {
+    return mOVInfo.id;
+}
+
+inline int MdpCtrl::getFd() const {
+    return mFd.getFD();
+}
+
+inline int MdpCtrl::getFlags() const {
+    return mOVInfo.flags;
+}
+
+inline void MdpCtrl::setFlags(int f) {
+    mOVInfo.flags = f;
+}
+
+inline void MdpCtrl::setZ(overlay::utils::eZorder z) {
+    mOVInfo.z_order = z;
+}
+
+inline void MdpCtrl::setPlaneAlpha(int planeAlpha) {
+    mOVInfo.alpha = planeAlpha;
+}
+
+inline void MdpCtrl::setBlending(overlay::utils::eBlending blending) {
+    switch((int) blending) {
+    case utils::OVERLAY_BLENDING_OPAQUE:
+        mOVInfo.blend_op = BLEND_OP_OPAQUE;
+        break;
+    case utils::OVERLAY_BLENDING_PREMULT:
+        mOVInfo.blend_op = BLEND_OP_PREMULTIPLIED;
+        break;
+    case utils::OVERLAY_BLENDING_COVERAGE:
+    default:
+        mOVInfo.blend_op = BLEND_OP_COVERAGE;
+    }
+}
+
+inline overlay::utils::Whf MdpCtrl::getSrcWhf() const {
+    return utils::Whf(  mOVInfo.src.width,
+                        mOVInfo.src.height,
+                        mOVInfo.src.format);
+}
+
+inline void MdpCtrl::setSrcWhf(const overlay::utils::Whf& whf) {
+    mOVInfo.src.width  = whf.w;
+    mOVInfo.src.height = whf.h;
+    mOVInfo.src.format = whf.format;
+}
+
+inline overlay::utils::Dim MdpCtrl::getSrcRectDim() const {
+    return utils::Dim(  mOVInfo.src_rect.x,
+                        mOVInfo.src_rect.y,
+                        mOVInfo.src_rect.w,
+                        mOVInfo.src_rect.h);
+}
+
+inline void MdpCtrl::setSrcRectDim(const overlay::utils::Dim d) {
+    mOVInfo.src_rect.x = d.x;
+    mOVInfo.src_rect.y = d.y;
+    mOVInfo.src_rect.w = d.w;
+    mOVInfo.src_rect.h = d.h;
+}
+
+inline overlay::utils::Dim MdpCtrl::getDstRectDim() const {
+    return utils::Dim(  mOVInfo.dst_rect.x,
+                        mOVInfo.dst_rect.y,
+                        mOVInfo.dst_rect.w,
+                        mOVInfo.dst_rect.h);
+}
+
+inline void MdpCtrl::setDstRectDim(const overlay::utils::Dim d) {
+    mOVInfo.dst_rect.x = d.x;
+    mOVInfo.dst_rect.y = d.y;
+    mOVInfo.dst_rect.w = d.w;
+    mOVInfo.dst_rect.h = d.h;
+}
+
+inline int MdpCtrl::getUserData() const { return mOVInfo.user_data[0]; }
+
+inline void MdpCtrl::setUserData(int v) { mOVInfo.user_data[0] = v; }
+
+inline void MdpCtrl::setRotationFlags() {
+    const int u = getUserData();
+    if (u & MDP_ROT_90)
+        mOVInfo.flags |= MDP_SOURCE_ROTATED_90;
+}
+
+inline uint8_t MdpCtrl::getPriority() const {
+    return mOVInfo.priority;
+}
+
+///////    MdpData   //////
+
+inline MdpData::MdpData(const int& dpy) {
+    reset();
+    init(dpy);
+}
+
+inline MdpData::~MdpData() { close(); }
+
+inline void MdpData::reset() {
+    overlay::utils::memset0(mOvData);
+    mOvData.data.memory_id = -1;
+}
+
+inline bool MdpData::close() {
+    reset();
+    return mFd.close();
+}
+
+inline int MdpData::getSrcMemoryId() const { return mOvData.data.memory_id; }
+
+inline void MdpData::setPipeId(int id) { mOvData.id = id; }
+
+inline int MdpData::getPipeId() const { return mOvData.id; }
+
+inline int MdpData::getFd() const { return mFd.getFD(); }
+
+inline bool MdpData::play(int fd, uint32_t offset) {
+    mOvData.data.memory_id = fd;
+    mOvData.data.offset = offset;
+    if(!mdp_wrapper::play(mFd.getFD(), mOvData)){
+        ALOGE("MdpData failed to play");
+        dump();
+        return false;
+    }
+    return true;
+}
+
+} // overlay
+
+#endif // OVERLAY_MDP_H
diff --git a/msm8909/liboverlay/overlayMdpRot.cpp b/msm8909/liboverlay/overlayMdpRot.cpp
new file mode 100755
index 0000000..d322897
--- /dev/null
+++ b/msm8909/liboverlay/overlayMdpRot.cpp
@@ -0,0 +1,322 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * Copyright (c) 2010-2014, The Linux Foundation. All rights reserved.
+ * Not a Contribution, Apache license notifications and license are retained
+ * for attribution purposes only.
+ *
+ * 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 <math.h>
+#include "overlayUtils.h"
+#include "overlayRotator.h"
+#include "gr.h"
+
+namespace ovutils = overlay::utils;
+
+namespace overlay {
+
+MdpRot::MdpRot() {
+    reset();
+    init();
+}
+
+MdpRot::~MdpRot() { close(); }
+
+bool MdpRot::enabled() const { return mRotImgInfo.enable; }
+
+void MdpRot::setRotations(uint32_t r) { mRotImgInfo.rotations = (uint8_t)r; }
+
+int MdpRot::getSrcMemId() const {
+    return mRotDataInfo.src.memory_id;
+}
+
+int MdpRot::getDstMemId() const {
+    return mRotDataInfo.dst.memory_id;
+}
+
+uint32_t MdpRot::getSrcOffset() const {
+    return mRotDataInfo.src.offset;
+}
+
+uint32_t MdpRot::getDstOffset() const {
+    return mRotDataInfo.dst.offset;
+}
+
+uint32_t MdpRot::getDstFormat() const {
+    return mRotImgInfo.dst.format;
+}
+
+//Added for completeness. Not expected to be called.
+utils::Whf MdpRot::getDstWhf() const {
+    int alW = 0, alH = 0;
+    int halFormat = ovutils::getHALFormat(mRotImgInfo.dst.format);
+    getBufferSizeAndDimensions(mRotImgInfo.dst.width, mRotImgInfo.dst.height,
+            halFormat, alW, alH);
+    return utils::Whf(alW, alH, mRotImgInfo.dst.format);
+}
+
+//Added for completeness. Not expected to be called.
+utils::Dim MdpRot::getDstDimensions() const {
+    int alW = 0, alH = 0;
+    int halFormat = ovutils::getHALFormat(mRotImgInfo.dst.format);
+    getBufferSizeAndDimensions(mRotImgInfo.dst.width, mRotImgInfo.dst.height,
+            halFormat, alW, alH);
+    return utils::Dim(0, 0, alW, alH);
+}
+
+uint32_t MdpRot::getSessId() const { return mRotImgInfo.session_id; }
+
+void MdpRot::setDownscale(int ds) {
+    if ((utils::ROT_DS_EIGHTH == ds) && (mRotImgInfo.src_rect.h & 0xF)) {
+        // Ensure src_rect.h is a multiple of 16 for 1/8 downscaling.
+        // This is an undocumented MDP Rotator constraint.
+        mRotImgInfo.src_rect.h = utils::aligndown(mRotImgInfo.src_rect.h, 16);
+    }
+    mRotImgInfo.downscale_ratio = ds;
+}
+
+void MdpRot::save() {
+    mLSRotImgInfo = mRotImgInfo;
+}
+
+bool MdpRot::rotConfChanged() const {
+    // 0 means same
+    if(0 == ::memcmp(&mRotImgInfo, &mLSRotImgInfo,
+                sizeof (msm_rotator_img_info))) {
+        return false;
+    }
+    return true;
+}
+
+bool MdpRot::init()
+{
+    if(!mFd.open(Res::rotPath, O_RDWR)){
+        ALOGE("MdpRot failed to init %s", Res::rotPath);
+        return false;
+    }
+    return true;
+}
+
+void MdpRot::setSource(const overlay::utils::Whf& awhf) {
+    utils::Whf whf(awhf);
+    mRotImgInfo.src.format = whf.format;
+
+    mRotImgInfo.src.width = whf.w;
+    mRotImgInfo.src.height = whf.h;
+
+    mRotImgInfo.src_rect.w = whf.w;
+    mRotImgInfo.src_rect.h = whf.h;
+
+    mRotImgInfo.dst.width = whf.w;
+    mRotImgInfo.dst.height = whf.h;
+}
+
+void MdpRot::setCrop(const utils::Dim& /*crop*/) {
+    // NO-OP for non-mdss rotator due to possible h/w limitations
+}
+
+void MdpRot::setFlags(const utils::eMdpFlags& flags) {
+    mRotImgInfo.secure = 0;
+    if(flags & utils::OV_MDP_SECURE_OVERLAY_SESSION)
+        mRotImgInfo.secure = 1;
+}
+
+void MdpRot::setTransform(const utils::eTransform& rot)
+{
+    int r = utils::getMdpOrient(rot);
+    setRotations(r);
+    mOrientation = static_cast<utils::eTransform>(r);
+    ALOGE_IF(DEBUG_OVERLAY, "%s: r=%d", __FUNCTION__, r);
+}
+
+void MdpRot::doTransform() {
+    if(mOrientation & utils::OVERLAY_TRANSFORM_ROT_90)
+        utils::swap(mRotImgInfo.dst.width, mRotImgInfo.dst.height);
+}
+
+bool MdpRot::commit() {
+    doTransform();
+    if(rotConfChanged()) {
+        mRotImgInfo.enable = 1;
+        if(!overlay::mdp_wrapper::startRotator(mFd.getFD(), mRotImgInfo)) {
+            ALOGE("MdpRot commit failed");
+            dump();
+            mRotImgInfo.enable = 0;
+            return false;
+        }
+        mRotDataInfo.session_id = mRotImgInfo.session_id;
+    }
+    return true;
+}
+
+uint32_t MdpRot::calcOutputBufSize() {
+    ovutils::Whf destWhf(mRotImgInfo.dst.width,
+            mRotImgInfo.dst.height, mRotImgInfo.dst.format);
+    return Rotator::calcOutputBufSize(destWhf);
+}
+
+bool MdpRot::open_i(uint32_t numbufs, uint32_t bufsz)
+{
+    OvMem mem;
+
+    OVASSERT(MAP_FAILED == mem.addr(), "MAP failed in open_i");
+
+    if(!mem.open(numbufs, bufsz, mRotImgInfo.secure)){
+        ALOGE("%s: Failed to open", __func__);
+        mem.close();
+        return false;
+    }
+
+    OVASSERT(MAP_FAILED != mem.addr(), "MAP failed");
+    OVASSERT(mem.getFD() != -1, "getFd is -1");
+
+    mRotDataInfo.dst.memory_id = mem.getFD();
+    mRotDataInfo.dst.offset = 0;
+    mMem.mem = mem;
+    return true;
+}
+
+bool MdpRot::close() {
+    bool success = true;
+    if(mFd.valid() && (getSessId() != 0)) {
+        if(!mdp_wrapper::endRotator(mFd.getFD(), getSessId())) {
+            ALOGE("Mdp Rot error endRotator, fd=%d sessId=%u",
+                    mFd.getFD(), getSessId());
+            success = false;
+        }
+    }
+    if (!mFd.close()) {
+        ALOGE("Mdp Rot error closing fd");
+        success = false;
+    }
+    if (!mMem.close()) {
+        ALOGE("Mdp Rot error closing mem");
+        success = false;
+    }
+    reset();
+    return success;
+}
+
+bool MdpRot::remap(uint32_t numbufs) {
+    // if current size changed, remap
+    uint32_t opBufSize = calcOutputBufSize();
+    if(opBufSize == mMem.size()) {
+        ALOGE_IF(DEBUG_OVERLAY, "%s: same size %d", __FUNCTION__, opBufSize);
+        return true;
+    }
+
+    if(!mMem.close()) {
+        ALOGE("%s error in closing prev rot mem", __FUNCTION__);
+        return false;
+    }
+
+    ALOGE_IF(DEBUG_OVERLAY, "%s: size changed - remapping", __FUNCTION__);
+
+    if(!open_i(numbufs, opBufSize)) {
+        ALOGE("%s Error could not open", __FUNCTION__);
+        return false;
+    }
+
+    for (uint32_t i = 0; i < numbufs; ++i) {
+        mMem.mRotOffset[i] = i * opBufSize;
+    }
+
+    return true;
+}
+
+void MdpRot::reset() {
+    ovutils::memset0(mRotImgInfo);
+    ovutils::memset0(mLSRotImgInfo);
+    ovutils::memset0(mRotDataInfo);
+    ovutils::memset0(mMem.mRotOffset);
+    mMem.mCurrIndex = 0;
+    mOrientation = utils::OVERLAY_TRANSFORM_0;
+}
+
+bool MdpRot::queueBuffer(int fd, uint32_t offset) {
+    if(enabled() and (not isRotCached(fd,offset))) {
+        int prev_fd = getSrcMemId();
+        uint32_t prev_offset = getSrcOffset();
+
+        mRotDataInfo.src.memory_id = fd;
+        mRotDataInfo.src.offset = offset;
+
+        if(false == remap(RotMem::ROT_NUM_BUFS)) {
+            ALOGE("%s Remap failed, not queueing", __FUNCTION__);
+            return false;
+        }
+
+        mRotDataInfo.dst.offset =
+                mMem.mRotOffset[mMem.mCurrIndex];
+
+        if(!overlay::mdp_wrapper::rotate(mFd.getFD(), mRotDataInfo)) {
+            ALOGE("MdpRot failed rotate");
+            dump();
+            mRotDataInfo.src.memory_id = prev_fd;
+            mRotDataInfo.src.offset = prev_offset;
+            return false;
+        }
+        save();
+        mMem.mCurrIndex =
+                (mMem.mCurrIndex + 1) % mMem.mem.numBufs();
+    }
+    return true;
+}
+
+void MdpRot::dump() const {
+    ALOGE("== Dump MdpRot start ==");
+    mFd.dump();
+    mMem.mem.dump();
+    mdp_wrapper::dump("mRotImgInfo", mRotImgInfo);
+    mdp_wrapper::dump("mRotDataInfo", mRotDataInfo);
+    ALOGE("== Dump MdpRot end ==");
+}
+
+void MdpRot::getDump(char *buf, size_t len) const {
+    ovutils::getDump(buf, len, "MdpRotCtrl", mRotImgInfo);
+    ovutils::getDump(buf, len, "MdpRotData", mRotDataInfo);
+}
+
+int MdpRot::getDownscaleFactor(const int& src_w, const int& src_h,
+        const int& dst_w, const int& dst_h, const uint32_t& /*mdpFormat*/,
+        const bool& /*isInterlaced*/) {
+    int dscale_factor = utils::ROT_DS_NONE;
+    // We need this check to engage the rotator whenever possible to assist MDP
+    // in performing video downscale.
+    // This saves bandwidth and avoids causing the driver to make too many panel
+    // -mode switches between BLT (writeback) and non-BLT (Direct) modes.
+    // Use-case: Video playback [with downscaling and rotation].
+    if (dst_w && dst_h)
+    {
+        float fDscale =  (float)(src_w * src_h) / (float)(dst_w * dst_h);
+        uint32_t dscale = (int)sqrtf(fDscale);
+
+        if(dscale < 2) {
+            // Down-scale to > 50% of orig.
+            dscale_factor = utils::ROT_DS_NONE;
+        } else if(dscale < 4) {
+            // Down-scale to between > 25% to <= 50% of orig.
+            dscale_factor = utils::ROT_DS_HALF;
+        } else if(dscale < 8) {
+            // Down-scale to between > 12.5% to <= 25% of orig.
+            dscale_factor = utils::ROT_DS_FOURTH;
+        } else {
+            // Down-scale to <= 12.5% of orig.
+            dscale_factor = utils::ROT_DS_EIGHTH;
+        }
+    }
+    return dscale_factor;
+}
+
+} // namespace overlay
diff --git a/msm8909/liboverlay/overlayMdssRot.cpp b/msm8909/liboverlay/overlayMdssRot.cpp
new file mode 100644
index 0000000..87e134a
--- /dev/null
+++ b/msm8909/liboverlay/overlayMdssRot.cpp
@@ -0,0 +1,430 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * Copyright (c) 2010-2014, The Linux Foundation. All rights reserved.
+ * Not a Contribution, Apache license notifications and license are retained
+ * for attribution purposes only.
+ *
+ * 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 <math.h>
+#include "overlayUtils.h"
+#include "overlayRotator.h"
+
+#define DEBUG_MDSS_ROT 0
+
+#ifdef VENUS_COLOR_FORMAT
+#include <media/msm_media_info.h>
+#else
+#define VENUS_BUFFER_SIZE(args...) 0
+#endif
+
+#ifndef MDSS_MDP_ROT_ONLY
+#define MDSS_MDP_ROT_ONLY 0x80
+#endif
+
+#define MDSS_ROT_MASK (MDP_ROT_90 | MDP_FLIP_UD | MDP_FLIP_LR)
+
+namespace ovutils = overlay::utils;
+
+namespace overlay {
+using namespace utils;
+
+MdssRot::MdssRot() {
+    reset();
+    init();
+}
+
+MdssRot::~MdssRot() { close(); }
+
+bool MdssRot::enabled() const { return mEnabled; }
+
+void MdssRot::setRotations(uint32_t flags) { mRotInfo.flags |= flags; }
+
+int MdssRot::getSrcMemId() const {
+    return mRotData.data.memory_id;
+}
+
+int MdssRot::getDstMemId() const {
+    return mRotData.dst_data.memory_id;
+}
+
+uint32_t MdssRot::getSrcOffset() const {
+    return mRotData.data.offset;
+}
+
+uint32_t MdssRot::getDstOffset() const {
+    return mRotData.dst_data.offset;
+}
+
+uint32_t MdssRot::getDstFormat() const {
+    //For mdss src and dst formats are same
+    return mRotInfo.src.format;
+}
+
+utils::Whf MdssRot::getDstWhf() const {
+    //For Mdss dst_rect itself represents buffer dimensions. We ignore actual
+    //aligned values during buffer allocation. Also the driver overwrites the
+    //src.format field if destination format is different.
+    //This implementation detail makes it possible to retrieve w,h even before
+    //buffer allocation, which happens in queueBuffer.
+    return utils::Whf(mRotInfo.dst_rect.w, mRotInfo.dst_rect.h,
+            mRotInfo.src.format);
+}
+
+utils::Dim MdssRot::getDstDimensions() const {
+    return utils::Dim(mRotInfo.dst_rect.x, mRotInfo.dst_rect.y,
+            mRotInfo.dst_rect.w, mRotInfo.dst_rect.h);
+}
+
+uint32_t MdssRot::getSessId() const { return mRotInfo.id; }
+
+void MdssRot::save() {
+    mLSRotInfo = mRotInfo;
+}
+
+bool MdssRot::rotConfChanged() const {
+    // 0 means same
+    if(0 == ::memcmp(&mRotInfo, &mLSRotInfo,
+                     sizeof (mdp_overlay))) {
+        return false;
+    }
+    return true;
+}
+
+bool MdssRot::init() {
+    if(!utils::openDev(mFd, 0, Res::fbPath, O_RDWR)) {
+        ALOGE("MdssRot failed to init fb0");
+        return false;
+    }
+    return true;
+}
+
+void MdssRot::setSource(const overlay::utils::Whf& awhf) {
+    utils::Whf whf(awhf);
+
+    mRotInfo.src.format = whf.format;
+    mRotInfo.src.width = whf.w;
+    mRotInfo.src.height = whf.h;
+}
+
+void MdssRot::setCrop(const utils::Dim& crop) {
+    mRotInfo.src_rect.x = crop.x;
+    mRotInfo.src_rect.y = crop.y;
+    mRotInfo.src_rect.w = crop.w;
+    mRotInfo.src_rect.h = crop.h;
+}
+
+void MdssRot::setDownscale(int downscale) {
+    mDownscale = downscale;
+}
+
+void MdssRot::setFlags(const utils::eMdpFlags& flags) {
+    mRotInfo.flags = flags;
+}
+
+void MdssRot::setTransform(const utils::eTransform& rot)
+{
+    // reset rotation flags to avoid stale orientation values
+    mRotInfo.flags &= ~MDSS_ROT_MASK;
+    int flags = utils::getMdpOrient(rot);
+    if (flags != -1)
+        setRotations(flags);
+    mOrientation = static_cast<utils::eTransform>(flags);
+    ALOGE_IF(DEBUG_OVERLAY, "%s: rot=%d", __FUNCTION__, flags);
+}
+
+void MdssRot::doTransform() {
+    mRotInfo.flags |= mOrientation;
+    if(mOrientation & utils::OVERLAY_TRANSFORM_ROT_90)
+        utils::swap(mRotInfo.dst_rect.w, mRotInfo.dst_rect.h);
+}
+
+bool MdssRot::commit() {
+    Dim adjCrop(mRotInfo.src_rect.x,mRotInfo.src_rect.y,
+            mRotInfo.src_rect.w,mRotInfo.src_rect.h);
+    adjCrop = getFormatAdjustedCrop(adjCrop, mRotInfo.src.format,
+            mRotInfo.flags & utils::OV_MDP_DEINTERLACE);
+    adjCrop = getDownscaleAdjustedCrop(adjCrop, mDownscale);
+
+    mRotInfo.src_rect.x = adjCrop.x;
+    mRotInfo.src_rect.y = adjCrop.y;
+    mRotInfo.src_rect.w = adjCrop.w;
+    mRotInfo.src_rect.h = adjCrop.h;
+
+    mRotInfo.dst_rect.x = 0;
+    mRotInfo.dst_rect.y = 0;
+    mRotInfo.dst_rect.w = mDownscale ?
+            mRotInfo.src_rect.w / mDownscale : mRotInfo.src_rect.w;
+    mRotInfo.dst_rect.h = mDownscale ?
+            mRotInfo.src_rect.h / mDownscale : mRotInfo.src_rect.h;
+    //Clear for next round
+    mDownscale = 0;
+
+    doTransform();
+
+    mRotInfo.flags |= MDSS_MDP_ROT_ONLY;
+    mEnabled = true;
+    if(!overlay::mdp_wrapper::setOverlay(mFd.getFD(), mRotInfo)) {
+        ALOGE("MdssRot commit failed!");
+        dump();
+        return (mEnabled = false);
+    }
+    mRotData.id = mRotInfo.id;
+    return true;
+}
+
+bool MdssRot::queueBuffer(int fd, uint32_t offset) {
+    if(enabled() and (not isRotCached(fd,offset))) {
+        int prev_fd = getSrcMemId();
+        uint32_t prev_offset = getSrcOffset();
+
+        mRotData.data.memory_id = fd;
+        mRotData.data.offset = offset;
+
+        if(false == remap(RotMem::ROT_NUM_BUFS)) {
+            ALOGE("%s Remap failed, not queuing", __FUNCTION__);
+            return false;
+        }
+
+        mRotData.dst_data.offset =
+                mMem.mRotOffset[mMem.mCurrIndex];
+
+        if(!overlay::mdp_wrapper::play(mFd.getFD(), mRotData)) {
+            ALOGE("MdssRot play failed!");
+            dump();
+            mRotData.data.memory_id = prev_fd;
+            mRotData.data.offset = prev_offset;
+            return false;
+        }
+        save();
+        mMem.mCurrIndex =
+                (mMem.mCurrIndex + 1) % mMem.mem.numBufs();
+    }
+    return true;
+}
+
+bool MdssRot::open_i(uint32_t numbufs, uint32_t bufsz)
+{
+    OvMem mem;
+    OVASSERT(MAP_FAILED == mem.addr(), "MAP failed in open_i");
+    bool isSecure = mRotInfo.flags & utils::OV_MDP_SECURE_OVERLAY_SESSION;
+
+    if(!mem.open(numbufs, bufsz, isSecure)){
+        ALOGE("%s: Failed to open", __func__);
+        mem.close();
+        return false;
+    }
+
+    OVASSERT(MAP_FAILED != mem.addr(), "MAP failed");
+    OVASSERT(mem.getFD() != -1, "getFd is -1");
+
+    mRotData.dst_data.memory_id = mem.getFD();
+    mRotData.dst_data.offset = 0;
+    mMem.mem = mem;
+    return true;
+}
+
+bool MdssRot::remap(uint32_t numbufs) {
+    // Calculate the size based on rotator's dst format, w and h.
+    uint32_t opBufSize = calcOutputBufSize();
+    // If current size changed, remap
+    if(opBufSize == mMem.size()) {
+        ALOGE_IF(DEBUG_OVERLAY, "%s: same size %d", __FUNCTION__, opBufSize);
+        return true;
+    }
+
+    ALOGE_IF(DEBUG_OVERLAY, "%s: size changed - remapping", __FUNCTION__);
+
+    if(!mMem.close()) {
+        ALOGE("%s error in closing prev rot mem", __FUNCTION__);
+        return false;
+    }
+
+    if(!open_i(numbufs, opBufSize)) {
+        ALOGE("%s Error could not open", __FUNCTION__);
+        return false;
+    }
+
+    for (uint32_t i = 0; i < numbufs; ++i) {
+        mMem.mRotOffset[i] = i * opBufSize;
+    }
+
+    return true;
+}
+
+bool MdssRot::close() {
+    bool success = true;
+    if(mFd.valid() && (getSessId() != (uint32_t) MSMFB_NEW_REQUEST)) {
+        if(!mdp_wrapper::unsetOverlay(mFd.getFD(), getSessId())) {
+            ALOGE("MdssRot::close unsetOverlay failed, fd=%d sessId=%d",
+                  mFd.getFD(), getSessId());
+            success = false;
+        }
+    }
+
+    if (!mFd.close()) {
+        ALOGE("Mdss Rot error closing fd");
+        success = false;
+    }
+    if (!mMem.close()) {
+        ALOGE("Mdss Rot error closing mem");
+        success = false;
+    }
+    reset();
+    return success;
+}
+
+void MdssRot::reset() {
+    ovutils::memset0(mRotInfo);
+    ovutils::memset0(mLSRotInfo);
+    ovutils::memset0(mRotData);
+    mRotData.data.memory_id = -1;
+    mRotInfo.id = MSMFB_NEW_REQUEST;
+    ovutils::memset0(mMem.mRotOffset);
+    mMem.mCurrIndex = 0;
+    mOrientation = utils::OVERLAY_TRANSFORM_0;
+    mDownscale = 0;
+}
+
+void MdssRot::dump() const {
+    ALOGE("== Dump MdssRot start ==");
+    mFd.dump();
+    mMem.mem.dump();
+    mdp_wrapper::dump("mRotInfo", mRotInfo);
+    mdp_wrapper::dump("mRotData", mRotData);
+    ALOGE("== Dump MdssRot end ==");
+}
+
+uint32_t MdssRot::calcOutputBufSize() {
+    uint32_t opBufSize = 0;
+    ovutils::Whf destWhf(mRotInfo.dst_rect.w, mRotInfo.dst_rect.h,
+            mRotInfo.src.format); //mdss src and dst formats are same.
+
+    if (mRotInfo.flags & ovutils::OV_MDSS_MDP_BWC_EN) {
+        opBufSize = calcCompressedBufSize(destWhf);
+    } else {
+        opBufSize = Rotator::calcOutputBufSize(destWhf);
+    }
+
+    return opBufSize;
+}
+
+void MdssRot::getDump(char *buf, size_t len) const {
+    ovutils::getDump(buf, len, "MdssRotCtrl", mRotInfo);
+    ovutils::getDump(buf, len, "MdssRotData", mRotData);
+}
+
+// Calculate the compressed o/p buffer size for BWC
+uint32_t MdssRot::calcCompressedBufSize(const ovutils::Whf& destWhf) {
+    uint32_t bufSize = 0;
+    //Worst case alignments
+    int aWidth = ovutils::align(destWhf.w, 64);
+    int aHeight = ovutils::align(destWhf.h, 4);
+    /*
+       Format           |   RAU size (width x height)
+       ----------------------------------------------
+       ARGB             |       32 pixel x 4 line
+       RGB888           |       32 pixel x 4 line
+       Y (Luma)         |       64 pixel x 4 line
+       CRCB 420         |       32 pixel x 2 line
+       CRCB 422 H2V1    |       32 pixel x 4 line
+       CRCB 422 H1V2    |       64 pixel x 2 line
+
+       Metadata requirements:-
+       1 byte meta data for every 8 RAUs
+       2 byte meta data per RAU
+     */
+
+    //These blocks attempt to allocate for the worst case in each of the
+    //respective format classes, yuv/rgb. The table above is for reference
+    if(utils::isYuv(destWhf.format)) {
+        int yRauCount = aWidth / 64; //Y
+        int cRauCount = aWidth / 32; //C
+        int yStride = (64 * 4 * yRauCount) + alignup(yRauCount, 8) / 8;
+        int cStride = ((32 * 2 * cRauCount) + alignup(cRauCount, 8) / 8) * 2;
+        int yStrideOffset = (aHeight / 4);
+        int cStrideOffset = (aHeight / 2);
+        bufSize = (yStride * yStrideOffset + cStride * cStrideOffset) +
+                (yRauCount * yStrideOffset * 2) +
+                (cRauCount * cStrideOffset * 2) * 2;
+        ALOGD_IF(DEBUG_MDSS_ROT, "%s:YUV Y RAU Count = %d C RAU Count = %d",
+                __FUNCTION__, yRauCount, cRauCount);
+    } else {
+        int rauCount = aWidth / 32;
+        //Single plane
+        int stride = (32 * 4 * rauCount) + alignup(rauCount, 8) / 8;
+        int strideOffset = (aHeight / 4);
+        bufSize = (stride * strideOffset * 4 /*bpp*/) +
+            (rauCount * strideOffset * 2);
+        ALOGD_IF(DEBUG_MDSS_ROT, "%s:RGB RAU count = %d", __FUNCTION__,
+                rauCount);
+    }
+
+    ALOGD_IF(DEBUG_MDSS_ROT, "%s: aligned width = %d, aligned height = %d "
+            "Buf Size = %d", __FUNCTION__, aWidth, aHeight, bufSize);
+
+    return bufSize;
+}
+
+int MdssRot::getDownscaleFactor(const int& srcW, const int& srcH,
+        const int& dstW, const int& dstH, const uint32_t& mdpFormat,
+        const bool& isInterlaced) {
+    if(not srcW or not srcH or not dstW or not dstH or isInterlaced) return 0;
+
+    Dim crop(0, 0, srcW, srcH);
+    Dim adjCrop = getFormatAdjustedCrop(crop, mdpFormat,
+            false /*isInterlaced */);
+
+    uint32_t downscale = min((adjCrop.w / dstW), (adjCrop.h / dstH));
+    //Reduced to a power of 2
+    downscale = (uint32_t) powf(2.0f, floorf(log2f((float)downscale)));
+
+    if(downscale < 2 or downscale > 32) return 0;
+
+    //Allow only 1 line or pixel to be chopped off since the source needs to
+    //be aligned to downscale. Progressively try with smaller downscale to see
+    //if we can satisfy the threshold
+    //For YUV the loop shouldnt be needed, unless in exceptional cases
+    Dim dsAdjCrop = getDownscaleAdjustedCrop(adjCrop, downscale);
+    while(downscale > 2 and (adjCrop.w > dsAdjCrop.w or
+            adjCrop.h > dsAdjCrop.h)) {
+        downscale /= 2;
+        dsAdjCrop = getDownscaleAdjustedCrop(adjCrop, downscale);
+    }
+
+    if(not dsAdjCrop.w or not dsAdjCrop.h) return 0;
+    return downscale;
+}
+
+Dim MdssRot::getFormatAdjustedCrop(const Dim& crop,
+            const uint32_t& mdpFormat, const bool& isInterlaced) {
+    Dim adjCrop = crop;
+    if (isYuv(mdpFormat)) {
+        normalizeCrop(adjCrop.x, adjCrop.w);
+        normalizeCrop(adjCrop.y, adjCrop.h);
+        // For interlaced, crop.h should be 4-aligned
+        if (isInterlaced and (adjCrop.h % 4))
+            adjCrop.h = aligndown(adjCrop.h, 4);
+    }
+    return adjCrop;
+}
+
+Dim MdssRot::getDownscaleAdjustedCrop(const Dim& crop,
+        const uint32_t& downscale) {
+    uint32_t alignedSrcW = aligndown(crop.w, downscale * 2);
+    uint32_t alignedSrcH = aligndown(crop.h, downscale * 2);
+    return Dim(crop.x, crop.y, alignedSrcW, alignedSrcH);
+}
+
+} // namespace overlay
diff --git a/msm8909/liboverlay/overlayMem.h b/msm8909/liboverlay/overlayMem.h
new file mode 100644
index 0000000..f0a1922
--- /dev/null
+++ b/msm8909/liboverlay/overlayMem.h
@@ -0,0 +1,222 @@
+/*
+* Copyright (c) 2011, The Linux Foundation. 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 The Linux Foundation 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 OVERLAY_MEM_H
+#define OVERLAY_MEM_H
+
+#include <sys/mman.h>
+#include <fcntl.h>
+#include <alloc_controller.h>
+#include <memalloc.h>
+
+#include "gralloc_priv.h"
+#include "overlayUtils.h"
+#define SIZE_1M 0x00100000
+
+namespace overlay {
+
+/*
+* Holds base address, offset and the fd
+* */
+class OvMem {
+public:
+    /* ctor init*/
+    explicit OvMem();
+
+    /* dtor DO NOT call close so it can be copied */
+    ~OvMem();
+
+    /* Use libgralloc to retrieve fd, base addr, alloc type */
+    bool open(uint32_t numbufs,
+            uint32_t bufSz, bool isSecure);
+
+    /* close fd. assign base address to invalid*/
+    bool close();
+
+    /* return underlying fd */
+    int getFD() const;
+
+    /* return true if fd is valid and base address is valid */
+    bool valid() const;
+
+    /* dump the state of the object */
+    void dump() const;
+
+    /* return underlying address */
+    void* addr() const;
+
+    /* return underlying offset */
+    uint32_t bufSz() const;
+
+    /* return number of bufs */
+    uint32_t numBufs() const ;
+
+private:
+    /* actual os fd */
+    int mFd;
+
+    /* points to base addr (mmap)*/
+    void* mBaseAddr;
+
+    /* allocated buffer type determined by gralloc (ashmem, ion, etc) */
+    int mAllocType;
+
+    /* holds buf size sent down by the client */
+    uint32_t mBufSz;
+
+    /* num of bufs */
+    uint32_t mNumBuffers;
+
+    /* gralloc alloc controller */
+    gralloc::IAllocController* mAlloc;
+
+    /*Holds the aligned buffer size used for actual allocation*/
+    uint32_t mBufSzAligned;
+};
+
+//-------------------Inlines-----------------------------------
+
+using gralloc::IMemAlloc;
+using gralloc::alloc_data;
+
+inline OvMem::OvMem() {
+    mFd = -1;
+    mBaseAddr = MAP_FAILED;
+    mAllocType = 0;
+    mBufSz = 0;
+    mNumBuffers = 0;
+    mAlloc = gralloc::IAllocController::getInstance();
+}
+
+inline OvMem::~OvMem() { }
+
+inline bool OvMem::open(uint32_t numbufs,
+        uint32_t bufSz, bool isSecure)
+{
+    alloc_data data;
+    int allocFlags = GRALLOC_USAGE_PRIVATE_IOMMU_HEAP;
+    int err = 0;
+    OVASSERT(numbufs && bufSz, "numbufs=%d bufSz=%d", numbufs, bufSz);
+    mBufSz = bufSz;
+
+    if(isSecure) {
+        allocFlags = GRALLOC_USAGE_PRIVATE_MM_HEAP;
+        allocFlags |= GRALLOC_USAGE_PROTECTED;
+        mBufSzAligned = utils::align(bufSz, SIZE_1M);
+        data.align = SIZE_1M;
+    } else {
+        mBufSzAligned = bufSz;
+        data.align = getpagesize();
+    }
+
+    // Allocate uncached rotator buffers
+    allocFlags |= GRALLOC_USAGE_PRIVATE_UNCACHED;
+
+    mNumBuffers = numbufs;
+
+    data.base = 0;
+    data.fd = -1;
+    data.offset = 0;
+    data.size = mBufSzAligned * mNumBuffers;
+    data.uncached = true;
+
+    err = mAlloc->allocate(data, allocFlags);
+    if (err != 0) {
+        ALOGE("OvMem: Error allocating memory");
+        return false;
+    }
+
+    mFd = data.fd;
+    mBaseAddr = data.base;
+    mAllocType = data.allocType;
+
+    return true;
+}
+
+inline bool OvMem::close()
+{
+    int ret = 0;
+
+    if(!valid()) {
+        return true;
+    }
+
+    IMemAlloc* memalloc = mAlloc->getAllocator(mAllocType);
+    ret = memalloc->free_buffer(mBaseAddr, mBufSzAligned * mNumBuffers, 0, mFd);
+    if (ret != 0) {
+        ALOGE("OvMem: error freeing buffer");
+        return false;
+    }
+
+    mFd = -1;
+    mBaseAddr = MAP_FAILED;
+    mAllocType = 0;
+    mBufSz = 0;
+    mBufSzAligned = 0;
+    mNumBuffers = 0;
+    return true;
+}
+
+inline bool OvMem::valid() const
+{
+    return (mFd != -1) && (mBaseAddr != MAP_FAILED);
+}
+
+inline int OvMem::getFD() const
+{
+    return mFd;
+}
+
+inline void* OvMem::addr() const
+{
+    return mBaseAddr;
+}
+
+inline uint32_t OvMem::bufSz() const
+{
+    return mBufSz;
+}
+
+inline uint32_t OvMem::numBufs() const
+{
+    return mNumBuffers;
+}
+
+inline void OvMem::dump() const
+{
+    ALOGE("== Dump OvMem start ==");
+    ALOGE("fd=%d addr=%p type=%d bufsz=%u AlignedBufSz=%u",
+           mFd, mBaseAddr, mAllocType, mBufSz, mBufSzAligned);
+    ALOGE("== Dump OvMem end ==");
+}
+
+} // overlay
+
+#endif // OVERLAY_MEM_H
diff --git a/msm8909/liboverlay/overlayRotator.cpp b/msm8909/liboverlay/overlayRotator.cpp
new file mode 100644
index 0000000..b55f06a
--- /dev/null
+++ b/msm8909/liboverlay/overlayRotator.cpp
@@ -0,0 +1,242 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * Copyright (c) 2010-2012, The Linux Foundation. All rights reserved.
+ * Not a Contribution, Apache license notifications and license are retained
+ * for attribution purposes only.
+ *
+ * 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 "overlayRotator.h"
+#include "overlayUtils.h"
+#include "mdp_version.h"
+#include "sync/sync.h"
+#include "gr.h"
+
+namespace ovutils = overlay::utils;
+
+namespace overlay {
+
+//============Rotator=========================
+
+Rotator::Rotator() {
+    char property[PROPERTY_VALUE_MAX];
+    mRotCacheDisabled = false;
+    if((property_get("debug.rotcache.disable", property, NULL) > 0) &&
+       (!strncmp(property, "1", PROPERTY_VALUE_MAX ) ||
+        (!strncasecmp(property,"true", PROPERTY_VALUE_MAX )))) {
+        /* Used in debugging to turnoff rotator caching */
+        mRotCacheDisabled = true;
+    }
+}
+
+Rotator::~Rotator() {}
+
+Rotator* Rotator::getRotator() {
+    int type = getRotatorHwType();
+    if(type == TYPE_MDP) {
+        return new MdpRot(); //will do reset
+    } else if(type == TYPE_MDSS) {
+        return new MdssRot();
+    } else {
+        ALOGE("%s Unknown h/w type %d", __FUNCTION__, type);
+        return NULL;
+    }
+}
+
+int Rotator::getDownscaleFactor(const int& srcW, const int& srcH,
+        const int& dstW, const int& dstH, const uint32_t& mdpFormat,
+        const bool& isInterlaced) {
+    if(getRotatorHwType() == TYPE_MDSS) {
+        return MdssRot::getDownscaleFactor(srcW, srcH, dstW, dstH,
+                mdpFormat, isInterlaced);
+    }
+    return MdpRot::getDownscaleFactor(srcW, srcH, dstW, dstH,
+            mdpFormat, isInterlaced);
+}
+
+uint32_t Rotator::calcOutputBufSize(const utils::Whf& destWhf) {
+    //dummy aligned w & h.
+    int alW = 0, alH = 0;
+    int halFormat = ovutils::getHALFormat(destWhf.format);
+    //A call into gralloc/memalloc
+    return getBufferSizeAndDimensions(
+            destWhf.w, destWhf.h, halFormat, alW, alH);
+}
+
+int Rotator::getRotatorHwType() {
+    int mdpVersion = qdutils::MDPVersion::getInstance().getMDPVersion();
+    if (mdpVersion == qdutils::MDSS_V5)
+        return TYPE_MDSS;
+    return TYPE_MDP;
+}
+
+bool Rotator::isRotCached(int fd, uint32_t offset) const {
+    if(mRotCacheDisabled or rotConfChanged() or rotDataChanged(fd,offset))
+        return false;
+    return true;
+}
+
+bool Rotator::rotDataChanged(int fd, uint32_t offset) const {
+    /* fd and offset are the attributes of the current rotator input buffer.
+     * At this instance, getSrcMemId() and getSrcOffset() return the
+     * attributes of the previous rotator input buffer */
+    if( (fd == getSrcMemId()) and (offset == getSrcOffset()) )
+        return false;
+    return true;
+}
+
+//============RotMem=========================
+
+bool RotMem::close() {
+    bool ret = true;
+    if(valid()) {
+        if(mem.close() == false) {
+            ALOGE("%s error in closing rot mem", __FUNCTION__);
+            ret = false;
+        }
+    }
+    return ret;
+}
+
+RotMem::RotMem() : mCurrIndex(0) {
+    utils::memset0(mRotOffset);
+    for(int i = 0; i < ROT_NUM_BUFS; i++) {
+        mRelFence[i] = -1;
+    }
+}
+
+RotMem::~RotMem() {
+    for(int i = 0; i < ROT_NUM_BUFS; i++) {
+        ::close(mRelFence[i]);
+        mRelFence[i] = -1;
+    }
+}
+
+void RotMem::setCurrBufReleaseFd(const int& fence) {
+    int ret = 0;
+
+    if(mRelFence[mCurrIndex] >= 0) {
+        //Wait for previous usage of this buffer to be over.
+        //Can happen if rotation takes > vsync and a fast producer. i.e queue
+        //happens in subsequent vsyncs either because content is 60fps or
+        //because the producer is hasty sometimes.
+        ret = sync_wait(mRelFence[mCurrIndex], 1000);
+        if(ret < 0) {
+            ALOGE("%s: sync_wait error!! error no = %d err str = %s",
+                __FUNCTION__, errno, strerror(errno));
+        }
+        ::close(mRelFence[mCurrIndex]);
+    }
+    mRelFence[mCurrIndex] = fence;
+}
+
+void RotMem::setPrevBufReleaseFd(const int& fence) {
+    uint32_t numRotBufs = mem.numBufs();
+    uint32_t prevIndex = (mCurrIndex + numRotBufs - 1) % (numRotBufs);
+
+    if(mRelFence[prevIndex] >= 0) {
+        /* No need of any wait as nothing will be written into this
+         * buffer by the rotator (this func is called when rotator is
+         * in cache mode) */
+        ::close(mRelFence[prevIndex]);
+    }
+
+    mRelFence[prevIndex] = fence;
+}
+
+//============RotMgr=========================
+RotMgr * RotMgr::sRotMgr = NULL;
+
+RotMgr* RotMgr::getInstance() {
+    if(sRotMgr == NULL) {
+        sRotMgr = new RotMgr();
+    }
+    return sRotMgr;
+}
+
+RotMgr::RotMgr() {
+    for(int i = 0; i < MAX_ROT_SESS; i++) {
+        mRot[i] = 0;
+    }
+    mUseCount = 0;
+    mRotDevFd = -1;
+}
+
+RotMgr::~RotMgr() {
+    clear();
+}
+
+void RotMgr::configBegin() {
+    //Reset the number of objects used
+    mUseCount = 0;
+}
+
+void RotMgr::configDone() {
+    //Remove the top most unused objects. Videos come and go.
+    for(int i = mUseCount; i < MAX_ROT_SESS; i++) {
+        if(mRot[i]) {
+            delete mRot[i];
+            mRot[i] = 0;
+        }
+    }
+}
+
+Rotator* RotMgr::getNext() {
+    //Return a rot object, creating one if necessary
+    overlay::Rotator *rot = NULL;
+    if(mUseCount >= MAX_ROT_SESS) {
+        ALOGW("%s, MAX rotator sessions reached, request rejected", __func__);
+    } else {
+        if(mRot[mUseCount] == NULL)
+            mRot[mUseCount] = overlay::Rotator::getRotator();
+        rot = mRot[mUseCount++];
+    }
+    return rot;
+}
+
+void RotMgr::clear() {
+    //Brute force obj destruction, helpful in suspend.
+    for(int i = 0; i < MAX_ROT_SESS; i++) {
+        if(mRot[i]) {
+            delete mRot[i];
+            mRot[i] = 0;
+        }
+    }
+    mUseCount = 0;
+    ::close(mRotDevFd);
+    mRotDevFd = -1;
+}
+
+void RotMgr::getDump(char *buf, size_t len) {
+    for(int i = 0; i < MAX_ROT_SESS; i++) {
+        if(mRot[i]) {
+            mRot[i]->getDump(buf, len);
+        }
+    }
+    char str[4] = {'\0'};
+    snprintf(str, 4, "\n");
+    strlcat(buf, str, len);
+}
+
+int RotMgr::getRotDevFd() {
+    if(mRotDevFd < 0 && Rotator::getRotatorHwType() == Rotator::TYPE_MDSS) {
+        mRotDevFd = ::open("/dev/graphics/fb0", O_RDWR, 0);
+        if(mRotDevFd < 0) {
+            ALOGE("%s failed to open fb0", __FUNCTION__);
+        }
+    }
+    return mRotDevFd;
+}
+
+}
diff --git a/msm8909/liboverlay/overlayRotator.h b/msm8909/liboverlay/overlayRotator.h
new file mode 100644
index 0000000..e045b44
--- /dev/null
+++ b/msm8909/liboverlay/overlayRotator.h
@@ -0,0 +1,322 @@
+/*
+* Copyright (c) 2011,2013 The Linux Foundation. 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 The Linux Foundation. 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 OVERlAY_ROTATOR_H
+#define OVERlAY_ROTATOR_H
+
+#include <stdlib.h>
+
+#include "mdpWrapper.h"
+#include "overlayUtils.h"
+#include "overlayMem.h"
+
+namespace overlay {
+
+/*
+   Manages the case where new rotator memory needs to be
+   allocated, before previous is freed, due to resolution change etc. If we make
+   rotator memory to be always max size, irrespctive of source resolution then
+   we don't need this RotMem wrapper. The inner class is sufficient.
+*/
+struct RotMem {
+    // Max rotator buffers
+    enum { ROT_NUM_BUFS = 2 };
+    RotMem();
+    ~RotMem();
+    bool close();
+    bool valid() { return mem.valid(); }
+    uint32_t size() const { return mem.bufSz(); }
+    void setCurrBufReleaseFd(const int& fence);
+    void setPrevBufReleaseFd(const int& fence);
+
+    // rotator data info dst offset
+    uint32_t mRotOffset[ROT_NUM_BUFS];
+    int mRelFence[ROT_NUM_BUFS];
+    // current slot being used
+    uint32_t mCurrIndex;
+    OvMem mem;
+};
+
+class Rotator
+{
+public:
+    enum { TYPE_MDP, TYPE_MDSS };
+    virtual ~Rotator();
+    virtual void setSource(const utils::Whf& wfh) = 0;
+    virtual void setCrop(const utils::Dim& crop) = 0;
+    virtual void setFlags(const utils::eMdpFlags& flags) = 0;
+    virtual void setTransform(const utils::eTransform& rot) = 0;
+    virtual bool commit() = 0;
+    /* return true if the current rotator state is cached */
+    virtual bool isRotCached(int fd, uint32_t offset) const;
+    /* return true if current rotator config is same as the last round*/
+    virtual bool rotConfChanged() const = 0;
+    /* return true if the current rotator input buffer fd and offset
+     * are same as the last round */
+    virtual bool rotDataChanged(int fd, uint32_t offset) const;
+    virtual void setDownscale(int ds) = 0;
+    /* returns the src buffer of the rotator for the previous/current round,
+     * depending on when it is called(before/after the queuebuffer)*/
+    virtual int getSrcMemId() const = 0;
+    //Mem id and offset should be retrieved only after rotator kickoff
+    virtual int getDstMemId() const = 0;
+    virtual uint32_t getSrcOffset() const = 0;
+    virtual uint32_t getDstOffset() const = 0;
+    //Destination width, height, format, position should be retrieved only after
+    //rotator configuration is committed via commit API
+    virtual uint32_t getDstFormat() const = 0;
+    virtual utils::Whf getDstWhf() const = 0;
+    virtual utils::Dim getDstDimensions() const = 0;
+    virtual uint32_t getSessId() const = 0;
+    virtual bool queueBuffer(int fd, uint32_t offset) = 0;
+    virtual void dump() const = 0;
+    virtual void getDump(char *buf, size_t len) const = 0;
+    inline void setCurrBufReleaseFd(const int& fence) {
+        mMem.setCurrBufReleaseFd(fence);
+    }
+    inline void setPrevBufReleaseFd(const int& fence) {
+        mMem.setPrevBufReleaseFd(fence);
+    }
+    static Rotator *getRotator();
+    /* Returns downscale by successfully applying constraints
+     * Returns 0 if target doesnt support rotator downscaling
+     * or if any of the constraints are not met
+     */
+    static int getDownscaleFactor(const int& srcW, const int& srcH,
+            const int& dstW, const int& dstH, const uint32_t& mdpFormat,
+            const bool& isInterlaced);
+
+protected:
+    /* Rotator memory manager */
+    RotMem mMem;
+    Rotator();
+    static uint32_t calcOutputBufSize(const utils::Whf& destWhf);
+
+private:
+    bool mRotCacheDisabled;
+    /*Returns rotator h/w type */
+    static int getRotatorHwType();
+    friend class RotMgr;
+};
+
+/*
+* MDP rot holds MDP's rotation related structures.
+*
+* */
+class MdpRot : public Rotator {
+public:
+    virtual ~MdpRot();
+    virtual void setSource(const utils::Whf& wfh);
+    virtual void setCrop(const utils::Dim& crop);
+    virtual void setFlags(const utils::eMdpFlags& flags);
+    virtual void setTransform(const utils::eTransform& rot);
+    virtual bool commit();
+    virtual bool rotConfChanged() const;
+    virtual void setDownscale(int ds);
+    virtual int getSrcMemId() const;
+    virtual int getDstMemId() const;
+    virtual uint32_t getSrcOffset() const;
+    virtual uint32_t getDstOffset() const;
+    virtual uint32_t getDstFormat() const;
+    virtual utils::Whf getDstWhf() const;
+    virtual utils::Dim getDstDimensions() const;
+    virtual uint32_t getSessId() const;
+    virtual bool queueBuffer(int fd, uint32_t offset);
+    virtual void dump() const;
+    virtual void getDump(char *buf, size_t len) const;
+
+private:
+    explicit MdpRot();
+    bool init();
+    bool close();
+    void setRotations(uint32_t r);
+    bool enabled () const;
+    /* remap rot buffers */
+    bool remap(uint32_t numbufs);
+    bool open_i(uint32_t numbufs, uint32_t bufsz);
+    /* Deferred transform calculations */
+    void doTransform();
+    /* reset underlying data, basically memset 0 */
+    void reset();
+    /* save mRotImgInfo to be last known good config*/
+    void save();
+    /* Calculates the rotator's o/p buffer size post the transform calcs and
+     * knowing the o/p format depending on whether fastYuv is enabled or not */
+    uint32_t calcOutputBufSize();
+
+    /* Applies downscale by taking areas
+     * Returns a log(downscale)
+     * Constraints applied:
+     * - downscale should be a power of 2
+     * - Max downscale is 1/8
+     */
+    static int getDownscaleFactor(const int& srcW, const int& srcH,
+            const int& dstW, const int& dstH, const uint32_t& mdpFormat,
+            const bool& isInterlaced);
+
+    /* rot info*/
+    msm_rotator_img_info mRotImgInfo;
+    /* Last saved rot info*/
+    msm_rotator_img_info mLSRotImgInfo;
+    /* rot data */
+    msm_rotator_data_info mRotDataInfo;
+    /* Orientation */
+    utils::eTransform mOrientation;
+    /* rotator fd */
+    OvFD mFd;
+
+    friend Rotator* Rotator::getRotator();
+    friend int Rotator::getDownscaleFactor(const int& srcW, const int& srcH,
+            const int& dstW, const int& dstH, const uint32_t& mdpFormat,
+            const bool& isInterlaced);
+};
+
+/*
++* MDSS Rot holds MDSS's rotation related structures.
++*
++* */
+class MdssRot : public Rotator {
+public:
+    virtual ~MdssRot();
+    virtual void setSource(const utils::Whf& wfh);
+    virtual void setCrop(const utils::Dim& crop);
+    virtual void setFlags(const utils::eMdpFlags& flags);
+    virtual void setTransform(const utils::eTransform& rot);
+    virtual bool commit();
+    virtual bool rotConfChanged() const;
+    virtual void setDownscale(int ds);
+    virtual int getSrcMemId() const;
+    virtual int getDstMemId() const;
+    virtual uint32_t getSrcOffset() const;
+    virtual uint32_t getDstOffset() const;
+    virtual uint32_t getDstFormat() const;
+    virtual utils::Whf getDstWhf() const;
+    virtual utils::Dim getDstDimensions() const;
+    virtual uint32_t getSessId() const;
+    virtual bool queueBuffer(int fd, uint32_t offset);
+    virtual void dump() const;
+    virtual void getDump(char *buf, size_t len) const;
+
+private:
+    explicit MdssRot();
+    bool init();
+    bool close();
+    void setRotations(uint32_t r);
+    bool enabled () const;
+    /* remap rot buffers */
+    bool remap(uint32_t numbufs);
+    bool open_i(uint32_t numbufs, uint32_t bufsz);
+    /* Deferred transform calculations */
+    void doTransform();
+    /* reset underlying data, basically memset 0 */
+    void reset();
+    /* save mRotInfo to be last known good config*/
+    void save();
+    /* Calculates the rotator's o/p buffer size post the transform calcs and
+     * knowing the o/p format depending on whether fastYuv is enabled or not */
+    uint32_t calcOutputBufSize();
+    // Calculate the compressed o/p buffer size for BWC
+    uint32_t calcCompressedBufSize(const utils::Whf& destWhf);
+
+     /* Caller's responsibility to swap srcW, srcH if there is a 90 transform
+      * Returns actual downscale (not a log value)
+      * Constraints applied:
+      * - downscale should be a power of 2
+      * - Max downscale is 1/32
+      * - Equal downscale is applied in both directions
+      * - {srcW, srcH} mod downscale = 0
+      * - Interlaced content is not supported
+      */
+    static int getDownscaleFactor(const int& srcW, const int& srcH,
+            const int& dstW, const int& dstH, const uint32_t& mdpFormat,
+            const bool& isInterlaced);
+
+    static utils::Dim getFormatAdjustedCrop(const utils::Dim& crop,
+            const uint32_t& mdpFormat, const bool& isInterlaced);
+
+    static utils::Dim getDownscaleAdjustedCrop(const utils::Dim& crop,
+            const uint32_t& downscale);
+
+    /* MdssRot info structure */
+    mdp_overlay mRotInfo;
+    /* Last saved MdssRot info structure*/
+    mdp_overlay mLSRotInfo;
+    /* MdssRot data structure */
+    msmfb_overlay_data mRotData;
+    /* Orientation */
+    utils::eTransform mOrientation;
+    /* rotator fd */
+    OvFD mFd;
+    /* Enable/Disable Mdss Rot*/
+    bool mEnabled;
+    int mDownscale;
+
+    friend Rotator* Rotator::getRotator();
+    friend int Rotator::getDownscaleFactor(const int& srcW, const int& srcH,
+            const int& dstW, const int& dstH, const uint32_t& mdpFormat,
+            const bool& isInterlaced);
+};
+
+// Holder of rotator objects. Manages lifetimes
+class RotMgr {
+public:
+    //Virtually we can support as many rotator sessions as possible, However
+    // more number of rotator sessions leads to performance issues, so
+    // restricting the max rotator session to 4
+    enum { MAX_ROT_SESS = 4 };
+
+    ~RotMgr();
+    void configBegin();
+    void configDone();
+    overlay::Rotator *getNext();
+    void clear(); //Removes all instances
+    //Resets the usage of top count objects, making them available for reuse
+    void markUnusedTop(const uint32_t& count) { mUseCount -= count; }
+    /* Returns rot dump.
+     * Expects a NULL terminated buffer of big enough size.
+     */
+    void getDump(char *buf, size_t len);
+    int getRotDevFd();
+    int getNumActiveSessions() { return mUseCount; }
+
+    static RotMgr *getInstance();
+
+private:
+    RotMgr();
+    static RotMgr *sRotMgr;
+
+    overlay::Rotator *mRot[MAX_ROT_SESS];
+    uint32_t mUseCount;
+    int mRotDevFd;
+};
+
+
+} // overlay
+
+#endif // OVERlAY_ROTATOR_H
diff --git a/msm8909/liboverlay/overlayUtils.cpp b/msm8909/liboverlay/overlayUtils.cpp
new file mode 100644
index 0000000..cbd52ae
--- /dev/null
+++ b/msm8909/liboverlay/overlayUtils.cpp
@@ -0,0 +1,399 @@
+/*
+* Copyright (c) 2011-2014, The Linux Foundation. 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 The Linux Foundation 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.
+*/
+
+#include <stdlib.h>
+#include <math.h>
+#include <utils/Log.h>
+#include <linux/msm_mdp.h>
+#include <cutils/properties.h>
+#include "gralloc_priv.h"
+#include "overlayUtils.h"
+#include "mdpWrapper.h"
+#include "mdp_version.h"
+#include <hardware/hwcomposer_defs.h>
+
+// just a helper static thingy
+namespace {
+struct IOFile {
+    IOFile(const char* s, const char* mode) : fp(0) {
+        fp = ::fopen(s, mode);
+        if(!fp) {
+            ALOGE("Failed open %s", s);
+        }
+    }
+    template <class T>
+            size_t read(T& r, size_t elem) {
+                if(fp) {
+                    return ::fread(&r, sizeof(T), elem, fp);
+                }
+                return 0;
+            }
+    size_t write(const char* s, uint32_t val) {
+        if(fp) {
+            return ::fprintf(fp, s, val);
+        }
+        return 0;
+    }
+    bool valid() const { return fp != 0; }
+    ~IOFile() {
+        if(fp) ::fclose(fp);
+        fp=0;
+    }
+    FILE* fp;
+};
+}
+
+namespace overlay {
+
+//----------From class Res ------------------------------
+const char* const Res::fbPath = "/dev/graphics/fb%u";
+const char* const Res::rotPath = "/dev/msm_rotator";
+//--------------------------------------------------------
+
+
+
+namespace utils {
+
+//--------------------------------------------------------
+//Refer to graphics.h, gralloc_priv.h, msm_mdp.h
+int getMdpFormat(int format) {
+    switch (format) {
+        //From graphics.h
+        case HAL_PIXEL_FORMAT_RGBA_8888 :
+            return MDP_RGBA_8888;
+        case HAL_PIXEL_FORMAT_RGBX_8888:
+            return MDP_RGBX_8888;
+        case HAL_PIXEL_FORMAT_RGB_888:
+            return MDP_RGB_888;
+        case HAL_PIXEL_FORMAT_RGB_565:
+            return MDP_RGB_565;
+        case HAL_PIXEL_FORMAT_BGRA_8888:
+            return MDP_BGRA_8888;
+        case HAL_PIXEL_FORMAT_BGRX_8888:
+            return MDP_BGRX_8888;
+        case HAL_PIXEL_FORMAT_YV12:
+            return MDP_Y_CR_CB_GH2V2;
+        case HAL_PIXEL_FORMAT_YCbCr_422_SP:
+            return MDP_Y_CBCR_H2V1;
+        case HAL_PIXEL_FORMAT_YCrCb_420_SP:
+            return MDP_Y_CRCB_H2V2;
+
+        //From gralloc_priv.h
+        case HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED:
+            return MDP_Y_CBCR_H2V2_TILE;
+        case HAL_PIXEL_FORMAT_YCbCr_420_SP:
+            return MDP_Y_CBCR_H2V2;
+        case HAL_PIXEL_FORMAT_YCrCb_422_SP:
+            return MDP_Y_CRCB_H2V1;
+        case HAL_PIXEL_FORMAT_YCbCr_422_I:
+            return MDP_YCBYCR_H2V1;
+        case HAL_PIXEL_FORMAT_YCrCb_422_I:
+            return MDP_YCRYCB_H2V1;
+        case HAL_PIXEL_FORMAT_YCbCr_444_SP:
+            return MDP_Y_CBCR_H1V1;
+        case HAL_PIXEL_FORMAT_YCrCb_444_SP:
+            return MDP_Y_CRCB_H1V1;
+        case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS:
+        case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:
+            //NV12 encodeable format maps to the venus format on
+            //B-Family targets
+            return MDP_Y_CBCR_H2V2_VENUS;
+        default:
+            //Unsupported by MDP
+            //---graphics.h--------
+            //HAL_PIXEL_FORMAT_RGBA_5551
+            //HAL_PIXEL_FORMAT_RGBA_4444
+            //---gralloc_priv.h-----
+            //HAL_PIXEL_FORMAT_YCrCb_420_SP_ADRENO    = 0x7FA30C01
+            //HAL_PIXEL_FORMAT_R_8                    = 0x10D
+            //HAL_PIXEL_FORMAT_RG_88                  = 0x10E
+            ALOGE("%s: Unsupported HAL format = 0x%x", __func__, format);
+            return -1;
+    }
+    // not reached
+    return -1;
+}
+
+// This function returns corresponding tile format
+// MDSS support following RGB tile formats
+//  32 bit formats
+//  16 bit formats
+int getMdpFormat(int format, bool tileEnabled)
+{
+    if(!tileEnabled) {
+        return getMdpFormat(format);
+    }
+    switch (format) {
+        case HAL_PIXEL_FORMAT_RGBA_8888 :
+            return MDP_RGBA_8888_TILE;
+        case HAL_PIXEL_FORMAT_RGBX_8888:
+            return MDP_RGBX_8888_TILE;
+        case HAL_PIXEL_FORMAT_RGB_565:
+            return MDP_RGB_565_TILE;
+        case HAL_PIXEL_FORMAT_BGRA_8888:
+            return MDP_BGRA_8888_TILE;
+        case HAL_PIXEL_FORMAT_BGRX_8888:
+            return MDP_BGRX_8888_TILE;
+        default:
+            return getMdpFormat(format);
+    }
+}
+
+
+
+//Takes mdp format as input and translates to equivalent HAL format
+//Refer to graphics.h, gralloc_priv.h, msm_mdp.h for formats.
+int getHALFormat(int mdpFormat) {
+    switch (mdpFormat) {
+        //From graphics.h
+        case MDP_RGBA_8888:
+            return HAL_PIXEL_FORMAT_RGBA_8888;
+        case MDP_RGBX_8888:
+            return HAL_PIXEL_FORMAT_RGBX_8888;
+        case MDP_RGB_888:
+            return HAL_PIXEL_FORMAT_RGB_888;
+        case MDP_RGB_565:
+            return HAL_PIXEL_FORMAT_RGB_565;
+        case MDP_BGRA_8888:
+            return HAL_PIXEL_FORMAT_BGRA_8888;
+        case MDP_Y_CR_CB_GH2V2:
+            return HAL_PIXEL_FORMAT_YV12;
+        case MDP_Y_CBCR_H2V1:
+            return HAL_PIXEL_FORMAT_YCbCr_422_SP;
+        case MDP_Y_CRCB_H2V2:
+            return HAL_PIXEL_FORMAT_YCrCb_420_SP;
+
+        //From gralloc_priv.h
+        case MDP_Y_CBCR_H2V2_TILE:
+            return HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED;
+        case MDP_Y_CBCR_H2V2:
+            return HAL_PIXEL_FORMAT_YCbCr_420_SP;
+        case MDP_Y_CRCB_H2V1:
+            return HAL_PIXEL_FORMAT_YCrCb_422_SP;
+        case MDP_YCBYCR_H2V1:
+            return HAL_PIXEL_FORMAT_YCbCr_422_I;
+        case MDP_YCRYCB_H2V1:
+            return HAL_PIXEL_FORMAT_YCrCb_422_I;
+         case MDP_Y_CBCR_H1V1:
+            return HAL_PIXEL_FORMAT_YCbCr_444_SP;
+        case MDP_Y_CRCB_H1V1:
+            return HAL_PIXEL_FORMAT_YCrCb_444_SP;
+        case MDP_Y_CBCR_H2V2_VENUS:
+            return HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS;
+        default:
+            ALOGE("%s: Unsupported MDP format = 0x%x", __func__, mdpFormat);
+            return -1;
+    }
+    // not reached
+    return -1;
+}
+
+int getMdpOrient(eTransform rotation) {
+    int retTrans = 0;
+    bool trans90 = false;
+    int mdpVersion = qdutils::MDPVersion::getInstance().getMDPVersion();
+    bool aFamily = (mdpVersion < qdutils::MDSS_V5);
+
+    ALOGD_IF(DEBUG_OVERLAY, "%s: In rotation = %d", __FUNCTION__, rotation);
+    if(rotation & OVERLAY_TRANSFORM_ROT_90) {
+        retTrans |= MDP_ROT_90;
+        trans90 = true;
+    }
+
+    if(rotation & OVERLAY_TRANSFORM_FLIP_H) {
+        if(trans90 && aFamily) {
+            //Swap for a-family, since its driver does 90 first
+            retTrans |= MDP_FLIP_UD;
+        } else {
+            retTrans |= MDP_FLIP_LR;
+        }
+    }
+
+    if(rotation & OVERLAY_TRANSFORM_FLIP_V) {
+        if(trans90 && aFamily) {
+            //Swap for a-family, since its driver does 90 first
+            retTrans |= MDP_FLIP_LR;
+        } else {
+            retTrans |= MDP_FLIP_UD;
+        }
+    }
+
+    ALOGD_IF(DEBUG_OVERLAY, "%s: Out rotation = %d", __FUNCTION__, retTrans);
+    return retTrans;
+}
+
+void getDecimationFactor(const int& src_w, const int& src_h,
+        const int& dst_w, const int& dst_h, uint8_t& horzDeci,
+        uint8_t& vertDeci) {
+    horzDeci = 0;
+    vertDeci = 0;
+    float horDscale = ceilf((float)src_w / (float)dst_w);
+    float verDscale = ceilf((float)src_h / (float)dst_h);
+    qdutils::MDPVersion& mdpHw = qdutils::MDPVersion::getInstance();
+
+    //Next power of 2, if not already
+    horDscale = powf(2.0f, ceilf(log2f(horDscale)));
+    verDscale = powf(2.0f, ceilf(log2f(verDscale)));
+
+    //Since MDP can do downscale and has better quality, split the task
+    //between decimator and MDP downscale
+    horDscale /= (float)mdpHw.getMaxMDPDownscale();
+    verDscale /= (float)mdpHw.getMaxMDPDownscale();
+
+    if((int)horDscale)
+        horzDeci = (uint8_t)log2f(horDscale);
+
+    if((int)verDscale)
+        vertDeci = (uint8_t)log2f(verDscale);
+
+    if(src_w > (int) mdpHw.getMaxMixerWidth()) {
+        //If the client sends us something > what a layer mixer supports
+        //then it means it doesn't want to use split-pipe but wants us to
+        //decimate. A minimum decimation of 2 will ensure that the width is
+        //always within layer mixer limits.
+        if(horzDeci < 2)
+            horzDeci = 2;
+    }
+}
+
+static inline int compute(const uint32_t& x, const uint32_t& y,
+        const uint32_t& z) {
+    return x - ( y + z );
+}
+
+void preRotateSource(const eTransform& tr, Whf& whf, Dim& srcCrop) {
+    if(tr & OVERLAY_TRANSFORM_FLIP_H) {
+        srcCrop.x = compute(whf.w, srcCrop.x, srcCrop.w);
+    }
+    if(tr & OVERLAY_TRANSFORM_FLIP_V) {
+        srcCrop.y = compute(whf.h, srcCrop.y, srcCrop.h);
+    }
+    if(tr & OVERLAY_TRANSFORM_ROT_90) {
+        int tmp = srcCrop.x;
+        srcCrop.x = compute(whf.h,
+                srcCrop.y,
+                srcCrop.h);
+        srcCrop.y = tmp;
+        swap(whf.w, whf.h);
+        swap(srcCrop.w, srcCrop.h);
+    }
+}
+
+void getDump(char *buf, size_t len, const char *prefix,
+        const mdp_overlay& ov) {
+    char str[256] = {'\0'};
+    snprintf(str, 256,
+            "%s id=%d z=%d alpha=%d mask=%d flags=0x%x H.Deci=%d,"
+            "V.Deci=%d\n",
+            prefix, ov.id, ov.z_order, ov.alpha,
+            ov.transp_mask, ov.flags, ov.horz_deci, ov.vert_deci);
+    strlcat(buf, str, len);
+    getDump(buf, len, "\tsrc", ov.src);
+    getDump(buf, len, "\tsrc_rect", ov.src_rect);
+    getDump(buf, len, "\tdst_rect", ov.dst_rect);
+}
+
+void getDump(char *buf, size_t len, const char *prefix,
+        const msmfb_img& ov) {
+    char str_src[256] = {'\0'};
+    snprintf(str_src, 256,
+            "%s w=%d h=%d format=%d %s\n",
+            prefix, ov.width, ov.height, ov.format,
+            overlay::utils::getFormatString(ov.format));
+    strlcat(buf, str_src, len);
+}
+
+void getDump(char *buf, size_t len, const char *prefix,
+        const mdp_rect& ov) {
+    char str_rect[256] = {'\0'};
+    snprintf(str_rect, 256,
+            "%s x=%d y=%d w=%d h=%d\n",
+            prefix, ov.x, ov.y, ov.w, ov.h);
+    strlcat(buf, str_rect, len);
+}
+
+void getDump(char *buf, size_t len, const char *prefix,
+        const msmfb_overlay_data& ov) {
+    char str[256] = {'\0'};
+    snprintf(str, 256,
+            "%s id=%d\n",
+            prefix, ov.id);
+    strlcat(buf, str, len);
+    getDump(buf, len, "\tdata", ov.data);
+}
+
+void getDump(char *buf, size_t len, const char *prefix,
+        const msmfb_data& ov) {
+    char str_data[256] = {'\0'};
+    snprintf(str_data, 256,
+            "%s offset=%d memid=%d id=%d flags=0x%x\n",
+            prefix, ov.offset, ov.memory_id, ov.id, ov.flags);
+    strlcat(buf, str_data, len);
+}
+
+void getDump(char *buf, size_t len, const char *prefix,
+        const msm_rotator_img_info& rot) {
+    char str[256] = {'\0'};
+    snprintf(str, 256, "%s sessid=%u rot=%d, enable=%d downscale=%d\n",
+            prefix, rot.session_id, rot.rotations, rot.enable,
+            rot.downscale_ratio);
+    strlcat(buf, str, len);
+    getDump(buf, len, "\tsrc", rot.src);
+    getDump(buf, len, "\tdst", rot.dst);
+    getDump(buf, len, "\tsrc_rect", rot.src_rect);
+}
+
+void getDump(char *buf, size_t len, const char *prefix,
+        const msm_rotator_data_info& rot) {
+    char str[256] = {'\0'};
+    snprintf(str, 256,
+            "%s sessid=%u\n",
+            prefix, rot.session_id);
+    strlcat(buf, str, len);
+    getDump(buf, len, "\tsrc", rot.src);
+    getDump(buf, len, "\tdst", rot.dst);
+}
+
+//Helper to even out x,w and y,h pairs
+//x,y are always evened to ceil and w,h are evened to floor
+void normalizeCrop(uint32_t& xy, uint32_t& wh) {
+    if(xy & 1) {
+        even_ceil(xy);
+        if(wh & 1)
+            even_floor(wh);
+        else
+            wh -= 2;
+    } else {
+        even_floor(wh);
+    }
+}
+
+} // utils
+
+} // overlay
diff --git a/msm8909/liboverlay/overlayUtils.h b/msm8909/liboverlay/overlayUtils.h
new file mode 100644
index 0000000..2b8e303
--- /dev/null
+++ b/msm8909/liboverlay/overlayUtils.h
@@ -0,0 +1,683 @@
+/*
+* Copyright (c) 2011-2014, The Linux Foundation. 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 The Linux Foundation 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 OVERLAY_UTILS_H
+#define OVERLAY_UTILS_H
+
+#include <cutils/log.h> // ALOGE, etc
+#include <errno.h>
+#include <fcntl.h> // open, O_RDWR, etc
+#include <hardware/hardware.h>
+#include <hardware/gralloc.h> // buffer_handle_t
+#include <linux/msm_mdp.h> // flags
+#include <linux/msm_rotator.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <utils/Log.h>
+#include "gralloc_priv.h" //for interlace
+
+// Older platforms do not support Venus
+#ifndef VENUS_COLOR_FORMAT
+#define MDP_Y_CBCR_H2V2_VENUS MDP_IMGTYPE_LIMIT
+#endif
+
+/*
+*
+* Collection of utilities functions/structs/enums etc...
+*
+* */
+
+// comment that out if you want to remove asserts
+// or put it as -D in Android.mk. your choice.
+#define OVERLAY_HAS_ASSERT
+
+#ifdef OVERLAY_HAS_ASSERT
+# define OVASSERT(x, ...) if(!(x)) { ALOGE(__VA_ARGS__); abort(); }
+#else
+# define OVASSERT(x, ...) ALOGE_IF(!(x), __VA_ARGS__)
+#endif // OVERLAY_HAS_ASSERT
+
+#define DEBUG_OVERLAY 0
+#define PROFILE_OVERLAY 0
+
+#ifndef MDSS_MDP_RIGHT_MIXER
+#define MDSS_MDP_RIGHT_MIXER 0x100
+#endif
+
+#ifndef MDP_OV_PIPE_FORCE_DMA
+#define MDP_OV_PIPE_FORCE_DMA 0x4000
+#endif
+
+#ifndef MDSS_MDP_DUAL_PIPE
+#define MDSS_MDP_DUAL_PIPE 0x200
+#endif
+
+#define FB_DEVICE_TEMPLATE "/dev/graphics/fb%u"
+
+namespace overlay {
+
+// fwd
+class Overlay;
+class OvFD;
+
+/* helper function to open by using fbnum */
+bool open(OvFD& fd, uint32_t fbnum, const char* const dev,
+    int flags = O_RDWR);
+
+namespace utils {
+struct Whf;
+struct Dim;
+
+inline uint32_t setBit(uint32_t x, uint32_t mask) {
+    return (x | mask);
+}
+
+inline uint32_t clrBit(uint32_t x, uint32_t mask) {
+    return (x & ~mask);
+}
+
+/* Utility class to help avoid copying instances by making the copy ctor
+* and assignment operator private
+*
+* Usage:
+*    class SomeClass : utils::NoCopy {...};
+*/
+class NoCopy {
+protected:
+    NoCopy(){}
+    ~NoCopy() {}
+private:
+    NoCopy(const NoCopy&);
+    const NoCopy& operator=(const NoCopy&);
+};
+
+bool isMdssRotator();
+void normalizeCrop(uint32_t& xy, uint32_t& wh);
+
+template <class Type>
+void swapWidthHeight(Type& width, Type& height);
+
+struct Dim {
+    Dim () : x(0), y(0),
+    w(0), h(0),
+    o(0) {}
+    Dim(uint32_t _x, uint32_t _y, uint32_t _w, uint32_t _h) :
+        x(_x), y(_y),
+        w(_w), h(_h) {}
+    Dim(uint32_t _x, uint32_t _y, uint32_t _w, uint32_t _h, uint32_t _o) :
+        x(_x), y(_y),
+        w(_w), h(_h),
+        o(_o) {}
+    bool check(uint32_t _w, uint32_t _h) const {
+        return (x+w <= _w && y+h <= _h);
+
+    }
+
+    bool operator==(const Dim& d) const {
+        return d.x == x && d.y == y &&
+                d.w == w && d.h == h &&
+                d.o == o;
+    }
+
+    bool operator!=(const Dim& d) const {
+        return !operator==(d);
+    }
+
+    void dump() const;
+    uint32_t x;
+    uint32_t y;
+    uint32_t w;
+    uint32_t h;
+    uint32_t o;
+};
+
+// TODO have Whfz
+
+struct Whf {
+    Whf() : w(0), h(0), format(0), size(0) {}
+    Whf(uint32_t wi, uint32_t he, uint32_t f) :
+        w(wi), h(he), format(f), size(0) {}
+    Whf(uint32_t wi, uint32_t he, uint32_t f, uint32_t s) :
+        w(wi), h(he), format(f), size(s) {}
+    // FIXME not comparing size at the moment
+    bool operator==(const Whf& whf) const {
+        return whf.w == w && whf.h == h &&
+                whf.format == format;
+    }
+    bool operator!=(const Whf& whf) const {
+        return !operator==(whf);
+    }
+    void dump() const;
+    uint32_t w;
+    uint32_t h;
+    uint32_t format;
+    uint32_t size;
+};
+
+enum { MAX_PATH_LEN = 256 };
+
+enum { DEFAULT_PLANE_ALPHA = 0xFF };
+
+/**
+ * Rotator flags: not to be confused with orientation flags.
+ * Usually, you want to open the rotator to make sure it is
+ * ready for business.
+ * */
+ enum eRotFlags {
+    ROT_FLAGS_NONE = 0,
+    //Use rotator for 0 rotation. It is used anyway for others.
+    ROT_0_ENABLED = 1 << 0,
+    //Enable rotator downscale optimization for hardware bugs not handled in
+    //driver. If downscale optimizatation is required,
+    //then rotator will be used even if its 0 rotation case.
+    ROT_DOWNSCALE_ENABLED = 1 << 1,
+    ROT_PREROTATED = 1 << 2,
+};
+
+enum eRotDownscale {
+    ROT_DS_NONE = 0,
+    ROT_DS_HALF = 1,
+    ROT_DS_FOURTH = 2,
+    ROT_DS_EIGHTH = 3,
+};
+
+/*
+ * Various mdp flags like PIPE SHARE, DEINTERLACE etc...
+ * kernel/common/linux/msm_mdp.h
+ * INTERLACE_MASK: hardware/qcom/display/libgralloc/badger/fb_priv.h
+ * */
+enum eMdpFlags {
+    OV_MDP_FLAGS_NONE = 0,
+    OV_MDP_PIPE_SHARE =  MDP_OV_PIPE_SHARE,
+    OV_MDP_PIPE_FORCE_DMA = MDP_OV_PIPE_FORCE_DMA,
+    OV_MDP_DEINTERLACE = MDP_DEINTERLACE,
+    OV_MDP_SECURE_OVERLAY_SESSION = MDP_SECURE_OVERLAY_SESSION,
+    OV_MDP_SECURE_DISPLAY_OVERLAY_SESSION = MDP_SECURE_DISPLAY_OVERLAY_SESSION,
+    OV_MDP_SOURCE_ROTATED_90 = MDP_SOURCE_ROTATED_90,
+    OV_MDP_BACKEND_COMPOSITION = MDP_BACKEND_COMPOSITION,
+    OV_MDP_BLEND_FG_PREMULT = MDP_BLEND_FG_PREMULT,
+    OV_MDP_FLIP_H = MDP_FLIP_LR,
+    OV_MDP_FLIP_V = MDP_FLIP_UD,
+    OV_MDSS_MDP_RIGHT_MIXER = MDSS_MDP_RIGHT_MIXER,
+    OV_MDP_PP_EN = MDP_OVERLAY_PP_CFG_EN,
+    OV_MDSS_MDP_BWC_EN = MDP_BWC_EN,
+    OV_MDSS_MDP_DUAL_PIPE = MDSS_MDP_DUAL_PIPE,
+    OV_MDP_SOLID_FILL = MDP_SOLID_FILL,
+};
+
+enum eZorder {
+    ZORDER_0 = 0,
+    ZORDER_1,
+    ZORDER_2,
+    ZORDER_3,
+    Z_SYSTEM_ALLOC = 0xFFFF
+};
+
+enum eMdpPipeType {
+    OV_MDP_PIPE_RGB = 0,
+    OV_MDP_PIPE_VG,
+    OV_MDP_PIPE_DMA,
+    OV_MDP_PIPE_ANY, //Any
+};
+
+// Identify destination pipes
+// TODO Names useless, replace with int and change all interfaces
+enum eDest {
+    OV_P0 = 0,
+    OV_P1,
+    OV_P2,
+    OV_P3,
+    OV_P4,
+    OV_P5,
+    OV_P6,
+    OV_P7,
+    OV_P8,
+    OV_P9,
+    OV_INVALID,
+    OV_MAX = OV_INVALID,
+};
+
+/* Used when a buffer is split over 2 pipes and sent to display */
+enum {
+    OV_LEFT_SPLIT = 0,
+    OV_RIGHT_SPLIT,
+};
+
+/* values for copybit_set_parameter(OVERLAY_TRANSFORM) */
+enum eTransform {
+    /* No rot */
+    OVERLAY_TRANSFORM_0 = 0x0,
+    /* flip source image horizontally 0x1 */
+    OVERLAY_TRANSFORM_FLIP_H = HAL_TRANSFORM_FLIP_H,
+    /* flip source image vertically 0x2 */
+    OVERLAY_TRANSFORM_FLIP_V = HAL_TRANSFORM_FLIP_V,
+    /* rotate source image 180 degrees
+     * It is basically bit-or-ed  H | V == 0x3 */
+    OVERLAY_TRANSFORM_ROT_180 = HAL_TRANSFORM_ROT_180,
+    /* rotate source image 90 degrees 0x4 */
+    OVERLAY_TRANSFORM_ROT_90 = HAL_TRANSFORM_ROT_90,
+    /* rotate source image 90 degrees and flip horizontally 0x5 */
+    OVERLAY_TRANSFORM_ROT_90_FLIP_H = HAL_TRANSFORM_ROT_90 |
+                                      HAL_TRANSFORM_FLIP_H,
+    /* rotate source image 90 degrees and flip vertically 0x6 */
+    OVERLAY_TRANSFORM_ROT_90_FLIP_V = HAL_TRANSFORM_ROT_90 |
+                                      HAL_TRANSFORM_FLIP_V,
+    /* rotate source image 270 degrees
+     * Basically 180 | 90 == 0x7 */
+    OVERLAY_TRANSFORM_ROT_270 = HAL_TRANSFORM_ROT_270,
+    /* rotate invalid like in Transform.h */
+    OVERLAY_TRANSFORM_INV = 0x80
+};
+
+enum eBlending {
+    OVERLAY_BLENDING_UNDEFINED = 0x0,
+    /* No blending */
+    OVERLAY_BLENDING_OPAQUE,
+    /* src.rgb + dst.rgb*(1-src_alpha) */
+    OVERLAY_BLENDING_PREMULT,
+    /* src.rgb * src_alpha + dst.rgb (1 - src_alpha) */
+    OVERLAY_BLENDING_COVERAGE,
+};
+
+// Used to consolidate pipe params
+struct PipeArgs {
+    PipeArgs() : mdpFlags(OV_MDP_FLAGS_NONE),
+        zorder(Z_SYSTEM_ALLOC),
+        rotFlags(ROT_FLAGS_NONE),
+        planeAlpha(DEFAULT_PLANE_ALPHA),
+        blending(OVERLAY_BLENDING_COVERAGE){
+    }
+
+    PipeArgs(eMdpFlags f, Whf _whf,
+            eZorder z, eRotFlags r,
+            int pA = DEFAULT_PLANE_ALPHA, eBlending b = OVERLAY_BLENDING_COVERAGE) :
+        mdpFlags(f),
+        whf(_whf),
+        zorder(z),
+        rotFlags(r),
+        planeAlpha(pA),
+        blending(b){
+    }
+
+    eMdpFlags mdpFlags; // for mdp_overlay flags
+    Whf whf;
+    eZorder zorder; // stage number
+    eRotFlags rotFlags;
+    int planeAlpha;
+    eBlending blending;
+};
+
+// Cannot use HW_OVERLAY_MAGNIFICATION_LIMIT, since at the time
+// of integration, HW_OVERLAY_MAGNIFICATION_LIMIT was a define
+enum { HW_OV_MAGNIFICATION_LIMIT = 20,
+    HW_OV_MINIFICATION_LIMIT  = 8
+};
+
+inline void setMdpFlags(eMdpFlags& f, eMdpFlags v) {
+    f = static_cast<eMdpFlags>(setBit(f, v));
+}
+
+inline void clearMdpFlags(eMdpFlags& f, eMdpFlags v) {
+    f = static_cast<eMdpFlags>(clrBit(f, v));
+}
+
+enum { FB0, FB1, FB2 };
+
+struct ScreenInfo {
+    ScreenInfo() : mFBWidth(0),
+    mFBHeight(0),
+    mFBbpp(0),
+    mFBystride(0) {}
+    void dump(const char* const s) const;
+    uint32_t mFBWidth;
+    uint32_t mFBHeight;
+    uint32_t mFBbpp;
+    uint32_t mFBystride;
+};
+
+int getMdpFormat(int format);
+int getMdpFormat(int format, bool tileEnabled);
+int getHALFormat(int mdpFormat);
+void getDecimationFactor(const int& src_w, const int& src_h,
+        const int& dst_w, const int& dst_h, uint8_t& horzDeci,
+        uint8_t& vertDeci);
+
+/* flip is upside down and such. V, H flip
+ * rotation is 90, 180 etc
+ * It returns MDP related enum/define that match rot+flip*/
+int getMdpOrient(eTransform rotation);
+const char* getFormatString(int format);
+
+template <class T>
+inline void memset0(T& t) { ::memset(&t, 0, sizeof(t)); }
+
+template <class T> inline void swap ( T& a, T& b )
+{
+    T c(a); a=b; b=c;
+}
+
+template<typename T> inline T max(T a, T b) { return (a > b) ? a : b; }
+
+template<typename T> inline T min(T a, T b) { return (a < b) ? a : b; }
+
+inline int alignup(int value, int a) {
+    //if align = 0, return the value. Else, do alignment.
+    return a ? ((((value - 1) / a) + 1) * a) : value;
+}
+
+inline int aligndown(int value, int a) {
+    //if align = 0, return the value. Else, do alignment.
+    return a ? ((value) & ~(a-1)) : value;
+}
+
+// FIXME that align should replace the upper one.
+inline int align(int value, int a) {
+    //if align = 0, return the value. Else, do alignment.
+    return a ? ((value + (a-1)) & ~(a-1)) : value;
+}
+
+inline bool isYuv(uint32_t format) {
+    switch(format){
+        case MDP_Y_CBCR_H2V1:
+        case MDP_Y_CBCR_H2V2:
+        case MDP_Y_CRCB_H2V2:
+        case MDP_Y_CRCB_H1V1:
+        case MDP_Y_CRCB_H2V1:
+        case MDP_Y_CRCB_H2V2_TILE:
+        case MDP_Y_CBCR_H2V2_TILE:
+        case MDP_Y_CR_CB_H2V2:
+        case MDP_Y_CR_CB_GH2V2:
+        case MDP_Y_CBCR_H2V2_VENUS:
+        case MDP_YCBYCR_H2V1:
+        case MDP_YCRYCB_H2V1:
+            return true;
+        default:
+            return false;
+    }
+    return false;
+}
+
+inline bool isRgb(uint32_t format) {
+    switch(format) {
+        case MDP_RGBA_8888:
+        case MDP_BGRA_8888:
+        case MDP_RGBX_8888:
+        case MDP_RGB_565:
+            return true;
+        default:
+            return false;
+    }
+    return false;
+}
+
+inline const char* getFormatString(int format){
+    #define STR(f) #f;
+    static const char* formats[MDP_IMGTYPE_LIMIT + 1] = {0};
+    formats[MDP_RGB_565] = STR(MDP_RGB_565);
+    formats[MDP_XRGB_8888] = STR(MDP_XRGB_8888);
+    formats[MDP_Y_CBCR_H2V2] = STR(MDP_Y_CBCR_H2V2);
+    formats[MDP_Y_CBCR_H2V2_ADRENO] = STR(MDP_Y_CBCR_H2V2_ADRENO);
+    formats[MDP_ARGB_8888] = STR(MDP_ARGB_8888);
+    formats[MDP_RGB_888] = STR(MDP_RGB_888);
+    formats[MDP_Y_CRCB_H2V2] = STR(MDP_Y_CRCB_H2V2);
+    formats[MDP_YCBYCR_H2V1] = STR(MDP_YCBYCR_H2V1);
+    formats[MDP_YCRYCB_H2V1] = STR(MDP_YCRYCB_H2V1);
+    formats[MDP_CBYCRY_H2V1] = STR(MDP_CBYCRY_H2V1);
+    formats[MDP_Y_CRCB_H2V1] = STR(MDP_Y_CRCB_H2V1);
+    formats[MDP_Y_CBCR_H2V1] = STR(MDP_Y_CBCR_H2V1);
+    formats[MDP_Y_CRCB_H1V2] = STR(MDP_Y_CRCB_H1V2);
+    formats[MDP_Y_CBCR_H1V2] = STR(MDP_Y_CBCR_H1V2);
+    formats[MDP_RGBA_8888] = STR(MDP_RGBA_8888);
+    formats[MDP_BGRA_8888] = STR(MDP_BGRA_8888);
+    formats[MDP_RGBX_8888] = STR(MDP_RGBX_8888);
+    formats[MDP_Y_CRCB_H2V2_TILE] = STR(MDP_Y_CRCB_H2V2_TILE);
+    formats[MDP_Y_CBCR_H2V2_TILE] = STR(MDP_Y_CBCR_H2V2_TILE);
+    formats[MDP_Y_CR_CB_H2V2] = STR(MDP_Y_CR_CB_H2V2);
+    formats[MDP_Y_CR_CB_GH2V2] = STR(MDP_Y_CR_CB_GH2V2);
+    formats[MDP_Y_CB_CR_H2V2] = STR(MDP_Y_CB_CR_H2V2);
+    formats[MDP_Y_CRCB_H1V1] = STR(MDP_Y_CRCB_H1V1);
+    formats[MDP_Y_CBCR_H1V1] = STR(MDP_Y_CBCR_H1V1);
+    formats[MDP_YCRCB_H1V1] = STR(MDP_YCRCB_H1V1);
+    formats[MDP_YCBCR_H1V1] = STR(MDP_YCBCR_H1V1);
+    formats[MDP_BGR_565] = STR(MDP_BGR_565);
+    formats[MDP_BGR_888] = STR(MDP_BGR_888);
+    formats[MDP_Y_CBCR_H2V2_VENUS] = STR(MDP_Y_CBCR_H2V2_VENUS);
+    formats[MDP_BGRX_8888] = STR(MDP_BGRX_8888);
+    formats[MDP_RGBA_8888_TILE] = STR(MDP_RGBA_8888_TILE);
+    formats[MDP_ARGB_8888_TILE] = STR(MDP_ARGB_8888_TILE);
+    formats[MDP_ABGR_8888_TILE] = STR(MDP_ABGR_8888_TILE);
+    formats[MDP_BGRA_8888_TILE] = STR(MDP_BGRA_8888_TILE);
+    formats[MDP_RGBX_8888_TILE] = STR(MDP_RGBX_8888_TILE);
+    formats[MDP_XRGB_8888_TILE] = STR(MDP_XRGB_8888_TILE);
+    formats[MDP_XBGR_8888_TILE] = STR(MDP_XBGR_8888_TILE);
+    formats[MDP_BGRX_8888_TILE] = STR(MDP_BGRX_8888_TILE);
+    formats[MDP_RGB_565_TILE] = STR(MDP_RGB_565_TILE);
+    formats[MDP_IMGTYPE_LIMIT] = STR(MDP_IMGTYPE_LIMIT);
+
+    if(format < 0 || format >= MDP_IMGTYPE_LIMIT) {
+        ALOGE("%s wrong fmt %d", __FUNCTION__, format);
+        return "Unsupported format";
+    }
+    if(formats[format] == 0) {
+        ALOGE("%s: table missing format %d from header", __FUNCTION__, format);
+        return "";
+    }
+    return formats[format];
+}
+
+inline void Whf::dump() const {
+    ALOGE("== Dump WHF w=%d h=%d f=%d s=%d start/end ==",
+            w, h, format, size);
+}
+
+inline void Dim::dump() const {
+    ALOGE("== Dump Dim x=%d y=%d w=%d h=%d start/end ==", x, y, w, h);
+}
+
+template <class Type>
+void swapWidthHeight(Type& width, Type& height) {
+    Type tmp = width;
+    width = height;
+    height = tmp;
+}
+
+inline void ScreenInfo::dump(const char* const s) const {
+    ALOGE("== Dump %s ScreenInfo w=%d h=%d"
+            " bpp=%d stride=%d start/end ==",
+            s, mFBWidth, mFBHeight, mFBbpp, mFBystride);
+}
+
+inline bool openDev(OvFD& fd, int fbnum,
+    const char* const devpath, int flags) {
+    return overlay::open(fd, fbnum, devpath, flags);
+}
+
+template <class T>
+inline void even_ceil(T& value) {
+    if(value & 1)
+        value++;
+}
+
+template <class T>
+inline void even_floor(T& value) {
+    if(value & 1)
+        value--;
+}
+
+/* Prerotation adjusts crop co-ordinates to the new transformed values within
+ * destination buffer. This is necessary only when the entire buffer is rotated
+ * irrespective of crop (A-family). If only the crop portion of the buffer is
+ * rotated into a destination buffer matching the size of crop, we don't need to
+ * use this helper (B-family).
+ * @Deprecated as of now, retained for the case where a full buffer needs
+ * transform and also as a reference.
+ */
+void preRotateSource(const eTransform& tr, Whf& whf, Dim& srcCrop);
+void getDump(char *buf, size_t len, const char *prefix, const mdp_overlay& ov);
+void getDump(char *buf, size_t len, const char *prefix, const msmfb_img& ov);
+void getDump(char *buf, size_t len, const char *prefix, const mdp_rect& ov);
+void getDump(char *buf, size_t len, const char *prefix,
+        const msmfb_overlay_data& ov);
+void getDump(char *buf, size_t len, const char *prefix, const msmfb_data& ov);
+void getDump(char *buf, size_t len, const char *prefix,
+        const msm_rotator_img_info& ov);
+void getDump(char *buf, size_t len, const char *prefix,
+        const msm_rotator_data_info& ov);
+
+} // namespace utils ends
+
+//--------------------Class Res stuff (namespace overlay only) -----------
+
+class Res {
+public:
+    // /dev/graphics/fb%u
+    static const char* const fbPath;
+    // /dev/msm_rotator
+    static const char* const rotPath;
+};
+
+
+//--------------------Class OvFD stuff (namespace overlay only) -----------
+
+/*
+* Holds one FD
+* Dtor will NOT close the underlying FD.
+* That enables us to copy that object around
+* */
+class OvFD {
+public:
+    /* Ctor */
+    explicit OvFD();
+
+    /* dtor will NOT close the underlying FD */
+    ~OvFD();
+
+    /* Open fd using the path given by dev.
+     * return false in failure */
+    bool open(const char* const dev,
+            int flags = O_RDWR);
+
+    /* populate path */
+    void setPath(const char* const dev);
+
+    /* Close fd if we have a valid fd. */
+    bool close();
+
+    /* returns underlying fd.*/
+    int getFD() const;
+
+    /* returns true if fd is valid */
+    bool valid() const;
+
+    /* like operator= */
+    void copy(int fd);
+
+    /* dump the state of the instance */
+    void dump() const;
+private:
+    /* helper enum for determine valid/invalid fd */
+    enum { INVAL = -1 };
+
+    /* actual os fd */
+    int mFD;
+
+    /* path, for debugging */
+    char mPath[utils::MAX_PATH_LEN];
+};
+
+//-------------------Inlines--------------------------
+
+inline bool open(OvFD& fd, uint32_t fbnum, const char* const dev, int flags)
+{
+    char dev_name[64] = {0};
+    snprintf(dev_name, sizeof(dev_name), dev, fbnum);
+    return fd.open(dev_name, flags);
+}
+
+inline OvFD::OvFD() : mFD (INVAL) {
+    mPath[0] = 0;
+}
+
+inline OvFD::~OvFD() {
+    //no op since copy() can be used to share fd, in 3d cases.
+}
+
+inline bool OvFD::open(const char* const dev, int flags)
+{
+    mFD = ::open(dev, flags, 0);
+    if (mFD < 0) {
+        // FIXME errno, strerror in bionic?
+        ALOGE("Cant open device %s err=%d", dev, errno);
+        return false;
+    }
+    setPath(dev);
+    return true;
+}
+
+inline void OvFD::setPath(const char* const dev)
+{
+    ::strlcpy(mPath, dev, sizeof(mPath));
+}
+
+inline bool OvFD::close()
+{
+    int ret = 0;
+    if(valid()) {
+        ret = ::close(mFD);
+        mFD = INVAL;
+    }
+    return (ret == 0);
+}
+
+inline bool OvFD::valid() const
+{
+    return (mFD != INVAL);
+}
+
+inline int OvFD::getFD() const { return mFD; }
+
+inline void OvFD::copy(int fd) {
+    mFD = fd;
+}
+
+inline void OvFD::dump() const
+{
+    ALOGE("== Dump OvFD fd=%d path=%s start/end ==",
+            mFD, mPath);
+}
+
+//--------------- class OvFD stuff ends ---------------------
+
+} // overlay
+
+
+#endif // OVERLAY_UTILS_H
diff --git a/msm8909/liboverlay/overlayWriteback.cpp b/msm8909/liboverlay/overlayWriteback.cpp
new file mode 100644
index 0000000..ed42a9f
--- /dev/null
+++ b/msm8909/liboverlay/overlayWriteback.cpp
@@ -0,0 +1,280 @@
+/*
+* Copyright (c) 2013 The Linux Foundation. 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 The Linux Foundation. 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.
+*/
+
+#include "overlay.h"
+#include "overlayWriteback.h"
+#include "mdpWrapper.h"
+
+#define SIZE_1M 0x00100000
+
+namespace overlay {
+
+//=========== class WritebackMem ==============================================
+bool WritebackMem::manageMem(uint32_t size, bool isSecure) {
+    if(mBuf.bufSz() == size) {
+        return true;
+    }
+    if(mBuf.valid()) {
+        if(!mBuf.close()) {
+            ALOGE("%s error closing mem", __func__);
+            return false;
+        }
+    }
+    return alloc(size, isSecure);
+}
+
+bool WritebackMem::alloc(uint32_t size, bool isSecure) {
+    if(!mBuf.open(NUM_BUFS, size, isSecure)){
+        ALOGE("%s: Failed to open", __func__);
+        mBuf.close();
+        return false;
+    }
+
+    OVASSERT(MAP_FAILED != mBuf.addr(), "MAP failed");
+    OVASSERT(mBuf.getFD() != -1, "getFd is -1");
+
+    mCurrOffsetIndex = 0;
+    for (uint32_t i = 0; i < NUM_BUFS; i++) {
+        mOffsets[i] = i * size;
+    }
+    return true;
+}
+
+bool WritebackMem::dealloc() {
+    bool ret = true;
+    if(mBuf.valid()) {
+        ret = mBuf.close();
+    }
+    return ret;
+}
+
+//=========== class Writeback =================================================
+Writeback::Writeback() : mXres(0), mYres(0), mOpFmt(-1), mSecure(false) {
+    int fbNum = Overlay::getFbForDpy(Overlay::DPY_WRITEBACK);
+    if(!utils::openDev(mFd, fbNum, Res::fbPath, O_RDWR)) {
+        ALOGE("%s failed to init %s", __func__, Res::fbPath);
+        return;
+    }
+    startSession();
+}
+
+Writeback::~Writeback() {
+    stopSession();
+    if (!mFd.close()) {
+        ALOGE("%s error closing fd", __func__);
+    }
+}
+
+bool Writeback::startSession() {
+    if(!mdp_wrapper::wbInitStart(mFd.getFD())) {
+        ALOGE("%s failed", __func__);
+        return false;
+    }
+    return true;
+}
+
+bool Writeback::stopSession() {
+    if(mFd.valid()) {
+        if(!Overlay::displayCommit(mFd.getFD())) {
+            ALOGE("%s: displayCommit failed", __func__);
+            return false;
+        }
+        if(!mdp_wrapper::wbStopTerminate(mFd.getFD())) {
+            ALOGE("%s: wbStopTerminate failed", __func__);
+            return false;
+        }
+    } else {
+        ALOGE("%s Invalid fd", __func__);
+        return false;
+    }
+    return true;
+}
+
+bool Writeback::configureDpyInfo(int xres, int yres) {
+    if(mXres != xres || mYres != yres) {
+        fb_var_screeninfo vinfo;
+        memset(&vinfo, 0, sizeof(fb_var_screeninfo));
+        if(!mdp_wrapper::getVScreenInfo(mFd.getFD(), vinfo)) {
+            ALOGE("%s failed", __func__);
+            return false;
+        }
+        vinfo.xres = xres;
+        vinfo.yres = yres;
+        vinfo.xres_virtual = xres;
+        vinfo.yres_virtual = yres;
+        vinfo.xoffset = 0;
+        vinfo.yoffset = 0;
+        if(!mdp_wrapper::setVScreenInfo(mFd.getFD(), vinfo)) {
+            ALOGE("%s failed", __func__);
+            return false;
+        }
+        mXres = xres;
+        mYres = yres;
+    }
+    return true;
+}
+
+bool Writeback::configureMemory(uint32_t size) {
+    if(!mWbMem.manageMem(size, mSecure)) {
+        ALOGE("%s failed, memory failure", __func__);
+        return false;
+    }
+    return true;
+}
+
+bool Writeback::queueBuffer(int opFd, uint32_t opOffset) {
+    memset(&mFbData, 0, sizeof(struct msmfb_data));
+    //Queue
+    mFbData.offset = opOffset;
+    mFbData.memory_id = opFd;
+    mFbData.id = 0;
+    mFbData.flags = 0;
+    if(!mdp_wrapper::wbQueueBuffer(mFd.getFD(), mFbData)) {
+        ALOGE("%s: queuebuffer failed", __func__);
+        return false;
+    }
+    return true;
+}
+
+bool Writeback::dequeueBuffer() {
+    //Dequeue
+    mFbData.flags = MSMFB_WRITEBACK_DEQUEUE_BLOCKING;
+    if(!mdp_wrapper::wbDequeueBuffer(mFd.getFD(), mFbData)) {
+        ALOGE("%s: dequeuebuffer failed", __func__);
+        return false;
+    }
+    return true;
+}
+
+bool Writeback::writeSync(int opFd, uint32_t opOffset) {
+    if(!queueBuffer(opFd, opOffset)) {
+        return false;
+    }
+    if(!Overlay::displayCommit(mFd.getFD())) {
+        return false;
+    }
+    if(!dequeueBuffer()) {
+        return false;
+    }
+    return true;
+}
+
+bool Writeback::writeSync() {
+    mWbMem.useNextBuffer();
+    return writeSync(mWbMem.getDstFd(), mWbMem.getOffset());
+}
+
+bool Writeback::setOutputFormat(int mdpFormat) {
+    if(mdpFormat != mOpFmt) {
+        struct msmfb_metadata metadata;
+        memset(&metadata, 0 , sizeof(metadata));
+        metadata.op = metadata_op_wb_format;
+        metadata.data.mixer_cfg.writeback_format = mdpFormat;
+        if (ioctl(mFd.getFD(), MSMFB_METADATA_SET, &metadata) < 0) {
+            ALOGE("Error setting MDP Writeback format");
+            return false;
+        }
+        mOpFmt = mdpFormat;
+    }
+    return true;
+}
+
+int Writeback::getOutputFormat() {
+    if(mOpFmt < 0) {
+        struct msmfb_metadata metadata;
+        memset(&metadata, 0 , sizeof(metadata));
+        metadata.op = metadata_op_wb_format;
+        if (ioctl(mFd.getFD(), MSMFB_METADATA_GET, &metadata) < 0) {
+            ALOGE("Error retrieving MDP Writeback format");
+            return -1;
+        }
+        mOpFmt =  metadata.data.mixer_cfg.writeback_format;
+    }
+    return mOpFmt;
+}
+
+bool Writeback::setSecure(bool isSecure) {
+    if(isSecure != mSecure) {
+        // Call IOCTL to set WB interface as secure
+        struct msmfb_metadata metadata;
+        memset(&metadata, 0 , sizeof(metadata));
+        metadata.op = metadata_op_wb_secure;
+        metadata.data.secure_en = isSecure;
+        if (ioctl(mFd.getFD(), MSMFB_METADATA_SET, &metadata) < 0) {
+            ALOGE("Error setting MDP WB secure");
+            return false;
+        }
+        mSecure = isSecure;
+    }
+    return true;
+}
+
+//static
+
+Writeback *Writeback::getInstance() {
+    if(sWb == NULL) {
+        sWb = new Writeback();
+    }
+    sUsed = true;
+    return sWb;
+}
+
+void Writeback::configDone() {
+    if(sUsed == false && sWb) {
+        delete sWb;
+        sWb = NULL;
+    }
+}
+
+void Writeback::clear() {
+    sUsed = false;
+    if(sWb) {
+        delete sWb;
+        sWb = NULL;
+    }
+}
+
+bool Writeback::getDump(char *buf, size_t len) {
+    if(sWb) {
+        utils::getDump(buf, len, "WBData", sWb->mFbData);
+        char outputBufferInfo[256];
+        snprintf(outputBufferInfo, sizeof(outputBufferInfo),
+                "OutputBuffer xres=%d yres=%d format=%s\n\n",
+                sWb->getWidth(), sWb->getHeight(),
+                utils::getFormatString(sWb->getOutputFormat()));
+        strlcat(buf, outputBufferInfo, len);
+        return true;
+    }
+    return false;
+}
+
+Writeback *Writeback::sWb = 0;
+bool Writeback::sUsed = false;
+
+} //namespace overlay
diff --git a/msm8909/liboverlay/overlayWriteback.h b/msm8909/liboverlay/overlayWriteback.h
new file mode 100644
index 0000000..21186e6
--- /dev/null
+++ b/msm8909/liboverlay/overlayWriteback.h
@@ -0,0 +1,122 @@
+/*
+* Copyright (c) 2013 The Linux Foundation. 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 The Linux Foundation. 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 OVERLAY_WRITEBACK_H
+#define OVERLAY_WRITEBACK_H
+
+#include "overlayMem.h"
+
+namespace overlay {
+
+class WritebackMgr;
+
+class WritebackMem {
+public:
+    explicit WritebackMem() : mCurrOffsetIndex(0) {
+        memset(&mOffsets, 0, sizeof(mOffsets));
+    }
+    ~WritebackMem() { dealloc(); }
+    bool manageMem(uint32_t size, bool isSecure);
+    void useNextBuffer() {
+            mCurrOffsetIndex = (mCurrOffsetIndex + 1) % NUM_BUFS;
+    }
+    uint32_t getOffset() const { return mOffsets[mCurrOffsetIndex]; }
+    int getDstFd() const { return mBuf.getFD(); }
+private:
+    bool alloc(uint32_t size, bool isSecure);
+    bool dealloc();
+    enum { NUM_BUFS = 2 };
+    OvMem mBuf;
+    uint32_t mOffsets[NUM_BUFS];
+    uint32_t mCurrOffsetIndex;
+};
+
+//Abstracts the WB2 interface of MDP
+//Has modes to either manage memory or work with memory allocated elsewhere
+class Writeback {
+public:
+    ~Writeback();
+    bool configureDpyInfo(int xres, int yres);
+    bool configureMemory(uint32_t size);
+    /* Blocking write. (queue, commit, dequeue)
+     * This class will do writeback memory management.
+     * This class will call display-commit on writeback mixer.
+     */
+    bool writeSync();
+    /* Blocking write. (queue, commit, dequeue)
+     * Client must do writeback memory management.
+     * Client must not call display-commit on writeback mixer.
+     */
+    bool writeSync(int opFd, uint32_t opOffset);
+    /* Async queue. (Does not write)
+     * Client must do writeback memory management.
+     * Client must call display-commit on their own.
+     * Client must use sync mechanism e.g sync pt.
+     */
+    bool queueBuffer(int opFd, uint32_t opOffset);
+    uint32_t getOffset() const { return mWbMem.getOffset(); }
+    int getDstFd() const { return mWbMem.getDstFd(); }
+    int getWidth() const { return mXres; }
+    int getHeight() const { return mYres; }
+    /* Subject to GC if writeback isnt used for a drawing round.
+     * Get always if caching the value.
+     */
+    int getFbFd() const { return mFd.getFD(); }
+    int getOutputFormat();
+    bool setOutputFormat(int mdpFormat);
+    bool setSecure(bool isSecure);
+
+    static Writeback* getInstance();
+    static void configBegin() { sUsed = false; }
+    static void configDone();
+    static void clear();
+    //Will take a dump of data structure only if there is an instance existing
+    //Returns true if dump is added to the input buffer, false otherwise
+    static bool getDump(char *buf, size_t len);
+
+private:
+    explicit Writeback();
+    bool startSession();
+    bool stopSession();
+    //Actually block_until_write_done for the usage here.
+    bool dequeueBuffer();
+    OvFD mFd;
+    WritebackMem mWbMem;
+    struct msmfb_data mFbData;
+    int mXres;
+    int mYres;
+    int mOpFmt;
+    bool mSecure;
+
+    static bool sUsed;
+    static Writeback *sWb;
+};
+
+}
+
+#endif
diff --git a/msm8909/liboverlay/pipes/overlayGenPipe.cpp b/msm8909/liboverlay/pipes/overlayGenPipe.cpp
new file mode 100644
index 0000000..aebaebf
--- /dev/null
+++ b/msm8909/liboverlay/pipes/overlayGenPipe.cpp
@@ -0,0 +1,124 @@
+/*
+* Copyright (c) 2012-2013, The Linux Foundation. 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 The Linux Foundation 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.
+*/
+
+#include "overlayGenPipe.h"
+#include "mdp_version.h"
+
+namespace overlay {
+
+GenericPipe::GenericPipe(const int& dpy) : mDpy(dpy),
+    mCtrl(new Ctrl(dpy)), mData(new Data(dpy)) {
+}
+
+GenericPipe::~GenericPipe() {
+    delete mCtrl;
+    delete mData;
+}
+
+void GenericPipe::setSource(const utils::PipeArgs& args) {
+    mCtrl->setSource(args);
+}
+
+void GenericPipe::setCrop(const overlay::utils::Dim& d) {
+    mCtrl->setCrop(d);
+}
+
+void GenericPipe::setColor(const uint32_t color) {
+    mCtrl->setColor(color);
+}
+
+void GenericPipe::setTransform(const utils::eTransform& orient) {
+    mCtrl->setTransform(orient);
+}
+
+void GenericPipe::setPosition(const utils::Dim& d) {
+    mCtrl->setPosition(d);
+}
+
+bool GenericPipe::setVisualParams(const MetaData_t &metadata)
+{
+        return mCtrl->setVisualParams(metadata);
+}
+
+void GenericPipe::setPipeType(const utils::eMdpPipeType& pType) {
+    mCtrl->setPipeType(pType);
+}
+
+bool GenericPipe::commit() {
+    return mCtrl->commit();
+}
+
+bool GenericPipe::queueBuffer(int fd, uint32_t offset) {
+    int pipeId = mCtrl->getPipeId();
+    OVASSERT(-1 != pipeId, "Ctrl ID should not be -1");
+    // set pipe id from ctrl to data
+    mData->setPipeId(pipeId);
+
+    return mData->queueBuffer(fd, offset);
+}
+
+utils::Dim GenericPipe::getCrop() const
+{
+    return mCtrl->getCrop();
+}
+
+uint8_t GenericPipe::getPriority() const {
+    return mCtrl->getPriority();
+}
+
+void GenericPipe::dump() const
+{
+    ALOGE("== Dump Generic pipe start ==");
+    mCtrl->dump();
+    mData->dump();
+    ALOGE("== Dump Generic pipe end ==");
+}
+
+void GenericPipe::getDump(char *buf, size_t len) {
+    mCtrl->getDump(buf, len);
+    mData->getDump(buf, len);
+}
+
+int GenericPipe::getPipeId() {
+    return mCtrl->getPipeId();
+}
+
+bool GenericPipe::validateAndSet(GenericPipe* pipeArray[], const int& count,
+        const int& fbFd) {
+    Ctrl* ctrlArray[count];
+    memset(&ctrlArray, 0, sizeof(ctrlArray));
+
+    for(int i = 0; i < count; i++) {
+        ctrlArray[i] = pipeArray[i]->mCtrl;
+    }
+
+    return Ctrl::validateAndSet(ctrlArray, count, fbFd);
+}
+
+} //namespace overlay
diff --git a/msm8909/liboverlay/pipes/overlayGenPipe.h b/msm8909/liboverlay/pipes/overlayGenPipe.h
new file mode 100644
index 0000000..0a2639a
--- /dev/null
+++ b/msm8909/liboverlay/pipes/overlayGenPipe.h
@@ -0,0 +1,86 @@
+/*
+* Copyright (c) 2011-2013, The Linux Foundation. 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 The Linux Foundation 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 OVERLAY_GENERIC_PIPE_H
+#define OVERLAY_GENERIC_PIPE_H
+
+#include "overlayUtils.h"
+#include "overlayCtrlData.h"
+
+namespace overlay {
+
+class GenericPipe : utils::NoCopy {
+public:
+    /* ctor */
+    explicit GenericPipe(const int& dpy);
+    /* dtor */
+    ~GenericPipe();
+    /* Control APIs */
+    /* set source using whf, orient and wait flag */
+    void setSource(const utils::PipeArgs& args);
+    /* set crop a.k.a the region of interest */
+    void setCrop(const utils::Dim& d);
+    /* set color for mdp pipe */
+    void setColor(const uint32_t color);
+    /* set orientation*/
+    void setTransform(const utils::eTransform& param);
+    /* set mdp posision using dim */
+    void setPosition(const utils::Dim& dim);
+    /* set visual param */
+    bool setVisualParams(const MetaData_t &metadata);
+    /* set pipe type RGB/DMA/VG */
+    void setPipeType(const utils::eMdpPipeType& pType);
+    /* commit changes to the overlay "set"*/
+    bool commit();
+    /* Data APIs */
+    /* queue buffer to the overlay */
+    bool queueBuffer(int fd, uint32_t offset);
+    /* return cached startup args */
+    const utils::PipeArgs& getArgs() const;
+    /* retrieve cached crop data */
+    utils::Dim getCrop() const;
+    /* return pipe priority */
+    uint8_t getPriority() const;
+    /* dump the state of the object */
+    void dump() const;
+    /* Return the dump in the specified buffer */
+    void getDump(char *buf, size_t len);
+    int getPipeId();
+
+    static bool validateAndSet(GenericPipe* pipeArray[], const int& count,
+            const int& fbFd);
+private:
+    int mDpy;
+    Ctrl *mCtrl;
+    Data *mData;
+};
+
+} //namespace overlay
+
+#endif // OVERLAY_GENERIC_PIPE_H
diff --git a/msm8909/libqdutils/Android.mk b/msm8909/libqdutils/Android.mk
new file mode 100644
index 0000000..212c8d8
--- /dev/null
+++ b/msm8909/libqdutils/Android.mk
@@ -0,0 +1,33 @@
+LOCAL_PATH := $(call my-dir)
+include $(LOCAL_PATH)/../common.mk
+include $(CLEAR_VARS)
+
+LOCAL_MODULE                  := libqdutils
+LOCAL_MODULE_TAGS             := optional
+LOCAL_SHARED_LIBRARIES        := $(common_libs) libui libbinder libqservice
+LOCAL_C_INCLUDES              := $(common_includes) $(kernel_includes)
+LOCAL_CFLAGS                  := $(common_flags) -DLOG_TAG=\"qdutils\"
+LOCAL_ADDITIONAL_DEPENDENCIES := $(common_deps)
+LOCAL_COPY_HEADERS_TO         := $(common_header_export_path)
+LOCAL_COPY_HEADERS            := display_config.h mdp_version.h
+LOCAL_SRC_FILES               := profiler.cpp mdp_version.cpp \
+                                 idle_invalidator.cpp \
+                                 comptype.cpp qd_utils.cpp \
+                                 cb_utils.cpp display_config.cpp \
+                                 cb_swap_rect.cpp
+include $(BUILD_SHARED_LIBRARY)
+
+include $(CLEAR_VARS)
+
+LOCAL_COPY_HEADERS_TO           := $(common_header_export_path)
+LOCAL_COPY_HEADERS              := qdMetaData.h
+LOCAL_SHARED_LIBRARIES          := liblog libcutils
+LOCAL_C_INCLUDES                := $(common_includes)
+LOCAL_ADDITIONAL_DEPENDENCIES   := $(common_deps)
+LOCAL_SRC_FILES                 := qdMetaData.cpp
+LOCAL_CFLAGS                    := $(common_flags)
+LOCAL_CFLAGS                    += -DLOG_TAG=\"DisplayMetaData\"
+LOCAL_MODULE_TAGS               := optional
+LOCAL_MODULE                    := libqdMetaData
+include $(BUILD_SHARED_LIBRARY)
+
diff --git a/msm8909/libqdutils/cb_swap_rect.cpp b/msm8909/libqdutils/cb_swap_rect.cpp
new file mode 100644
index 0000000..8c8efec
--- /dev/null
+++ b/msm8909/libqdutils/cb_swap_rect.cpp
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2014, The Linux Foundation. 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 The Linux Foundation or 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.
+ */
+
+#include "cb_swap_rect.h"
+
+ANDROID_SINGLETON_STATIC_INSTANCE(qdutils::cb_swap_rect);
+
+namespace qdutils {
+
+cb_swap_rect:: cb_swap_rect(){
+     swap_rect_feature_on = false ;
+}
+void cb_swap_rect::setSwapRectFeature_on( bool value){
+       swap_rect_feature_on = value ;
+}
+bool cb_swap_rect::checkSwapRectFeature_on(){
+       return swap_rect_feature_on;
+}
+
+};
diff --git a/msm8909/libqdutils/cb_swap_rect.h b/msm8909/libqdutils/cb_swap_rect.h
new file mode 100644
index 0000000..daaeb37
--- /dev/null
+++ b/msm8909/libqdutils/cb_swap_rect.h
@@ -0,0 +1,51 @@
+/* Copyright (c) 2014, The Linux Foundation. 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 copyrigh
+*     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 The Linux Foundation 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 CB_SWAP_RECT
+#define CB_SWAP_RECT
+
+#include <stdint.h>
+#include <utils/Singleton.h>
+#include <cutils/log.h>
+
+using namespace android;
+namespace qdutils {
+enum {
+HWC_SKIP_HWC_COMPOSITION = 0x00040000,
+};
+
+class cb_swap_rect : public Singleton <cb_swap_rect>
+{
+   bool swap_rect_feature_on;
+   public :
+   cb_swap_rect();
+   void setSwapRectFeature_on( bool value);
+   bool checkSwapRectFeature_on();
+};
+} // namespace qdutils
+#endif
diff --git a/msm8909/libqdutils/cb_utils.cpp b/msm8909/libqdutils/cb_utils.cpp
new file mode 100644
index 0000000..9c533a2
--- /dev/null
+++ b/msm8909/libqdutils/cb_utils.cpp
@@ -0,0 +1,133 @@
+/* Copyright (c) 2013, The Linux Foundation. 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 copyrigh
+*     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 The Linux Foundation 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.
+*/
+
+#include "cb_utils.h"
+#include "cb_swap_rect.h"
+/* get union of two rects into 3rd rect */
+void getUnion(hwc_rect_t& rect1,hwc_rect_t& rect2, hwc_rect_t& irect) {
+
+    irect.left   = min(rect1.left, rect2.left);
+    irect.top    = min(rect1.top, rect2.top);
+    irect.right  = max(rect1.right, rect2.right);
+    irect.bottom = max(rect1.bottom, rect2.bottom);
+}
+
+int clear (copybit_device_t *copybit, private_handle_t* hnd, hwc_rect_t& rect)
+{
+    int ret = 0;
+    copybit_rect_t clear_rect = {rect.left, rect.top,rect.right,rect.bottom};
+
+    copybit_image_t buf;
+    buf.w = ALIGN(getWidth(hnd),32);
+    buf.h = getHeight(hnd);
+    buf.format = hnd->format;
+    buf.base = (void *)hnd->base;
+    buf.handle = (native_handle_t *)hnd;
+
+    ret = copybit->clear(copybit, &buf, &clear_rect);
+    return ret;
+}
+using namespace android;
+using namespace qhwc;
+namespace qdutils {
+
+int CBUtils::uiClearRegion(hwc_display_contents_1_t* list,
+        int version, LayerProp *layerProp,  hwc_rect_t dirtyRect,
+            copybit_device_t *copybit, private_handle_t *renderBuffer) {
+
+    size_t last = list->numHwLayers - 1;
+    hwc_rect_t fbFrame = list->hwLayers[last].displayFrame;
+    Rect fbFrameRect(fbFrame.left,fbFrame.top,fbFrame.right,fbFrame.bottom);
+    Region wormholeRegion(fbFrameRect);
+
+   if ((dirtyRect.right - dirtyRect.left > 0) &&
+                               (dirtyRect.bottom - dirtyRect.top > 0)) {
+#ifdef QTI_BSP
+      Rect tmpRect(dirtyRect.left,dirtyRect.top,dirtyRect.right,
+            dirtyRect.bottom);
+      Region tmpRegion(tmpRect);
+      wormholeRegion = wormholeRegion.intersect(tmpRegion);
+#endif
+   }
+    if(cb_swap_rect::getInstance().checkSwapRectFeature_on() == true){
+      wormholeRegion.set(0,0);
+      for(size_t i = 0 ; i < last; i++) {
+         if(((list->hwLayers[i].blending == HWC_BLENDING_NONE) &&
+           (list->hwLayers[i].planeAlpha == 0xFF)) ||
+           !(layerProp[i].mFlags & HWC_COPYBIT) ||
+           (list->hwLayers[i].flags  & HWC_SKIP_HWC_COMPOSITION))
+              continue ;
+         hwc_rect_t displayFrame = list->hwLayers[i].displayFrame;
+         Rect tmpRect(displayFrame.left,displayFrame.top,
+                      displayFrame.right,displayFrame.bottom);
+         wormholeRegion.set(tmpRect);
+      }
+   }else{
+     for (size_t i = 0 ; i < last; i++) {
+        // need to take care only in per pixel blending.
+        // Restrict calculation only for copybit layers.
+        if((list->hwLayers[i].blending != HWC_BLENDING_NONE) ||
+           (list->hwLayers[i].planeAlpha != 0xFF) ||
+           !(layerProp[i].mFlags & HWC_COPYBIT))
+            continue ;
+        hwc_rect_t displayFrame = list->hwLayers[i].displayFrame;
+        Rect tmpRect(displayFrame.left,displayFrame.top,displayFrame.right,
+        displayFrame.bottom);
+        Region tmpRegion(tmpRect);
+        wormholeRegion.subtractSelf(wormholeRegion.intersect(tmpRegion));
+     }
+   }
+   if(wormholeRegion.isEmpty()){
+        return 1;
+   }
+   //TO DO :- 1. remove union and call clear for each rect.
+   Region::const_iterator it = wormholeRegion.begin();
+   Region::const_iterator const end = wormholeRegion.end();
+   while (it != end) {
+       const Rect& r = *it++;
+       hwc_rect_t tmpWormRect = {r.left,r.top,r.right,r.bottom};
+       if (version == qdutils::MDP_V3_0_4 ||
+               version == qdutils::MDP_V3_0_5) {
+           int clear_w =  tmpWormRect.right - tmpWormRect.left;
+           int clear_h =  tmpWormRect.bottom - tmpWormRect.top;
+           //mdp can't handle solid fill for one line
+           //making solid fill as full in this case
+           //disable swap rect if presents
+           if ((clear_w == 1) || (clear_h ==1)) {
+               clear(copybit, renderBuffer, fbFrame);
+               return 0;
+           } else {
+               clear(copybit, renderBuffer, tmpWormRect);
+           }
+       } else {
+           clear(copybit, renderBuffer, tmpWormRect);
+       }
+   }
+   return 1;
+}
+
+}//namespace qdutils
diff --git a/msm8909/libqdutils/cb_utils.h b/msm8909/libqdutils/cb_utils.h
new file mode 100644
index 0000000..55225b6
--- /dev/null
+++ b/msm8909/libqdutils/cb_utils.h
@@ -0,0 +1,46 @@
+/* Copyright (c) 2013, The Linux Foundation. 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 copyrigh
+*     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 The Linux Foundation 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 CB_UTIL_H
+#define CB_UTIL_H
+
+#include <ui/Region.h>
+#include "hwc_utils.h"
+#include "copybit.h"
+
+using namespace qhwc;
+namespace qdutils {
+class CBUtils {
+public:
+    static int uiClearRegion(hwc_display_contents_1_t* list,
+            int version, LayerProp *layerProp, hwc_rect_t dirtyIndex,
+            copybit_device_t *copybit, private_handle_t *renderBuffer);
+};
+}//namespace qdutils
+#endif /* end of include guard: CB_UTIL_H*/
+
diff --git a/msm8909/libqdutils/comptype.cpp b/msm8909/libqdutils/comptype.cpp
new file mode 100644
index 0000000..a29158a
--- /dev/null
+++ b/msm8909/libqdutils/comptype.cpp
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2013, The Linux Foundation. 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 The Linux Foundation or 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.
+ */
+
+#include<comptype.h>
+
+//Instanticate the QCCompositionType Singleton
+ANDROID_SINGLETON_STATIC_INSTANCE(qdutils::QCCompositionType);
diff --git a/msm8909/libqdutils/comptype.h b/msm8909/libqdutils/comptype.h
new file mode 100644
index 0000000..71f4871
--- /dev/null
+++ b/msm8909/libqdutils/comptype.h
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2012-2013, The Linux Foundation. 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 The Linux Foundation or 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 INCLUDE_LIBQCOM_COMPTYPES
+#define INCLUDE_LIBQCOM_COMPTYPES
+
+#include <stdint.h>
+#include <utils/Singleton.h>
+#include <cutils/properties.h>
+
+using namespace android;
+namespace qdutils {
+// 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
+};
+
+/* This class caches the composition type
+ */
+class QCCompositionType : public Singleton <QCCompositionType>
+{
+    public:
+        QCCompositionType();
+        ~QCCompositionType() { }
+        int getCompositionType() {return mCompositionType;}
+    private:
+        int mCompositionType;
+
+};
+
+inline QCCompositionType::QCCompositionType()
+{
+    char property[PROPERTY_VALUE_MAX];
+    mCompositionType = COMPOSITION_TYPE_GPU;
+    if (property_get("debug.composition.type", property, "gpu") > 0) {
+        if ((strncmp(property, "mdp", 3)) == 0) {
+            mCompositionType = COMPOSITION_TYPE_MDP;
+        } else if ((strncmp(property, "c2d", 3)) == 0) {
+            mCompositionType = COMPOSITION_TYPE_C2D;
+        } else if ((strncmp(property, "dyn", 3)) == 0) {
+#ifdef USE_MDP3
+            mCompositionType = COMPOSITION_TYPE_DYN | COMPOSITION_TYPE_MDP;
+#else
+            mCompositionType = COMPOSITION_TYPE_DYN | COMPOSITION_TYPE_C2D;
+#endif
+        }
+    }
+}
+
+}; //namespace qdutils
+#endif //INCLUDE_LIBQCOM_COMPTYPES
diff --git a/msm8909/libqdutils/display_config.cpp b/msm8909/libqdutils/display_config.cpp
new file mode 100644
index 0000000..62422fe
--- /dev/null
+++ b/msm8909/libqdutils/display_config.cpp
@@ -0,0 +1,191 @@
+/*
+* Copyright (c) 2013-2015 The Linux Foundation. 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 The Linux Foundation. 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.
+*/
+
+#include <display_config.h>
+#include <QServiceUtils.h>
+
+using namespace android;
+using namespace qService;
+
+namespace qdutils {
+
+int isExternalConnected(void) {
+    int ret;
+    status_t err = (status_t) FAILED_TRANSACTION;
+    sp<IQService> binder = getBinder();
+    Parcel inParcel, outParcel;
+    if(binder != NULL) {
+        err = binder->dispatch(IQService::CHECK_EXTERNAL_STATUS,
+                &inParcel , &outParcel);
+    }
+    if(err) {
+        ALOGE("%s: Failed to get external status err=%d", __FUNCTION__, err);
+        ret = err;
+    } else {
+        ret = outParcel.readInt32();
+    }
+    return ret;
+}
+
+int getDisplayAttributes(int dpy, DisplayAttributes_t& dpyattr) {
+    status_t err = (status_t) FAILED_TRANSACTION;
+    sp<IQService> binder = getBinder();
+    Parcel inParcel, outParcel;
+    inParcel.writeInt32(dpy);
+    if(binder != NULL) {
+        err = binder->dispatch(IQService::GET_DISPLAY_ATTRIBUTES,
+                &inParcel, &outParcel);
+    }
+    if(!err) {
+        dpyattr.vsync_period = outParcel.readInt32();
+        dpyattr.xres = outParcel.readInt32();
+        dpyattr.yres = outParcel.readInt32();
+        dpyattr.xdpi = outParcel.readFloat();
+        dpyattr.ydpi = outParcel.readFloat();
+        dpyattr.panel_type = (char) outParcel.readInt32();
+    } else {
+        ALOGE("%s: Failed to get display attributes err=%d", __FUNCTION__, err);
+    }
+    return err;
+}
+
+int setHSIC(int dpy, const HSICData_t& hsic_data) {
+    status_t err = (status_t) FAILED_TRANSACTION;
+    sp<IQService> binder = getBinder();
+    Parcel inParcel, outParcel;
+    inParcel.writeInt32(dpy);
+    inParcel.writeInt32(hsic_data.hue);
+    inParcel.writeFloat(hsic_data.saturation);
+    inParcel.writeInt32(hsic_data.intensity);
+    inParcel.writeFloat(hsic_data.contrast);
+    if(binder != NULL) {
+        err = binder->dispatch(IQService::SET_HSIC_DATA, &inParcel, &outParcel);
+    }
+    if(err)
+        ALOGE("%s: Failed to get external status err=%d", __FUNCTION__, err);
+    return err;
+}
+
+int getDisplayVisibleRegion(int dpy, hwc_rect_t &rect) {
+    status_t err = (status_t) FAILED_TRANSACTION;
+    sp<IQService> binder = getBinder();
+    Parcel inParcel, outParcel;
+    inParcel.writeInt32(dpy);
+    if(binder != NULL) {
+        err = binder->dispatch(IQService::GET_DISPLAY_VISIBLE_REGION,
+                &inParcel, &outParcel);
+    }
+    if(!err) {
+        rect.left = outParcel.readInt32();
+        rect.top = outParcel.readInt32();
+        rect.right = outParcel.readInt32();
+        rect.bottom = outParcel.readInt32();
+    } else {
+        ALOGE("%s: Failed to getVisibleRegion for dpy =%d: err = %d",
+              __FUNCTION__, dpy, err);
+    }
+    return err;
+}
+
+int setViewFrame(int dpy, int l, int t, int r, int b) {
+    status_t err = (status_t) FAILED_TRANSACTION;
+    sp<IQService> binder = getBinder();
+    Parcel inParcel, outParcel;
+    inParcel.writeInt32(dpy);
+    inParcel.writeInt32(l);
+    inParcel.writeInt32(t);
+    inParcel.writeInt32(r);
+    inParcel.writeInt32(b);
+
+    if(binder != NULL) {
+        err = binder->dispatch(IQService::SET_VIEW_FRAME,
+                &inParcel, &outParcel);
+    }
+    if(err)
+        ALOGE("%s: Failed to set view frame for dpy %d err=%d",
+                            __FUNCTION__, dpy, err);
+
+    return err;
+}
+
+int setSecondaryDisplayStatus(int dpy, uint32_t status) {
+    status_t err = (status_t) FAILED_TRANSACTION;
+    sp<IQService> binder = getBinder();
+    Parcel inParcel, outParcel;
+    inParcel.writeInt32(dpy);
+    inParcel.writeInt32(status);
+
+    if(binder != NULL) {
+        err = binder->dispatch(IQService::SET_SECONDARY_DISPLAY_STATUS,
+                &inParcel, &outParcel);
+    }
+    if(err)
+        ALOGE("%s: Failed for dpy %d status = %d err=%d", __FUNCTION__, dpy,
+                                                        status, err);
+
+    return err;
+}
+
+int configureDynRefreshRate(uint32_t op, uint32_t refreshRate) {
+    status_t err = (status_t) FAILED_TRANSACTION;
+    sp<IQService> binder = getBinder();
+    Parcel inParcel, outParcel;
+    inParcel.writeInt32(op);
+    inParcel.writeInt32(refreshRate);
+
+    if(binder != NULL) {
+        err = binder->dispatch(IQService::CONFIGURE_DYN_REFRESH_RATE,
+                               &inParcel, &outParcel);
+    }
+
+    if(err)
+        ALOGE("%s: Failed setting op %d err=%d", __FUNCTION__, op, err);
+
+    return err;
+}
+
+}; //namespace
+
+// ----------------------------------------------------------------------------
+// Screen refresh for native daemons linking dynamically to libqdutils
+// ----------------------------------------------------------------------------
+extern "C" int refreshScreen() {
+    int ret = 0;
+    ret = screenRefresh();
+    return ret;
+}
+
+// ----------------------------------------------------------------------------
+// Native daemons needs to send enable partial update ack for PU to enable
+// ----------------------------------------------------------------------------
+extern "C" int setPartialUpdateState() {
+    int ret = 0;
+    ret = setPartialUpdate(IQService::ENABLE_PARTIAL_UPDATE);
+    return ret;
+}
diff --git a/msm8909/libqdutils/display_config.h b/msm8909/libqdutils/display_config.h
new file mode 100644
index 0000000..e9b2fc3
--- /dev/null
+++ b/msm8909/libqdutils/display_config.h
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2013 The Linux Foundation. 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 The Linux Foundation. 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.
+ */
+#include <gralloc_priv.h>
+#include <qdMetaData.h>
+#include <mdp_version.h>
+#include <hardware/hwcomposer.h>
+
+// This header is for clients to use to set/get global display configuration
+// The functions in this header run in the client process and wherever necessary
+// do a binder call to HWC to get/set data.
+// Only primary and external displays are supported here.
+// WiFi/virtual displays are not supported.
+
+namespace qdutils {
+
+// Use this enum to specify the dpy parameters where needed
+enum {
+    DISPLAY_PRIMARY  = HWC_DISPLAY_PRIMARY,
+    DISPLAY_EXTERNAL = HWC_DISPLAY_EXTERNAL,
+    DISPLAY_VIRTUAL  = HWC_DISPLAY_VIRTUAL,
+};
+
+// External Display states - used in setSecondaryDisplayStatus()
+// To be consistent with the same defined in hwc_utils.h
+enum {
+    EXTERNAL_OFFLINE = 0,
+    EXTERNAL_ONLINE,
+    EXTERNAL_PAUSE,
+    EXTERNAL_RESUME,
+};
+
+enum {
+    DISABLE_METADATA_DYN_REFRESH_RATE = 0,
+    ENABLE_METADATA_DYN_REFRESH_RATE,
+    SET_BINDER_DYN_REFRESH_RATE,
+};
+
+// Display Attributes that are available to clients of this library
+// Not to be confused with a similar struct in hwc_utils (in the hwc namespace)
+struct DisplayAttributes_t {
+    uint32_t vsync_period; //nanoseconds
+    uint32_t xres;
+    uint32_t yres;
+    float xdpi;
+    float ydpi;
+    char panel_type;
+};
+
+// Check if external display is connected. Useful to check before making
+// calls for external displays
+// Returns 1 if connected, 0 if disconnected, negative values on errors
+int isExternalConnected(void);
+
+// Get display vsync period which is in nanoseconds
+// i.e vsync_period = 1000000000l / fps
+// Returns 0 on success, negative values on errors
+int getDisplayAttributes(int dpy, DisplayAttributes_t& dpyattr);
+
+// Set HSIC data on a given display ID
+// Returns 0 on success, negative values on errors
+int setHSIC(int dpy, const HSICData_t& hsic_data);
+
+// get the active visible region for the display
+// Returns 0 on success, negative values on errors
+int getDisplayVisibleRegion(int dpy, hwc_rect_t &rect);
+
+// set the view frame information in hwc context from surfaceflinger
+int setViewFrame(int dpy, int l, int t, int r, int b);
+
+// Set the secondary display status(pause/resume/offline etc.,)
+int setSecondaryDisplayStatus(int dpy, uint32_t status);
+
+// Enable/Disable/Set refresh rate dynamically
+int configureDynRefreshRate(uint32_t op, uint32_t refreshRate);
+}; //namespace
diff --git a/msm8909/libqdutils/idle_invalidator.cpp b/msm8909/libqdutils/idle_invalidator.cpp
new file mode 100644
index 0000000..b8db0bf
--- /dev/null
+++ b/msm8909/libqdutils/idle_invalidator.cpp
@@ -0,0 +1,149 @@
+/*
+ * Copyright (c) 2012, The Linux Foundation. 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 The Linux Foundation 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.
+ */
+
+#include "idle_invalidator.h"
+#include <unistd.h>
+#include <poll.h>
+#include <string.h>
+#include <fcntl.h>
+#include <cutils/properties.h>
+
+#define II_DEBUG 0
+#define IDLE_NOTIFY_PATH "/sys/devices/virtual/graphics/fb0/idle_notify"
+#define IDLE_TIME_PATH "/sys/devices/virtual/graphics/fb0/idle_time"
+
+
+static const char *threadName = "IdleInvalidator";
+InvalidatorHandler IdleInvalidator::mHandler = NULL;
+android::sp<IdleInvalidator> IdleInvalidator::sInstance(0);
+
+IdleInvalidator::IdleInvalidator(): Thread(false), mHwcContext(0),
+    mTimeoutEventFd(-1) {
+    ALOGD_IF(II_DEBUG, "IdleInvalidator::%s", __FUNCTION__);
+}
+
+IdleInvalidator::~IdleInvalidator() {
+    if(mTimeoutEventFd >= 0) {
+        close(mTimeoutEventFd);
+    }
+}
+
+int IdleInvalidator::init(InvalidatorHandler reg_handler, void* user_data) {
+    mHandler = reg_handler;
+    mHwcContext = user_data;
+
+    // Open a sysfs node to receive the timeout notification from driver.
+    mTimeoutEventFd = open(IDLE_NOTIFY_PATH, O_RDONLY);
+    if (mTimeoutEventFd < 0) {
+        ALOGE ("%s:not able to open %s node %s",
+                __FUNCTION__, IDLE_NOTIFY_PATH, strerror(errno));
+        return -1;
+    }
+
+    int defaultIdleTime = 70; //ms
+    char property[PROPERTY_VALUE_MAX] = {0};
+    if((property_get("debug.mdpcomp.idletime", property, NULL) > 0)) {
+        defaultIdleTime = atoi(property);
+    }
+    if(not setIdleTimeout(defaultIdleTime)) {
+        close(mTimeoutEventFd);
+        mTimeoutEventFd = -1;
+        return -1;
+    }
+
+    //Triggers the threadLoop to run, if not already running.
+    run(threadName, android::PRIORITY_LOWEST);
+    return 0;
+}
+
+bool IdleInvalidator::setIdleTimeout(const uint32_t& timeout) {
+    ALOGD_IF(II_DEBUG, "IdleInvalidator::%s timeout %d",
+            __FUNCTION__, timeout);
+
+    // Open a sysfs node to send the timeout value to driver.
+    int fd = open(IDLE_TIME_PATH, O_WRONLY);
+
+    if (fd < 0) {
+        ALOGE ("%s:Unable to open %s node %s",
+                __FUNCTION__, IDLE_TIME_PATH, strerror(errno));
+        return false;
+    }
+
+    char strSleepTime[64];
+    snprintf(strSleepTime, sizeof(strSleepTime), "%d", timeout);
+
+    // Notify driver about the timeout value
+    ssize_t len = pwrite(fd, strSleepTime, strlen(strSleepTime), 0);
+    if(len < -1) {
+        ALOGE ("%s:Unable to write into %s node %s",
+                __FUNCTION__, IDLE_TIME_PATH, strerror(errno));
+        close(fd);
+        return false;
+    }
+
+    close(fd);
+    return true;
+}
+
+bool IdleInvalidator::threadLoop() {
+    ALOGD_IF(II_DEBUG, "IdleInvalidator::%s", __FUNCTION__);
+    struct pollfd pFd;
+    pFd.fd = mTimeoutEventFd;
+    if (pFd.fd >= 0)
+        pFd.events = POLLPRI | POLLERR;
+    // Poll for an timeout event from driver
+    int err = poll(&pFd, 1, -1);
+    if(err > 0) {
+        if (pFd.revents & POLLPRI) {
+            char data[64];
+            // Consume the node by reading it
+            ssize_t len = pread(pFd.fd, data, 64, 0);
+            ALOGD_IF(II_DEBUG, "IdleInvalidator::%s Idle Timeout fired len %zd",
+                __FUNCTION__, len);
+            mHandler((void*)mHwcContext);
+        }
+    }
+    return true;
+}
+
+int IdleInvalidator::readyToRun() {
+    ALOGD_IF(II_DEBUG, "IdleInvalidator::%s", __FUNCTION__);
+    return 0; /*NO_ERROR*/
+}
+
+void IdleInvalidator::onFirstRef() {
+    ALOGD_IF(II_DEBUG, "IdleInvalidator::%s", __FUNCTION__);
+}
+
+IdleInvalidator *IdleInvalidator::getInstance() {
+    ALOGD_IF(II_DEBUG, "IdleInvalidator::%s", __FUNCTION__);
+    if(sInstance.get() == NULL)
+        sInstance = new IdleInvalidator();
+    return sInstance.get();
+}
diff --git a/msm8909/libqdutils/idle_invalidator.h b/msm8909/libqdutils/idle_invalidator.h
new file mode 100644
index 0000000..52334a0
--- /dev/null
+++ b/msm8909/libqdutils/idle_invalidator.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2012, The Linux Foundation. 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 The Linux Foundation 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 INCLUDE_IDLEINVALIDATOR
+#define INCLUDE_IDLEINVALIDATOR
+
+#include <cutils/log.h>
+#include <utils/threads.h>
+#include <gr.h>
+
+typedef void (*InvalidatorHandler)(void*);
+
+class IdleInvalidator : public android::Thread {
+    IdleInvalidator();
+    void *mHwcContext;
+    int mTimeoutEventFd;
+    static InvalidatorHandler mHandler;
+    static android::sp<IdleInvalidator> sInstance;
+
+public:
+    ~IdleInvalidator();
+    /* init timer obj */
+    int init(InvalidatorHandler reg_handler, void* user_data);
+    bool setIdleTimeout(const uint32_t& timeout);
+
+    /*Overrides*/
+    virtual bool        threadLoop();
+    virtual int         readyToRun();
+    virtual void        onFirstRef();
+    static IdleInvalidator *getInstance();
+};
+
+#endif // INCLUDE_IDLEINVALIDATOR
diff --git a/msm8909/libqdutils/mdp_version.cpp b/msm8909/libqdutils/mdp_version.cpp
new file mode 100644
index 0000000..088f82b
--- /dev/null
+++ b/msm8909/libqdutils/mdp_version.cpp
@@ -0,0 +1,489 @@
+/*
+ * Copyright (c) 2012-2014, The Linux Foundation. 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 The Linux Foundation 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.
+ */
+#include <cutils/log.h>
+#include <linux/msm_mdp.h>
+#include "mdp_version.h"
+#include "qd_utils.h"
+
+#define DEBUG 0
+
+ANDROID_SINGLETON_STATIC_INSTANCE(qdutils::MDPVersion);
+namespace qdutils {
+
+#define TOKEN_PARAMS_DELIM  "="
+
+// chip variants have same major number and minor numbers usually vary
+// for e.g., MDSS_MDP_HW_REV_101 is 0x10010000
+//                                    1001       -  major number
+//                                        0000   -  minor number
+// 8x26 v1 minor number is 0000
+//      v2 minor number is 0001 etc..
+#ifndef MDSS_MDP_HW_REV_100
+#define MDSS_MDP_HW_REV_100 0x10000000 //8974 v1
+#endif
+#ifndef MDSS_MDP_HW_REV_101
+#define MDSS_MDP_HW_REV_101 0x10010000 //8x26
+#endif
+#ifndef MDSS_MDP_HW_REV_102
+#define MDSS_MDP_HW_REV_102 0x10020000 //8974 v2
+#endif
+#ifndef MDSS_MDP_HW_REV_103
+#define MDSS_MDP_HW_REV_103 0x10030000 //8084
+#endif
+#ifndef MDSS_MDP_HW_REV_104
+#define MDSS_MDP_HW_REV_104 0x10040000 //Next version
+#endif
+#ifndef MDSS_MDP_HW_REV_105
+#define MDSS_MDP_HW_REV_105 0x10050000 //8994
+#endif
+#ifndef MDSS_MDP_HW_REV_106
+#define MDSS_MDP_HW_REV_106 0x10060000 //8x16
+#endif
+#ifndef MDSS_MDP_HW_REV_107
+#define MDSS_MDP_HW_REV_107 0x10070000 //Next version
+#endif
+#ifndef MDSS_MDP_HW_REV_108
+#define MDSS_MDP_HW_REV_108 0x10080000 //8x39 & 8x36
+#endif
+#ifndef MDSS_MDP_HW_REV_109
+#define MDSS_MDP_HW_REV_109 0x10090000 //Next version
+#endif
+#ifndef MDSS_MDP_HW_REV_200
+#define MDSS_MDP_HW_REV_200 0x20000000 //8092
+#endif
+#ifndef MDSS_MDP_HW_REV_206
+#define MDSS_MDP_HW_REV_206 0x20060000 //Future
+#endif
+
+MDPVersion::MDPVersion()
+{
+    mMDPVersion = MDSS_V5;
+    mMdpRev = 0;
+    mRGBPipes = 0;
+    mVGPipes = 0;
+    mDMAPipes = 0;
+    mFeatures = 0;
+    mMDPUpscale = 1;
+    mMDPDownscale = 1;
+    mMacroTileEnabled = false;
+    mLowBw = 0;
+    mHighBw = 0;
+    mSourceSplit = false;
+    mSourceSplitAlways = false;
+    mRGBHasNoScalar = false;
+    mRotDownscale = false;
+
+    // this is the default limit of mixer unless driver reports it.
+    // For resolutions beyond this, we use dual/split overlay pipes.
+    mMaxMixerWidth = 2048;
+
+    updatePanelInfo();
+
+    if(!updateSysFsInfo()) {
+        ALOGE("Unable to read display sysfs node");
+    }
+    if (mMdpRev == MDP_V3_0_4){
+        mMDPVersion = MDP_V3_0_4;
+    }
+    else if (mMdpRev == MDP_V3_0_5){
+        mMDPVersion = MDP_V3_0_5;
+    }
+
+    mHasOverlay = false;
+    if((mMDPVersion >= MDP_V4_0) ||
+       (mMDPVersion == MDP_V_UNKNOWN) ||
+       (mMDPVersion == MDP_V3_0_4) ||
+       (mMDPVersion == MDP_V3_0_5))
+        mHasOverlay = true;
+    if(!updateSplitInfo()) {
+        ALOGE("Unable to read display split node");
+    }
+}
+
+MDPVersion::~MDPVersion() {
+    close(mFd);
+}
+
+int MDPVersion::tokenizeParams(char *inputParams, const char *delim,
+                                char* tokenStr[], int *idx) {
+    char *tmp_token = NULL;
+    char *temp_ptr;
+    int index = 0;
+    if (!inputParams) {
+        return -1;
+    }
+    tmp_token = strtok_r(inputParams, delim, &temp_ptr);
+    while (tmp_token != NULL) {
+        tokenStr[index++] = tmp_token;
+        tmp_token = strtok_r(NULL, " ", &temp_ptr);
+    }
+    *idx = index;
+    return 0;
+}
+// This function reads the sysfs node to read the primary panel type
+// and updates information accordingly
+void  MDPVersion::updatePanelInfo() {
+    FILE *displayDeviceFP = NULL;
+    FILE *panelInfoNodeFP = NULL;
+    char fbType[MAX_FRAME_BUFFER_NAME_SIZE];
+    const char *strCmdPanel = "mipi dsi cmd panel";
+    const char *strVideoPanel = "mipi dsi video panel";
+    const char *strLVDSPanel = "lvds panel";
+    const char *strEDPPanel = "edp panel";
+
+    displayDeviceFP = fopen("/sys/class/graphics/fb0/msm_fb_type", "r");
+    if(displayDeviceFP){
+        fread(fbType, sizeof(char), MAX_FRAME_BUFFER_NAME_SIZE,
+                displayDeviceFP);
+        if(strncmp(fbType, strCmdPanel, strlen(strCmdPanel)) == 0) {
+            mPanelInfo.mType = MIPI_CMD_PANEL;
+        }
+        else if(strncmp(fbType, strVideoPanel, strlen(strVideoPanel)) == 0) {
+            mPanelInfo.mType = MIPI_VIDEO_PANEL;
+        }
+        else if(strncmp(fbType, strLVDSPanel, strlen(strLVDSPanel)) == 0) {
+            mPanelInfo.mType = LVDS_PANEL;
+        }
+        else if(strncmp(fbType, strEDPPanel, strlen(strEDPPanel)) == 0) {
+            mPanelInfo.mType = EDP_PANEL;
+        }
+        fclose(displayDeviceFP);
+    } else {
+        ALOGE("Unable to read Primary Panel Information");
+    }
+
+    panelInfoNodeFP = fopen("/sys/class/graphics/fb0/msm_fb_panel_info", "r");
+    if(panelInfoNodeFP){
+        size_t len = PAGE_SIZE;
+        ssize_t read;
+        char *readLine = (char *) malloc (len);
+        char property[PROPERTY_VALUE_MAX];
+        while((read = getline((char **)&readLine, &len,
+                              panelInfoNodeFP)) != -1) {
+            int token_ct=0;
+            char *tokens[10];
+            memset(tokens, 0, sizeof(tokens));
+
+            if(!tokenizeParams(readLine, TOKEN_PARAMS_DELIM, tokens,
+                               &token_ct)) {
+                if(!strncmp(tokens[0], "pu_en", strlen("pu_en"))) {
+                    mPanelInfo.mPartialUpdateEnable = atoi(tokens[1]);
+                    ALOGI("PartialUpdate status: %s",
+                          mPanelInfo.mPartialUpdateEnable? "Enabled" :
+                          "Disabled");
+                }
+                if(!strncmp(tokens[0], "xstart", strlen("xstart"))) {
+                    mPanelInfo.mLeftAlign = atoi(tokens[1]);
+                    ALOGI("Left Align: %d", mPanelInfo.mLeftAlign);
+                }
+                if(!strncmp(tokens[0], "walign", strlen("walign"))) {
+                    mPanelInfo.mWidthAlign = atoi(tokens[1]);
+                    ALOGI("Width Align: %d", mPanelInfo.mWidthAlign);
+                }
+                if(!strncmp(tokens[0], "ystart", strlen("ystart"))) {
+                    mPanelInfo.mTopAlign = atoi(tokens[1]);
+                    ALOGI("Top Align: %d", mPanelInfo.mTopAlign);
+                }
+                if(!strncmp(tokens[0], "halign", strlen("halign"))) {
+                    mPanelInfo.mHeightAlign = atoi(tokens[1]);
+                    ALOGI("Height Align: %d", mPanelInfo.mHeightAlign);
+                }
+                if(!strncmp(tokens[0], "min_w", strlen("min_w"))) {
+                    mPanelInfo.mMinROIWidth = atoi(tokens[1]);
+                    ALOGI("Min ROI Width: %d", mPanelInfo.mMinROIWidth);
+                }
+                if(!strncmp(tokens[0], "min_h", strlen("min_h"))) {
+                    mPanelInfo.mMinROIHeight = atoi(tokens[1]);
+                    ALOGI("Min ROI Height: %d", mPanelInfo.mMinROIHeight);
+                }
+                if(!strncmp(tokens[0], "roi_merge", strlen("roi_merge"))) {
+                    mPanelInfo.mNeedsROIMerge = atoi(tokens[1]);
+                    ALOGI("Needs ROI Merge: %d", mPanelInfo.mNeedsROIMerge);
+                }
+                if(!strncmp(tokens[0], "dyn_fps_en", strlen("dyn_fps_en"))) {
+                    mPanelInfo.mDynFpsSupported = atoi(tokens[1]);
+                    ALOGI("Dynamic Fps: %s", mPanelInfo.mDynFpsSupported ?
+                                            "Enabled" : "Disabled");
+                }
+                if(!strncmp(tokens[0], "min_fps", strlen("min_fps"))) {
+                    mPanelInfo.mMinFps = atoi(tokens[1]);
+                    ALOGI("Min Panel fps: %d", mPanelInfo.mMinFps);
+                }
+                if(!strncmp(tokens[0], "max_fps", strlen("max_fps"))) {
+                    mPanelInfo.mMaxFps = atoi(tokens[1]);
+                    ALOGI("Max Panel fps: %d", mPanelInfo.mMaxFps);
+                }
+            }
+        }
+        if((property_get("persist.hwc.pubypass", property, 0) > 0) &&
+            (!strncmp(property, "1", PROPERTY_VALUE_MAX ) ||
+            (!strncasecmp(property,"true", PROPERTY_VALUE_MAX )))) {
+                mPanelInfo.mPartialUpdateEnable = 0;
+                ALOGI("PartialUpdate disabled by property");
+        }
+        fclose(panelInfoNodeFP);
+    } else {
+        ALOGE("Failed to open msm_fb_panel_info node");
+    }
+}
+
+// This function reads the sysfs node to read MDP capabilities
+// and parses and updates information accordingly.
+bool MDPVersion::updateSysFsInfo() {
+    FILE *sysfsFd;
+    size_t len = PAGE_SIZE;
+    ssize_t read;
+    char *line = NULL;
+    char sysfsPath[255];
+    memset(sysfsPath, 0, sizeof(sysfsPath));
+    snprintf(sysfsPath , sizeof(sysfsPath),
+            "/sys/class/graphics/fb0/mdp/caps");
+    char property[PROPERTY_VALUE_MAX];
+    bool enableMacroTile = false;
+
+    if((property_get("persist.hwc.macro_tile_enable", property, NULL) > 0) &&
+       (!strncmp(property, "1", PROPERTY_VALUE_MAX ) ||
+        (!strncasecmp(property,"true", PROPERTY_VALUE_MAX )))) {
+        enableMacroTile = true;
+    }
+
+    sysfsFd = fopen(sysfsPath, "rb");
+
+    if (sysfsFd == NULL) {
+        ALOGE("%s: sysFsFile file '%s' not found",
+                __FUNCTION__, sysfsPath);
+        return false;
+    } else {
+        line = (char *) malloc(len);
+        while((read = getline(&line, &len, sysfsFd)) != -1) {
+            int index=0;
+            char *tokens[10];
+            memset(tokens, 0, sizeof(tokens));
+
+            // parse the line and update information accordingly
+            if(!tokenizeParams(line, TOKEN_PARAMS_DELIM, tokens, &index)) {
+                if(!strncmp(tokens[0], "hw_rev", strlen("hw_rev"))) {
+                    mMdpRev = atoi(tokens[1]);
+                }
+                else if(!strncmp(tokens[0], "rgb_pipes", strlen("rgb_pipes"))) {
+                    mRGBPipes = (uint8_t)atoi(tokens[1]);
+                }
+                else if(!strncmp(tokens[0], "vig_pipes", strlen("vig_pipes"))) {
+                    mVGPipes = (uint8_t)atoi(tokens[1]);
+                }
+                else if(!strncmp(tokens[0], "dma_pipes", strlen("dma_pipes"))) {
+                    mDMAPipes = (uint8_t)atoi(tokens[1]);
+                }
+                else if(!strncmp(tokens[0], "max_downscale_ratio",
+                                strlen("max_downscale_ratio"))) {
+                    mMDPDownscale = atoi(tokens[1]);
+                }
+                else if(!strncmp(tokens[0], "max_upscale_ratio",
+                                strlen("max_upscale_ratio"))) {
+                    mMDPUpscale = atoi(tokens[1]);
+                } else if(!strncmp(tokens[0], "max_bandwidth_low",
+                        strlen("max_bandwidth_low"))) {
+                    mLowBw = atol(tokens[1]);
+                } else if(!strncmp(tokens[0], "max_bandwidth_high",
+                        strlen("max_bandwidth_high"))) {
+                    mHighBw = atol(tokens[1]);
+                } else if(!strncmp(tokens[0], "max_mixer_width",
+                        strlen("max_mixer_width"))) {
+                    mMaxMixerWidth = atoi(tokens[1]);
+                } else if(!strncmp(tokens[0], "features", strlen("features"))) {
+                    for(int i=1; i<index;i++) {
+                        if(!strncmp(tokens[i], "bwc", strlen("bwc"))) {
+                           mFeatures |= MDP_BWC_EN;
+                        } else if(!strncmp(tokens[i], "decimation",
+                                    strlen("decimation"))) {
+                           mFeatures |= MDP_DECIMATION_EN;
+                        } else if(!strncmp(tokens[i], "tile_format",
+                                    strlen("tile_format"))) {
+                           if(enableMacroTile)
+                               mMacroTileEnabled = true;
+                        } else if(!strncmp(tokens[i], "src_split",
+                                    strlen("src_split"))) {
+                            mSourceSplit = true;
+                        } else if(!strncmp(tokens[i], "non_scalar_rgb",
+                                    strlen("non_scalar_rgb"))) {
+                            mRGBHasNoScalar = true;
+                        } else if(!strncmp(tokens[i], "rotator_downscale",
+                                    strlen("rotator_downscale"))) {
+                            mRotDownscale = true;
+                        }
+                    }
+                }
+            }
+        }
+        free(line);
+        fclose(sysfsFd);
+    }
+
+    if(mMDPVersion >= qdutils::MDP_V4_2 and mMDPVersion < qdutils::MDSS_V5) {
+        mRotDownscale = true;
+    }
+
+    if(mSourceSplit) {
+        memset(sysfsPath, 0, sizeof(sysfsPath));
+        snprintf(sysfsPath , sizeof(sysfsPath),
+                "/sys/class/graphics/fb0/msm_fb_src_split_info");
+
+        sysfsFd = fopen(sysfsPath, "rb");
+        if (sysfsFd == NULL) {
+            ALOGE("%s: Opening file %s failed with error %s", __FUNCTION__,
+                    sysfsPath, strerror(errno));
+            return false;
+        } else {
+            line = (char *) malloc(len);
+            if((read = getline(&line, &len, sysfsFd)) != -1) {
+                if(!strncmp(line, "src_split_always",
+                        strlen("src_split_always"))) {
+                    mSourceSplitAlways = true;
+                }
+            }
+            free(line);
+            fclose(sysfsFd);
+        }
+    }
+
+    ALOGD_IF(DEBUG, "%s: mMDPVersion: %d mMdpRev: %x mRGBPipes:%d,"
+                    "mVGPipes:%d", __FUNCTION__, mMDPVersion, mMdpRev,
+                    mRGBPipes, mVGPipes);
+    ALOGD_IF(DEBUG, "%s:mDMAPipes:%d \t mMDPDownscale:%d, mFeatures:%d",
+                     __FUNCTION__,  mDMAPipes, mMDPDownscale, mFeatures);
+    ALOGD_IF(DEBUG, "%s:mLowBw: %lu mHighBw: %lu", __FUNCTION__,  mLowBw,
+            mHighBw);
+
+    return true;
+}
+
+// This function reads the sysfs node to read MDP capabilities
+// and parses and updates information accordingly.
+bool MDPVersion::updateSplitInfo() {
+    if(mMDPVersion >= MDSS_V5) {
+        char split[64] = {0};
+        FILE* fp = fopen("/sys/class/graphics/fb0/msm_fb_split", "r");
+        if(fp){
+            //Format "left right" space as delimiter
+            if(fread(split, sizeof(char), 64, fp)) {
+                split[sizeof(split) - 1] = '\0';
+                mSplit.mLeft = atoi(split);
+                ALOGI_IF(mSplit.mLeft, "Left Split=%d", mSplit.mLeft);
+                char *rght = strpbrk(split, " ");
+                if(rght)
+                    mSplit.mRight = atoi(rght + 1);
+                ALOGI_IF(mSplit.mRight, "Right Split=%d", mSplit.mRight);
+            }
+        } else {
+            ALOGE("Failed to open mdss_fb_split node");
+            return false;
+        }
+        if(fp)
+            fclose(fp);
+    }
+    return true;
+}
+
+
+bool MDPVersion::hasMinCropWidthLimitation() const {
+    return mMdpRev <= MDSS_MDP_HW_REV_102;
+}
+
+bool MDPVersion::supportsDecimation() {
+    return mFeatures & MDP_DECIMATION_EN;
+}
+
+uint32_t MDPVersion::getMaxMDPDownscale() {
+    return mMDPDownscale;
+}
+
+uint32_t MDPVersion::getMaxMDPUpscale() {
+    return mMDPUpscale;
+}
+
+bool MDPVersion::supportsBWC() {
+    // BWC - Bandwidth Compression
+    return (mFeatures & MDP_BWC_EN);
+}
+
+bool MDPVersion::supportsMacroTile() {
+    // MACRO TILE support
+    return mMacroTileEnabled;
+}
+
+bool MDPVersion::isSrcSplit() const {
+    return mSourceSplit;
+}
+
+bool MDPVersion::isSrcSplitAlways() const {
+    return mSourceSplitAlways;
+}
+
+bool MDPVersion::isRGBScalarSupported() const {
+    return (!mRGBHasNoScalar);
+}
+
+bool MDPVersion::is8x26() {
+    return (mMdpRev >= MDSS_MDP_HW_REV_101 and
+            mMdpRev < MDSS_MDP_HW_REV_102);
+}
+
+bool MDPVersion::is8x74v2() {
+    return (mMdpRev >= MDSS_MDP_HW_REV_102 and
+            mMdpRev < MDSS_MDP_HW_REV_103);
+}
+
+bool MDPVersion::is8084() {
+    return (mMdpRev >= MDSS_MDP_HW_REV_103 and
+            mMdpRev < MDSS_MDP_HW_REV_104);
+}
+
+bool MDPVersion::is8092() {
+    return (mMdpRev >= MDSS_MDP_HW_REV_200 and
+            mMdpRev < MDSS_MDP_HW_REV_206);
+}
+
+bool MDPVersion::is8994() {
+    return (mMdpRev >= MDSS_MDP_HW_REV_105 and
+            mMdpRev < MDSS_MDP_HW_REV_106);
+}
+
+bool MDPVersion::is8x16() {
+    return (mMdpRev >= MDSS_MDP_HW_REV_106 and
+            mMdpRev < MDSS_MDP_HW_REV_107);
+}
+
+bool MDPVersion::is8x39() {
+    return (mMdpRev >= MDSS_MDP_HW_REV_108 and
+            mMdpRev < MDSS_MDP_HW_REV_109);
+}
+
+
+}; //namespace qdutils
+
diff --git a/msm8909/libqdutils/mdp_version.h b/msm8909/libqdutils/mdp_version.h
new file mode 100644
index 0000000..3c7f6a3
--- /dev/null
+++ b/msm8909/libqdutils/mdp_version.h
@@ -0,0 +1,182 @@
+/*
+ * Copyright (c) 2012-2013, The Linux Foundation. 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 The Linux Foundation 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 INCLUDE_LIBQCOMUTILS_MDPVER
+#define INCLUDE_LIBQCOMUTILS_MDPVER
+
+#include <stdint.h>
+#include <utils/Singleton.h>
+#include <cutils/properties.h>
+
+/* This class gets the MSM type from the soc info
+*/
+using namespace android;
+namespace qdutils {
+// These panel definitions are available at mdss_mdp.h which is internal header
+// file and is not available at <linux/mdss_mdp.h>.
+// ToDo: once it is available at linux/mdss_mdp.h, these below definitions can
+// be removed.
+enum mdp_version {
+    MDP_V_UNKNOWN = 0,
+    MDP_V2_2    = 220,
+    MDP_V3_0    = 300,
+    MDP_V3_0_3  = 303,
+    MDP_V3_0_4  = 304,
+    MDP_V3_0_5  = 305,
+    MDP_V3_1    = 310,
+    MDP_V4_0    = 400,
+    MDP_V4_1    = 410,
+    MDP_V4_2    = 420,
+    MDP_V4_3    = 430,
+    MDP_V4_4    = 440,
+    MDSS_V5     = 500,
+};
+
+#define NO_PANEL         '0'
+#define MDDI_PANEL       '1'
+#define EBI2_PANEL       '2'
+#define LCDC_PANEL       '3'
+#define EXT_MDDI_PANEL   '4'
+#define TV_PANEL         '5'
+#define DTV_PANEL        '7'
+#define MIPI_VIDEO_PANEL '8'
+#define MIPI_CMD_PANEL   '9'
+#define WRITEBACK_PANEL  'a'
+#define LVDS_PANEL       'b'
+#define EDP_PANEL        'c'
+
+class MDPVersion;
+
+struct Split {
+    int mLeft;
+    int mRight;
+    Split() : mLeft(0), mRight(0){}
+    int left() { return mLeft; }
+    int right() { return mRight; }
+    friend class MDPVersion;
+};
+
+struct PanelInfo {
+    char mType;                  // Smart or Dumb
+    int mPartialUpdateEnable;    // Partial update feature
+    int mLeftAlign;              // ROI left alignment restriction
+    int mWidthAlign;             // ROI width alignment restriction
+    int mTopAlign;               // ROI top alignment restriction
+    int mHeightAlign;            // ROI height alignment restriction
+    int mMinROIWidth;            // Min width needed for ROI
+    int mMinROIHeight;           // Min height needed for ROI
+    bool mNeedsROIMerge;         // Merge ROI's of both the DSI's
+    bool mDynFpsSupported;       // Panel Supports dyn fps
+    uint32_t mMinFps;            // Min fps supported by panel
+    uint32_t mMaxFps;            // Max fps supported by panel
+    PanelInfo() : mType(NO_PANEL), mPartialUpdateEnable(0),
+    mLeftAlign(0), mWidthAlign(0), mTopAlign(0), mHeightAlign(0),
+    mMinROIWidth(0), mMinROIHeight(0), mNeedsROIMerge(false),
+    mDynFpsSupported(0), mMinFps(0), mMaxFps(0) {}
+    friend class MDPVersion;
+};
+
+class MDPVersion : public Singleton <MDPVersion>
+{
+public:
+    MDPVersion();
+    ~MDPVersion();
+    int getMDPVersion() {return mMDPVersion;}
+    char getPanelType() {return mPanelInfo.mType;}
+    bool hasOverlay() {return mHasOverlay;}
+    uint8_t getTotalPipes() {
+        return (uint8_t)(mRGBPipes + mVGPipes + mDMAPipes);
+    }
+    uint8_t getRGBPipes() { return mRGBPipes; }
+    uint8_t getVGPipes() { return mVGPipes; }
+    uint8_t getDMAPipes() { return mDMAPipes; }
+    bool supportsDecimation();
+    uint32_t getMaxMDPDownscale();
+    uint32_t getMaxMDPUpscale();
+    bool supportsBWC();
+    bool supportsMacroTile();
+    int getLeftSplit() { return mSplit.left(); }
+    int getRightSplit() { return mSplit.right(); }
+    bool isPartialUpdateEnabled() { return mPanelInfo.mPartialUpdateEnable; }
+    int getLeftAlign() { return mPanelInfo.mLeftAlign; }
+    int getWidthAlign() { return mPanelInfo.mWidthAlign; }
+    int getTopAlign() { return mPanelInfo.mTopAlign; }
+    int getHeightAlign() { return mPanelInfo.mHeightAlign; }
+    int getMinROIWidth() { return mPanelInfo.mMinROIWidth; }
+    int getMinROIHeight() { return mPanelInfo.mMinROIHeight; }
+    bool needsROIMerge() { return mPanelInfo.mNeedsROIMerge; }
+    unsigned long getLowBw() { return mLowBw; }
+    unsigned long getHighBw() { return mHighBw; }
+    bool isRotDownscaleEnabled() { return mRotDownscale; }
+    bool isDynFpsSupported() { return mPanelInfo.mDynFpsSupported; }
+    uint32_t getMinFpsSupported() { return mPanelInfo.mMinFps; }
+    uint32_t getMaxFpsSupported() { return mPanelInfo.mMaxFps; }
+    uint32_t getMaxMixerWidth() const { return mMaxMixerWidth; }
+    bool hasMinCropWidthLimitation() const;
+    bool isSrcSplit() const;
+    bool isSrcSplitAlways() const;
+    bool isRGBScalarSupported() const;
+    bool is8x26();
+    bool is8x74v2();
+    bool is8084();
+    bool is8092();
+    bool is8994();
+    bool is8x16();
+    bool is8x39();
+
+private:
+    bool updateSysFsInfo();
+    void updatePanelInfo();
+    bool updateSplitInfo();
+    int tokenizeParams(char *inputParams, const char *delim,
+                        char* tokenStr[], int *idx);
+    int mFd;
+    int mMDPVersion;
+    bool mHasOverlay;
+    uint32_t mMdpRev;
+    uint8_t mRGBPipes;
+    uint8_t mVGPipes;
+    uint8_t mDMAPipes;
+    uint32_t mFeatures;
+    uint32_t mMDPDownscale;
+    uint32_t mMDPUpscale;
+    bool mMacroTileEnabled;
+    Split mSplit;
+    PanelInfo mPanelInfo;
+    unsigned long mLowBw; //kbps
+    unsigned long mHighBw; //kbps
+    bool mSourceSplit;
+    //Additional property on top of source split
+    bool mSourceSplitAlways;
+    bool mRGBHasNoScalar;
+    bool mRotDownscale;
+    uint32_t mMaxMixerWidth; //maximum x-res of a given mdss mixer.
+};
+}; //namespace qdutils
+#endif //INCLUDE_LIBQCOMUTILS_MDPVER
diff --git a/msm8909/libqdutils/profiler.cpp b/msm8909/libqdutils/profiler.cpp
new file mode 100644
index 0000000..810b019
--- /dev/null
+++ b/msm8909/libqdutils/profiler.cpp
@@ -0,0 +1,197 @@
+/*
+ * Copyright (c) 2011-2012, The Linux Foundation. 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 The Linux Foundation 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.
+ */
+
+#define LOG_NDDEBUG 0
+#define __STDC_FORMAT_MACROS 1
+#include <inttypes.h>
+
+#include "profiler.h"
+
+#ifdef DEBUG_CALC_FPS
+
+
+ANDROID_SINGLETON_STATIC_INSTANCE(qdutils::CalcFps) ;
+
+namespace qdutils {
+
+CalcFps::CalcFps() {
+    debug_fps_level = 0;
+    Init();
+}
+
+CalcFps::~CalcFps() {
+}
+
+void CalcFps::Init() {
+    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) {
+        ALOGW("out of range value for debug.gr.calcfps, using 0");
+        debug_fps_level = 0;
+    }
+
+    ALOGD("DEBUG_CALC_FPS: %d", debug_fps_level);
+    populate_debug_fps_metadata();
+}
+
+void CalcFps::Fps() {
+    if (debug_fps_level > 0)
+        calc_fps(ns2us(systemTime()));
+}
+
+void CalcFps::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 =
+        (unsigned int)(debug_fps_metadata.ignorethresh_us / 16666);
+
+    if (debug_fps_metadata.framearrival_steps > MAX_FRAMEARRIVAL_STEPS) {
+        debug_fps_metadata.framearrival_steps = MAX_FRAMEARRIVAL_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 (unsigned int i = 0; i < MAX_FRAMEARRIVAL_STEPS; i++)
+        debug_fps_metadata.accum_framearrivals[i] = 0;
+
+    debug_fps_metadata.curr_frame = 0;
+
+    ALOGD("period: %u", debug_fps_metadata.period);
+    ALOGD("ignorethresh_us: %" PRId64, debug_fps_metadata.ignorethresh_us);
+}
+
+void CalcFps::print_fps(float fps)
+{
+    if (debug_fps_metadata_t::DFM_FRAMES == debug_fps_metadata.type)
+        ALOGD("FPS for last %d frames: %3.2f", debug_fps_metadata.period, fps);
+    else
+        ALOGD("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) {
+        ALOGD("Frame Arrival Distribution:");
+        for (unsigned int i = 0;
+             i < ((debug_fps_metadata.framearrival_steps / 6) + 1);
+             i++) {
+            ALOGD("%" PRId64" %" PRId64" %" PRId64" %" PRId64" %" PRId64" %" PRId64,
+                  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;
+}
+
+void CalcFps::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;
+    }
+
+    debug_fps_metadata.curr_frame++;
+
+    if (debug_fps_level > 1) {
+        unsigned int currstep =
+            (unsigned int)(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(float(float(debug_fps_metadata.period * 1000000) /
+                                                              (float)sum));
+        }
+    }
+    else if (debug_fps_metadata_t::DFM_TIME == debug_fps_metadata.type) {
+        debug_fps_metadata.time_elapsed += (float)((float)diff/1000.0);
+        if (debug_fps_metadata.time_elapsed >= debug_fps_metadata.time_period) {
+            float fps = float(1000.0 * debug_fps_metadata.curr_frame/
+                                            debug_fps_metadata.time_elapsed);
+            print_fps(fps);
+        }
+    }
+    return;
+}
+};//namespace qomutils
+#endif
diff --git a/msm8909/libqdutils/profiler.h b/msm8909/libqdutils/profiler.h
new file mode 100644
index 0000000..5f270b0
--- /dev/null
+++ b/msm8909/libqdutils/profiler.h
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2011-2012, The Linux Foundation. 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 The Linux Foundation 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 INCLUDE_PROFILER
+#define INCLUDE_PROFILER
+
+#include <stdio.h>
+#include <utils/Singleton.h>
+#include <cutils/properties.h>
+#include <cutils/log.h>
+
+#ifndef DEBUG_CALC_FPS
+#define CALC_FPS() ((void)0)
+#define CALC_INIT() ((void)0)
+#else
+#define CALC_FPS() qdutils::CalcFps::getInstance().Fps()
+#define CALC_INIT() qdutils::CalcFps::getInstance().Init()
+using namespace android;
+namespace qdutils {
+class CalcFps : public Singleton<CalcFps> {
+    public:
+    CalcFps();
+    ~CalcFps();
+
+    void Init();
+    void Fps();
+
+    private:
+    static const unsigned int MAX_FPS_CALC_PERIOD_IN_FRAMES = 128;
+    static const unsigned int MAX_FRAMEARRIVAL_STEPS = 50;
+    static const unsigned int 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_FRAMEARRIVAL_STEPS];
+    };
+
+    private:
+    void populate_debug_fps_metadata(void);
+    void print_fps(float fps);
+    void calc_fps(nsecs_t currtime_us);
+
+    private:
+    debug_fps_metadata_t debug_fps_metadata;
+    unsigned int debug_fps_level;
+};
+};//namespace qdutils
+#endif
+
+#endif // INCLUDE_PROFILER
diff --git a/msm8909/libqdutils/qdMetaData.cpp b/msm8909/libqdutils/qdMetaData.cpp
new file mode 100644
index 0000000..88109c9
--- /dev/null
+++ b/msm8909/libqdutils/qdMetaData.cpp
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2012-2014, The Linux Foundation. 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 The Linux Foundation 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.
+ */
+
+#include <errno.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <cutils/log.h>
+#include <gralloc_priv.h>
+#define __STDC_FORMAT_MACROS 1
+#include <inttypes.h>
+#include "qdMetaData.h"
+
+int setMetaData(private_handle_t *handle, DispParamType paramType,
+                                                    void *param) {
+    if (!handle) {
+        ALOGE("%s: Private handle is null!", __func__);
+        return -1;
+    }
+    if (handle->fd_metadata == -1) {
+        ALOGE("%s: Bad fd for extra data!", __func__);
+        return -1;
+    }
+    if (!param) {
+        ALOGE("%s: input param is null!", __func__);
+        return -1;
+    }
+    unsigned long size = ROUND_UP_PAGESIZE(sizeof(MetaData_t));
+    void *base = mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_SHARED,
+        handle->fd_metadata, 0);
+    if (base == reinterpret_cast<void*>(MAP_FAILED)) {
+        ALOGE("%s: mmap() failed: error is %s!", __func__, strerror(errno));
+        return -1;
+    }
+    MetaData_t *data = reinterpret_cast <MetaData_t *>(base);
+    data->operation |= paramType;
+    switch (paramType) {
+        case PP_PARAM_HSIC:
+            memcpy((void *)&data->hsicData, param, sizeof(HSICData_t));
+            break;
+        case PP_PARAM_SHARPNESS:
+            data->sharpness = *((int32_t *)param);
+            break;
+        case PP_PARAM_VID_INTFC:
+            data->video_interface = *((int32_t *)param);
+            break;
+        case PP_PARAM_INTERLACED:
+            data->interlaced = *((int32_t *)param);
+            break;
+        case PP_PARAM_IGC:
+            memcpy((void *)&data->igcData, param, sizeof(IGCData_t));
+            break;
+        case PP_PARAM_SHARP2:
+            memcpy((void *)&data->Sharp2Data, param, sizeof(Sharp2Data_t));
+            break;
+        case PP_PARAM_TIMESTAMP:
+            data->timestamp = *((int64_t *)param);
+            break;
+        case UPDATE_BUFFER_GEOMETRY:
+            memcpy((void *)&data->bufferDim, param, sizeof(BufferDim_t));
+            break;
+        case UPDATE_REFRESH_RATE:
+            data->refreshrate = *((uint32_t *)param);
+            break;
+        case UPDATE_COLOR_SPACE:
+            data->colorSpace = *((ColorSpace_t *)param);
+            break;
+        case MAP_SECURE_BUFFER:
+            data->mapSecureBuffer = *((int32_t *)param);
+            break;
+        default:
+            ALOGE("Unknown paramType %d", paramType);
+            break;
+    }
+    if(munmap(base, size))
+        ALOGE("%s: failed to unmap ptr %p, err %d", __func__, (void*)base,
+                                                                        errno);
+    return 0;
+}
diff --git a/msm8909/libqdutils/qdMetaData.h b/msm8909/libqdutils/qdMetaData.h
new file mode 100644
index 0000000..32d788e
--- /dev/null
+++ b/msm8909/libqdutils/qdMetaData.h
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2012-2014, The Linux Foundation. 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 The Linux Foundation 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 _QDMETADATA_H
+#define _QDMETADATA_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define MAX_IGC_LUT_ENTRIES 256
+
+enum ColorSpace_t{
+    ITU_R_601,
+    ITU_R_601_FR,
+    ITU_R_709,
+};
+
+struct HSICData_t {
+    int32_t hue;
+    float   saturation;
+    int32_t intensity;
+    float   contrast;
+};
+
+struct Sharp2Data_t {
+    int32_t strength;
+    uint32_t edge_thr;
+    uint32_t smooth_thr;
+    uint32_t noise_thr;
+};
+
+struct IGCData_t{
+    uint16_t c0[MAX_IGC_LUT_ENTRIES];
+    uint16_t c1[MAX_IGC_LUT_ENTRIES];
+    uint16_t c2[MAX_IGC_LUT_ENTRIES];
+};
+
+struct BufferDim_t {
+    int32_t sliceWidth;
+    int32_t sliceHeight;
+};
+
+struct MetaData_t {
+    int32_t operation;
+    int32_t interlaced;
+    struct BufferDim_t bufferDim;
+    struct HSICData_t hsicData;
+    int32_t sharpness;
+    int32_t video_interface;
+    struct IGCData_t igcData;
+    struct Sharp2Data_t Sharp2Data;
+    int64_t timestamp;
+    uint32_t refreshrate;
+    enum ColorSpace_t colorSpace;
+     /* Gralloc sets PRIV_SECURE_BUFFER flag to inform that the buffers are from
+      * ION_SECURE. which should not be mapped. However, for GPU post proc
+      * feature, GFX needs to map this buffer, in the client context and in SF
+      * context, it should not. Hence to differentiate, add this metadata field
+      * for clients to set, and GPU will to read and know when to map the
+      * SECURE_BUFFER(ION) */
+    int32_t mapSecureBuffer;
+};
+
+enum DispParamType {
+    PP_PARAM_HSIC       = 0x0001,
+    PP_PARAM_SHARPNESS  = 0x0002,
+    PP_PARAM_INTERLACED = 0x0004,
+    PP_PARAM_VID_INTFC  = 0x0008,
+    PP_PARAM_IGC        = 0x0010,
+    PP_PARAM_SHARP2     = 0x0020,
+    PP_PARAM_TIMESTAMP  = 0x0040,
+    UPDATE_BUFFER_GEOMETRY = 0x0080,
+    UPDATE_REFRESH_RATE = 0x0100,
+    UPDATE_COLOR_SPACE = 0x0200,
+    MAP_SECURE_BUFFER = 0x400,
+};
+
+struct private_handle_t;
+int setMetaData(struct private_handle_t *handle, enum DispParamType paramType,
+        void *param);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _QDMETADATA_H */
+
diff --git a/msm8909/libqdutils/qd_utils.cpp b/msm8909/libqdutils/qd_utils.cpp
new file mode 100644
index 0000000..5726202
--- /dev/null
+++ b/msm8909/libqdutils/qd_utils.cpp
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 2013, The Linux Foundation. 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 The Linux Foundation 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.
+ */
+
+#include "qd_utils.h"
+#define QD_UTILS_DEBUG 0
+
+namespace qdutils {
+
+int getHDMINode(void)
+{
+    FILE *displayDeviceFP = NULL;
+    char fbType[MAX_FRAME_BUFFER_NAME_SIZE];
+    char msmFbTypePath[MAX_FRAME_BUFFER_NAME_SIZE];
+    int j = 0;
+
+    for(j = 0; j < HWC_NUM_DISPLAY_TYPES; j++) {
+        snprintf (msmFbTypePath, sizeof(msmFbTypePath),
+                  "/sys/class/graphics/fb%d/msm_fb_type", j);
+        displayDeviceFP = fopen(msmFbTypePath, "r");
+        if(displayDeviceFP) {
+            fread(fbType, sizeof(char), MAX_FRAME_BUFFER_NAME_SIZE,
+                    displayDeviceFP);
+            if(strncmp(fbType, "dtv panel", strlen("dtv panel")) == 0) {
+                ALOGD("%s: HDMI is at fb%d", __func__, j);
+                fclose(displayDeviceFP);
+                break;
+            }
+            fclose(displayDeviceFP);
+        } else {
+            ALOGE("%s: Failed to open fb node %d", __func__, j);
+        }
+    }
+
+    if (j < HWC_NUM_DISPLAY_TYPES)
+        return j;
+    else
+        ALOGE("%s: Failed to find HDMI node", __func__);
+
+    return -1;
+}
+
+int getEdidRawData(char *buffer)
+{
+    int size;
+    int edidFile;
+    char msmFbTypePath[MAX_FRAME_BUFFER_NAME_SIZE];
+    int node_id = getHDMINode();
+
+    if (node_id < 0) {
+        ALOGE("%s no HDMI node found", __func__);
+        return 0;
+    }
+
+    snprintf(msmFbTypePath, sizeof(msmFbTypePath),
+                 "/sys/class/graphics/fb%d/edid_raw_data", node_id);
+
+   edidFile = open(msmFbTypePath, O_RDONLY, 0);
+
+    if (edidFile < 0) {
+        ALOGE("%s no edid raw data found", __func__);
+        return 0;
+    }
+
+    size = (int)read(edidFile, (char*)buffer, EDID_RAW_DATA_SIZE);
+    close(edidFile);
+    return size;
+}
+
+/* Calculates the aspect ratio for based on src & dest */
+void getAspectRatioPosition(int destWidth, int destHeight, int srcWidth,
+                                int srcHeight, hwc_rect_t& rect) {
+   int x =0, y =0;
+
+   if (srcWidth * destHeight > destWidth * srcHeight) {
+        srcHeight = destWidth * srcHeight / srcWidth;
+        srcWidth = destWidth;
+    } else if (srcWidth * destHeight < destWidth * srcHeight) {
+        srcWidth = destHeight * srcWidth / srcHeight;
+        srcHeight = destHeight;
+    } else {
+        srcWidth = destWidth;
+        srcHeight = destHeight;
+    }
+    if (srcWidth > destWidth) srcWidth = destWidth;
+    if (srcHeight > destHeight) srcHeight = destHeight;
+    x = (destWidth - srcWidth) / 2;
+    y = (destHeight - srcHeight) / 2;
+    ALOGD_IF(QD_UTILS_DEBUG, "%s: AS Position: x = %d, y = %d w = %d h = %d",
+             __FUNCTION__, x, y, srcWidth , srcHeight);
+    // Convert it back to hwc_rect_t
+    rect.left = x;
+    rect.top = y;
+    rect.right = srcWidth + rect.left;
+    rect.bottom = srcHeight + rect.top;
+}
+
+}; //namespace qdutils
diff --git a/msm8909/libqdutils/qd_utils.h b/msm8909/libqdutils/qd_utils.h
new file mode 100644
index 0000000..1d4bc19
--- /dev/null
+++ b/msm8909/libqdutils/qd_utils.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2013, The Linux Foundation. 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 The Linux Foundation or 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 _QD_UTIL_MISC_H
+#define _QD_UTIL_MISC_H
+
+#include <utils/threads.h>
+#include <linux/fb.h>
+#include <ctype.h>
+#include <fcntl.h>
+#include <utils/Errors.h>
+#include <utils/Log.h>
+
+#include <linux/fb.h>
+#include <sys/ioctl.h>
+#include <sys/poll.h>
+#include <sys/resource.h>
+#include <cutils/properties.h>
+#include <hardware/hwcomposer.h>
+
+namespace qdutils {
+#define EDID_RAW_DATA_SIZE              640
+
+enum qd_utils {
+    MAX_FRAME_BUFFER_NAME_SIZE = 128,
+    MAX_SYSFS_FILE_PATH = 255,
+    SUPPORTED_DOWNSCALE_AREA = (1920*1080)
+};
+
+int getHDMINode(void);
+int getEdidRawData(char *buffer);
+
+void getAspectRatioPosition(int destWidth, int destHeight, int srcWidth,
+                                int srcHeight, hwc_rect_t& rect);
+}; //namespace qdutils
+#endif
diff --git a/msm8909/libqservice/Android.mk b/msm8909/libqservice/Android.mk
new file mode 100644
index 0000000..78b1d77
--- /dev/null
+++ b/msm8909/libqservice/Android.mk
@@ -0,0 +1,19 @@
+LOCAL_PATH := $(call my-dir)
+include $(LOCAL_PATH)/../common.mk
+include $(CLEAR_VARS)
+
+LOCAL_MODULE                  := libqservice
+LOCAL_MODULE_TAGS             := optional
+LOCAL_C_INCLUDES              := $(common_includes) $(kernel_includes)
+LOCAL_SHARED_LIBRARIES        := $(common_libs) libbinder
+LOCAL_CFLAGS                  := $(common_flags) -DLOG_TAG=\"qdqservice\"
+LOCAL_ADDITIONAL_DEPENDENCIES := $(common_deps)
+LOCAL_SRC_FILES               := QService.cpp \
+                                 IQService.cpp \
+                                 IQClient.cpp
+LOCAL_COPY_HEADERS_TO         := $(common_header_export_path)
+LOCAL_COPY_HEADERS            := IQService.h \
+                                 IQClient.h
+
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/msm8909/libqservice/IQClient.cpp b/msm8909/libqservice/IQClient.cpp
new file mode 100644
index 0000000..a6251c8
--- /dev/null
+++ b/msm8909/libqservice/IQClient.cpp
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ * Copyright (C) 2012-2013, The Linux Foundation. All rights reserved.
+ *
+ * Not a Contribution, Apache license notifications and license are
+ * retained for attribution purposes only.
+
+ * 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/types.h>
+#include <binder/Parcel.h>
+#include <binder/IBinder.h>
+#include <binder/IInterface.h>
+#include <utils/Errors.h>
+#include <IQClient.h>
+
+using namespace android;
+
+// ---------------------------------------------------------------------------
+// XXX: Since qservice currently runs as part of hwc instead of a standalone
+// process, the implementation below is overridden and the notifyCallback in
+// hwc_qclient is directly called.
+
+namespace qClient {
+
+enum {
+    NOTIFY_CALLBACK = IBinder::FIRST_CALL_TRANSACTION,
+};
+
+class BpQClient : public BpInterface<IQClient>
+{
+public:
+    BpQClient(const sp<IBinder>& impl)
+        : BpInterface<IQClient>(impl) {}
+
+    virtual status_t notifyCallback(uint32_t command,
+            const Parcel* inParcel,
+            Parcel* outParcel) {
+        Parcel data;
+        Parcel *reply = outParcel;
+        data.writeInterfaceToken(IQClient::getInterfaceDescriptor());
+        data.writeInt32(command);
+        if (inParcel->dataAvail())
+            data.appendFrom(inParcel, inParcel->dataPosition(),
+                    inParcel->dataAvail());
+        status_t result = remote()->transact(NOTIFY_CALLBACK, data, reply);
+        return result;
+    }
+};
+
+IMPLEMENT_META_INTERFACE(QClient, "android.display.IQClient");
+
+// ----------------------------------------------------------------------
+//Stub implementation - nothing needed here
+status_t BnQClient::onTransact(
+    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
+{
+    switch(code) {
+        case NOTIFY_CALLBACK: {
+            CHECK_INTERFACE(IQClient, data, reply);
+            uint32_t command = data.readInt32();
+            notifyCallback(command, &data, reply);
+            return NO_ERROR;
+        } break;
+        default:
+            return BBinder::onTransact(code, data, reply, flags);
+    }
+
+}
+
+}; // namespace qClient
diff --git a/msm8909/libqservice/IQClient.h b/msm8909/libqservice/IQClient.h
new file mode 100644
index 0000000..7d816d2
--- /dev/null
+++ b/msm8909/libqservice/IQClient.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ * Copyright (C) 2012-2013, The Linux Foundation. All rights reserved.
+ *
+ * Not a Contribution, Apache license notifications and license are
+ * retained for attribution purposes only.
+
+ * 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 ANDROID_IQCLIENT_H
+#define ANDROID_IQCLIENT_H
+
+#include <stdint.h>
+#include <sys/types.h>
+#include <utils/Errors.h>
+#include <utils/RefBase.h>
+#include <binder/IInterface.h>
+
+namespace qClient {
+// ----------------------------------------------------------------------------
+class IQClient : public android::IInterface
+{
+public:
+    DECLARE_META_INTERFACE(QClient);
+    virtual android::status_t notifyCallback(uint32_t command,
+            const android::Parcel* inParcel,
+            android::Parcel* outParcel) = 0;
+};
+
+// ----------------------------------------------------------------------------
+
+class BnQClient : public android::BnInterface<IQClient>
+{
+public:
+    virtual android::status_t onTransact( uint32_t code,
+                                          const android::Parcel& data,
+                                          android::Parcel* reply,
+                                          uint32_t flags = 0);
+};
+
+// ----------------------------------------------------------------------------
+}; // namespace qClient
+
+#endif // ANDROID_IQCLIENT_H
diff --git a/msm8909/libqservice/IQService.cpp b/msm8909/libqservice/IQService.cpp
new file mode 100644
index 0000000..9e2b0f5
--- /dev/null
+++ b/msm8909/libqservice/IQService.cpp
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ * Copyright (C) 2012-2014, The Linux Foundation. All rights reserved.
+ *
+ * Not a Contribution, Apache license notifications and license are
+ * retained for attribution purposes only.
+
+ * 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 <fcntl.h>
+#include <stdint.h>
+#include <sys/types.h>
+#include <binder/Parcel.h>
+#include <binder/IBinder.h>
+#include <binder/IInterface.h>
+#include <binder/IPCThreadState.h>
+#include <utils/Errors.h>
+#include <private/android_filesystem_config.h>
+#include <IQService.h>
+
+#define QSERVICE_DEBUG 0
+
+using namespace android;
+using namespace qClient;
+
+// ---------------------------------------------------------------------------
+
+namespace qService {
+
+class BpQService : public BpInterface<IQService>
+{
+public:
+    BpQService(const sp<IBinder>& impl)
+        : BpInterface<IQService>(impl) {}
+
+    virtual void connect(const sp<IQClient>& client) {
+        ALOGD_IF(QSERVICE_DEBUG, "%s: connect client", __FUNCTION__);
+        Parcel data, reply;
+        data.writeInterfaceToken(IQService::getInterfaceDescriptor());
+        data.writeStrongBinder(IInterface::asBinder(client));
+        remote()->transact(CONNECT, data, &reply);
+    }
+
+    virtual android::status_t dispatch(uint32_t command, const Parcel* inParcel,
+            Parcel* outParcel) {
+        ALOGD_IF(QSERVICE_DEBUG, "%s: dispatch in:%p", __FUNCTION__, inParcel);
+        status_t err = (status_t) android::FAILED_TRANSACTION;
+        Parcel data;
+        Parcel *reply = outParcel;
+        data.writeInterfaceToken(IQService::getInterfaceDescriptor());
+        if (inParcel && inParcel->dataSize() > 0)
+            data.appendFrom(inParcel, 0, inParcel->dataSize());
+        err = remote()->transact(command, data, reply);
+        return err;
+    }
+};
+
+IMPLEMENT_META_INTERFACE(QService, "android.display.IQService");
+
+// ----------------------------------------------------------------------
+
+static void getProcName(int pid, char *buf, int size);
+
+status_t BnQService::onTransact(
+    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
+{
+    ALOGD_IF(QSERVICE_DEBUG, "%s: code: %d", __FUNCTION__, code);
+    // IPC should be from certain processes only
+    IPCThreadState* ipc = IPCThreadState::self();
+    const int callerPid = ipc->getCallingPid();
+    const int callerUid = ipc->getCallingUid();
+    const int MAX_BUF_SIZE = 1024;
+    char callingProcName[MAX_BUF_SIZE] = {0};
+
+    getProcName(callerPid, callingProcName, MAX_BUF_SIZE);
+
+    const bool permission = (callerUid == AID_MEDIA ||
+            callerUid == AID_GRAPHICS ||
+            callerUid == AID_ROOT ||
+            callerUid == AID_SYSTEM);
+
+    if (code == CONNECT) {
+        CHECK_INTERFACE(IQService, data, reply);
+        if(callerUid != AID_GRAPHICS) {
+            ALOGE("display.qservice CONNECT access denied: \
+                    pid=%d uid=%d process=%s",
+                    callerPid, callerUid, callingProcName);
+            return PERMISSION_DENIED;
+        }
+        sp<IQClient> client =
+                interface_cast<IQClient>(data.readStrongBinder());
+        connect(client);
+        return NO_ERROR;
+    } else if (code > COMMAND_LIST_START && code < COMMAND_LIST_END) {
+        if(!permission) {
+            ALOGE("display.qservice access denied: command=%d\
+                  pid=%d uid=%d process=%s", code, callerPid,
+                  callerUid, callingProcName);
+            return PERMISSION_DENIED;
+        }
+        CHECK_INTERFACE(IQService, data, reply);
+        dispatch(code, &data, reply);
+        return NO_ERROR;
+    } else {
+        return BBinder::onTransact(code, data, reply, flags);
+    }
+}
+
+//Helper
+static void getProcName(int pid, char *buf, int size) {
+    int fd = -1;
+    snprintf(buf, size, "/proc/%d/cmdline", pid);
+    fd = open(buf, O_RDONLY);
+    if (fd < 0) {
+        strlcpy(buf, "Unknown", size);
+    } else {
+        ssize_t len = read(fd, buf, size - 1);
+        if (len >= 0)
+           buf[len] = 0;
+
+        close(fd);
+    }
+}
+
+}; // namespace qService
diff --git a/msm8909/libqservice/IQService.h b/msm8909/libqservice/IQService.h
new file mode 100644
index 0000000..0f0dc4c
--- /dev/null
+++ b/msm8909/libqservice/IQService.h
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ * Copyright (C) 2012-2015, The Linux Foundation. All rights reserved.
+ *
+ * Not a Contribution, Apache license notifications and license are
+ * retained for attribution purposes only.
+
+ * 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 ANDROID_IQSERVICE_H
+#define ANDROID_IQSERVICE_H
+
+#include <stdint.h>
+#include <sys/types.h>
+#include <utils/Errors.h>
+#include <utils/RefBase.h>
+#include <binder/IInterface.h>
+#include <binder/IBinder.h>
+#include <IQClient.h>
+
+
+namespace qService {
+// ----------------------------------------------------------------------------
+
+class IQService : public android::IInterface
+{
+public:
+    DECLARE_META_INTERFACE(QService);
+    enum {
+        COMMAND_LIST_START = android::IBinder::FIRST_CALL_TRANSACTION,
+        SECURING,                // Hardware securing start/end notification
+        UNSECURING,              // Hardware unsecuring start/end notification
+        CONNECT,                 // Connect to qservice
+        SCREEN_REFRESH,          // Refresh screen through SF invalidate
+        EXTERNAL_ORIENTATION,    // Set external orientation
+        BUFFER_MIRRORMODE,       // Buffer mirrormode
+        CHECK_EXTERNAL_STATUS,   // Check status of external display
+        GET_DISPLAY_ATTRIBUTES,  // Get display attributes
+        SET_HSIC_DATA,           // Set HSIC on dspp
+        GET_DISPLAY_VISIBLE_REGION,  // Get the visibleRegion for dpy
+        SET_SECONDARY_DISPLAY_STATUS,  // Sets secondary display status
+        SET_PARTIAL_UPDATE,      // Preference on partial update feature
+        SET_VIEW_FRAME,          // Set view frame of display
+        DYNAMIC_DEBUG,           // Enable more logging on the fly
+        SET_IDLE_TIMEOUT,        // Set idle timeout for GPU fallback
+        /* Enable/Disable/Set refresh rate dynamically */
+        CONFIGURE_DYN_REFRESH_RATE,
+        QDCM_SVC_CMDS,           // request QDCM services.
+        TOGGLE_SCREEN_UPDATE,    // Provides ability to disable screen updates
+        COMMAND_LIST_END = 400,
+    };
+
+    enum {
+        END = 0,
+        START,
+    };
+
+    enum {
+        DEBUG_ALL,
+        DEBUG_MDPCOMP,
+        DEBUG_VSYNC,
+        DEBUG_VD,
+        DEBUG_PIPE_LIFECYCLE,
+    };
+
+    enum {
+        PREF_POST_PROCESSING,
+        PREF_PARTIAL_UPDATE,
+        ENABLE_PARTIAL_UPDATE,
+    };
+
+    // Register a client that can be notified
+    virtual void connect(const android::sp<qClient::IQClient>& client) = 0;
+    // Generic function to dispatch binder commands
+    // The type of command decides how the data is parceled
+    virtual android::status_t dispatch(uint32_t command,
+            const android::Parcel* inParcel,
+            android::Parcel* outParcel) = 0;
+};
+
+// ----------------------------------------------------------------------------
+
+class BnQService : public android::BnInterface<IQService>
+{
+public:
+    virtual android::status_t onTransact( uint32_t code,
+                                          const android::Parcel& data,
+                                          android::Parcel* reply,
+                                          uint32_t flags = 0);
+};
+
+// ----------------------------------------------------------------------------
+}; // namespace qService
+
+#endif // ANDROID_IQSERVICE_H
diff --git a/msm8909/libqservice/QService.cpp b/msm8909/libqservice/QService.cpp
new file mode 100644
index 0000000..12dd995
--- /dev/null
+++ b/msm8909/libqservice/QService.cpp
@@ -0,0 +1,84 @@
+/*
+ *  Copyright (c) 2012-2014, The Linux Foundation. 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 The Linux Foundation 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.
+ */
+
+#include <QService.h>
+#include <binder/Parcel.h>
+#include <binder/IPCThreadState.h>
+
+#define QSERVICE_DEBUG 0
+
+using namespace android;
+
+namespace qService {
+
+QService* QService::sQService = NULL;
+// ----------------------------------------------------------------------------
+QService::QService()
+{
+    ALOGD_IF(QSERVICE_DEBUG, "QService Constructor invoked");
+}
+
+QService::~QService()
+{
+    ALOGD_IF(QSERVICE_DEBUG,"QService Destructor invoked");
+}
+
+void QService::connect(const sp<qClient::IQClient>& client) {
+    ALOGD_IF(QSERVICE_DEBUG,"client connected");
+    mClient = client;
+}
+
+status_t QService::dispatch(uint32_t command, const Parcel* inParcel,
+        Parcel* outParcel) {
+    status_t err = (status_t) FAILED_TRANSACTION;
+    IPCThreadState* ipc = IPCThreadState::self();
+    //Rewind parcel in case we're calling from the same process
+    if (ipc->getCallingPid() == getpid())
+        inParcel->setDataPosition(0);
+    if (mClient.get()) {
+        ALOGD_IF(QSERVICE_DEBUG, "Dispatching command: %d", command);
+        err = mClient->notifyCallback(command, inParcel, outParcel);
+    }
+    return err;
+}
+
+void QService::init()
+{
+    if(!sQService) {
+        sQService = new QService();
+        sp<IServiceManager> sm = defaultServiceManager();
+        sm->addService(String16("display.qservice"), sQService);
+        if(sm->checkService(String16("display.qservice")) != NULL)
+            ALOGD_IF(QSERVICE_DEBUG, "adding display.qservice succeeded");
+        else
+            ALOGD_IF(QSERVICE_DEBUG, "adding display.qservice failed");
+    }
+}
+
+}
diff --git a/msm8909/libqservice/QService.h b/msm8909/libqservice/QService.h
new file mode 100644
index 0000000..a8e4cdb
--- /dev/null
+++ b/msm8909/libqservice/QService.h
@@ -0,0 +1,59 @@
+/*
+ *  Copyright (c) 2012-2013, The Linux Foundation. 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 The Linux Foundation 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 ANDROID_QSERVICE_H
+#define ANDROID_QSERVICE_H
+
+#include <utils/Errors.h>
+#include <sys/types.h>
+#include <cutils/log.h>
+#include <binder/IServiceManager.h>
+#include <IQService.h>
+#include <IQClient.h>
+
+struct hwc_context_t;
+
+namespace qService {
+// ----------------------------------------------------------------------------
+
+class QService : public BnQService {
+public:
+    virtual ~QService();
+    virtual void connect(const android::sp<qClient::IQClient>& client);
+    virtual android::status_t dispatch(uint32_t command,
+            const android::Parcel* data,
+            android::Parcel* reply);
+    static void init();
+private:
+    QService();
+    android::sp<qClient::IQClient> mClient;
+    static QService *sQService;
+};
+}; // namespace qService
+#endif // ANDROID_QSERVICE_H
diff --git a/msm8909/libqservice/QServiceUtils.h b/msm8909/libqservice/QServiceUtils.h
new file mode 100644
index 0000000..ff09aa9
--- /dev/null
+++ b/msm8909/libqservice/QServiceUtils.h
@@ -0,0 +1,94 @@
+/*
+* Copyright (c) 2013-15 The Linux Foundation. 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 The Linux Foundation. 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 QSERVICEUTILS_H
+#define QSERVICEUTILS_H
+#include <binder/Parcel.h>
+#include <binder/IServiceManager.h>
+#include <utils/RefBase.h>
+#include <IQService.h>
+
+// ----------------------------------------------------------------------------
+// Helpers
+// ----------------------------------------------------------------------------
+inline android::sp<qService::IQService> getBinder() {
+    android::sp<android::IServiceManager> sm = android::defaultServiceManager();
+    android::sp<qService::IQService> binder =
+            android::interface_cast<qService::IQService>
+            (sm->getService(android::String16("display.qservice")));
+    if (binder == NULL) {
+        ALOGE("%s: invalid binder object", __FUNCTION__);
+    }
+    return binder;
+}
+
+inline android::status_t sendSingleParam(uint32_t command, uint32_t value) {
+    android::status_t err = (android::status_t) android::FAILED_TRANSACTION;
+    android::sp<qService::IQService> binder = getBinder();
+    android::Parcel inParcel, outParcel;
+    inParcel.writeInt32(value);
+    if(binder != NULL) {
+        err = binder->dispatch(command, &inParcel , &outParcel);
+    }
+    return err;
+}
+
+// ----------------------------------------------------------------------------
+// Convenience wrappers that clients can call
+// ----------------------------------------------------------------------------
+inline android::status_t securing(uint32_t startEnd) {
+    return sendSingleParam(qService::IQService::SECURING, startEnd);
+}
+
+inline android::status_t unsecuring(uint32_t startEnd) {
+    return sendSingleParam(qService::IQService::UNSECURING, startEnd);
+}
+
+inline android::status_t screenRefresh() {
+    return sendSingleParam(qService::IQService::SCREEN_REFRESH, 1);
+}
+
+inline android::status_t setPartialUpdate(uint32_t enable) {
+    return sendSingleParam(qService::IQService::SET_PARTIAL_UPDATE, enable);
+}
+
+inline android::status_t toggleScreenUpdate(uint32_t on) {
+    return sendSingleParam(qService::IQService::TOGGLE_SCREEN_UPDATE, on);
+}
+
+inline android::status_t setExtOrientation(uint32_t orientation) {
+    return sendSingleParam(qService::IQService::EXTERNAL_ORIENTATION,
+            orientation);
+}
+
+inline android::status_t setBufferMirrorMode(uint32_t enable) {
+    return sendSingleParam(qService::IQService::BUFFER_MIRRORMODE, enable);
+}
+
+#endif /* end of include guard: QSERVICEUTILS_H */