Merge "hwc: Request RGB pipe only if layer needs scaling."
diff --git a/common.mk b/common.mk
index 47c455f..ae4ea61 100644
--- a/common.mk
+++ b/common.mk
@@ -36,8 +36,7 @@
     common_flags += -DMDSS_TARGET
 endif
 
-ifeq ($(call is-board-platform-in-list, mpq8092 msm_bronze msm8916), true)
-    #XXX: Replace with check from MDP when available
+ifeq ($(call is-board-platform-in-list, mpq8092), true)
     common_flags += -DVPU_TARGET
 endif
 
diff --git a/libcopybit/copybit.cpp b/libcopybit/copybit.cpp
index 9558f69..c0246e3 100644
--- a/libcopybit/copybit.cpp
+++ b/libcopybit/copybit.cpp
@@ -573,7 +573,9 @@
     int rel_fen_fd = -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) {
@@ -607,6 +609,7 @@
     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);
 
diff --git a/libexternal/external.cpp b/libexternal/external.cpp
index d905e0d..e6395fb 100644
--- a/libexternal/external.cpp
+++ b/libexternal/external.cpp
@@ -493,7 +493,6 @@
 
 void ExternalDisplay::setResolution(int ID)
 {
-    struct fb_var_screeninfo info;
     int ret = 0;
     ret = ioctl(mFd, FBIOGET_VSCREENINFO, &mVInfo);
     if(ret < 0) {
diff --git a/libgralloc/Android.mk b/libgralloc/Android.mk
index a879c5c..ef10f54 100644
--- a/libgralloc/Android.mk
+++ b/libgralloc/Android.mk
@@ -27,7 +27,7 @@
 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
+LOCAL_COPY_HEADERS            := gralloc_priv.h gr.h
 
 include $(BUILD_SHARED_LIBRARY)
 
@@ -41,5 +41,6 @@
 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/libgralloc/alloc_controller.cpp b/libgralloc/alloc_controller.cpp
index 33c4f32..a2c2f14 100644
--- a/libgralloc/alloc_controller.cpp
+++ b/libgralloc/alloc_controller.cpp
@@ -36,6 +36,7 @@
 #include "ionalloc.h"
 #include "gr.h"
 #include "comptype.h"
+#include "mdp_version.h"
 
 #ifdef VENUS_COLOR_FORMAT
 #include <media/msm_media_info.h>
@@ -45,6 +46,9 @@
 #define VENUS_BUFFER_SIZE(args...) 0
 #endif
 
+#define ASTC_BLOCK_SIZE 16
+#define ASTC_IN_UNITS(n, unit_size)  (((n) + (unit_size) -1) / (unit_size))
+
 using namespace gralloc;
 using namespace qdutils;
 
@@ -88,13 +92,16 @@
 {
     LINK_adreno_compute_aligned_width_and_height = NULL;
     LINK_adreno_compute_padding = NULL;
+    LINK_adreno_isMacroTilingSupportedByGpu = 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");
+                ::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");
     }
 }
 
@@ -105,8 +112,19 @@
     }
 }
 
+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& aligned_w, int& aligned_h)
+                            int tile_enabled, int& aligned_w, int& aligned_h)
 {
     aligned_w = ALIGN(width, 32);
     aligned_h = ALIGN(height, 32);
@@ -138,9 +156,8 @@
             // 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) {
-               int tile_mode = 0;   // Linear surface
-               LINK_adreno_compute_aligned_width_and_height(width,
-                                     height, bpp, tile_mode,
+                LINK_adreno_compute_aligned_width_and_height(width,
+                                     height, bpp, tile_enabled,
                                      raster_mode, padding_threshold,
                                      &aligned_w, &aligned_h);
 
@@ -185,6 +202,76 @@
             case HAL_PIXEL_FORMAT_NV21_ZSL:
                 aligned_w = ALIGN(width, 64);
                 break;
+            case HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_4x4_KHR:
+            case HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR:
+                aligned_w = ASTC_IN_UNITS(width, 4);
+                aligned_h = ASTC_IN_UNITS(height, 4);
+                break;
+            case HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_5x4_KHR:
+            case HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR:
+                aligned_w = ASTC_IN_UNITS(width, 5);
+                aligned_h = ASTC_IN_UNITS(height, 4);
+                break;
+            case HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_5x5_KHR:
+            case HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR:
+                aligned_w = ASTC_IN_UNITS(width, 5);
+                aligned_h = ASTC_IN_UNITS(height, 5);
+                break;
+            case HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_6x5_KHR:
+            case HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR:
+                aligned_w = ASTC_IN_UNITS(width, 6);
+                aligned_h = ASTC_IN_UNITS(height, 5);
+                break;
+            case HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_6x6_KHR:
+            case HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR:
+                aligned_w = ASTC_IN_UNITS(width, 6);
+                aligned_h = ASTC_IN_UNITS(height, 6);
+                break;
+            case HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_8x5_KHR:
+            case HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR:
+                aligned_w = ASTC_IN_UNITS(width, 8);
+                aligned_h = ASTC_IN_UNITS(height, 5);
+                break;
+            case HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_8x6_KHR:
+            case HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR:
+                aligned_w = ASTC_IN_UNITS(width, 8);
+                aligned_h = ASTC_IN_UNITS(height, 6);
+                break;
+            case HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_8x8_KHR:
+            case HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR:
+                aligned_w = ASTC_IN_UNITS(width, 8);
+                aligned_h = ASTC_IN_UNITS(height, 8);
+                break;
+            case HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_10x5_KHR:
+            case HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR:
+                aligned_w = ASTC_IN_UNITS(width, 10);
+                aligned_h = ASTC_IN_UNITS(height, 5);
+                break;
+            case HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_10x6_KHR:
+            case HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR:
+                aligned_w = ASTC_IN_UNITS(width, 10);
+                aligned_h = ASTC_IN_UNITS(height, 6);
+                break;
+            case HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_10x8_KHR:
+            case HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR:
+                aligned_w = ASTC_IN_UNITS(width, 10);
+                aligned_h = ASTC_IN_UNITS(height, 8);
+                break;
+            case HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_10x10_KHR:
+            case HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR:
+                aligned_w = ASTC_IN_UNITS(width, 10);
+                aligned_h = ASTC_IN_UNITS(height, 10);
+                break;
+            case HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_12x10_KHR:
+            case HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR:
+                aligned_w = ASTC_IN_UNITS(width, 12);
+                aligned_h = ASTC_IN_UNITS(height, 10);
+                break;
+            case HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_12x12_KHR:
+            case HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR:
+                aligned_w = ASTC_IN_UNITS(width, 12);
+                aligned_h = ASTC_IN_UNITS(height, 12);
+                break;
             default: break;
         }
     }
@@ -289,16 +376,42 @@
     return memalloc;
 }
 
-size_t getBufferSizeAndDimensions(int width, int height, int format,
-                                  int& alignedw, int &alignedh)
+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:
+                {
+                    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
+size_t getSize(int format, int width, int height, int alignedw, int alignedh)
 {
     size_t size;
 
-    AdrenoMemInfo::getInstance().getAlignedWidthAndHeight(width,
-                                                          height,
-                                                          format,
-                                                          alignedw,
-                                                          alignedh);
     switch (format) {
         case HAL_PIXEL_FORMAT_RGBA_8888:
         case HAL_PIXEL_FORMAT_RGBX_8888:
@@ -372,14 +485,97 @@
             alignedh = ALIGN(height, 64);
             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:
+            size = alignedw * alignedh * ASTC_BLOCK_SIZE;
+            break;
         default:
             ALOGE("unrecognized pixel format: 0x%x", format);
             return -EINVAL;
     }
+    return size;
+}
+
+size_t getBufferSizeAndDimensions(int width, int height, int format,
+        int& alignedw, int &alignedh)
+{
+    size_t size;
+
+    AdrenoMemInfo::getInstance().getAlignedWidthAndHeight(width,
+            height,
+            format,
+            false,
+            alignedw,
+            alignedh);
+
+    size = getSize(format, width, height, alignedw, alignedh);
 
     return size;
 }
 
+
+size_t getBufferSizeAndDimensions(int width, int height, int format, int usage,
+        int& alignedw, int &alignedh)
+{
+    size_t 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, size_t& size)
+{
+    tileEnabled = isMacroTileEnabled(format, usage);
+
+    AdrenoMemInfo::getInstance().getAlignedWidthAndHeight(width,
+            height,
+            format,
+            tileEnabled,
+            alignedw,
+            alignedh);
+
+    if(size)
+        size = getSize(format, width, height, alignedw, alignedh);
+}
+
+
+
 // 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
@@ -392,7 +588,9 @@
     data.base = 0;
     data.fd = -1;
     data.offset = 0;
-    data.size = getBufferSizeAndDimensions(w, h, format, alignedw, alignedh);
+    data.size = getBufferSizeAndDimensions(w, h, format, usage, alignedw,
+                                            alignedh);
+
     data.align = getpagesize();
     data.uncached = useUncached(usage);
     int allocFlags = usage;
diff --git a/libgralloc/gpu.cpp b/libgralloc/gpu.cpp
index b4da363..da179f9 100644
--- a/libgralloc/gpu.cpp
+++ b/libgralloc/gpu.cpp
@@ -150,6 +150,10 @@
             flags |= private_handle_t::PRIV_FLAGS_SECURE_DISPLAY;
         }
 
+        if(isMacroTileEnabled(format, usage)) {
+            flags |= private_handle_t::PRIV_FLAGS_TILE_RENDERED;
+        }
+
         flags |= data.allocType;
         int eBaseAddr = int(eData.base) + eData.offset;
         private_handle_t *hnd = new private_handle_t(data.fd, size, flags,
@@ -173,6 +177,9 @@
 {
     *bufferType = BUFFER_TYPE_VIDEO;
 
+    if (inputFormat == HAL_PIXEL_FORMAT_RGB_888)
+        return;
+
     if (inputFormat <= HAL_PIXEL_FORMAT_sRGB_X_8888) {
         // RGB formats
         *bufferType = BUFFER_TYPE_UI;
@@ -285,7 +292,8 @@
     }
 
     getGrallocInformationFromFormat(grallocFormat, &bufferType);
-    size = getBufferSizeAndDimensions(w, h, grallocFormat, alignedw, alignedh);
+    size = getBufferSizeAndDimensions(w, h, grallocFormat, usage, alignedw,
+                   alignedh);
 
     if ((ssize_t)size <= 0)
         return -EINVAL;
diff --git a/libgralloc/gr.h b/libgralloc/gr.h
index 1949f45..8c68e16 100644
--- a/libgralloc/gr.h
+++ b/libgralloc/gr.h
@@ -51,9 +51,20 @@
 
 int mapFrameBufferLocked(struct private_module_t* module);
 int terminateBuffer(gralloc_module_t const* module, private_handle_t* hnd);
+size_t getBufferSizeAndDimensions(int width, int height, int format, int usage,
+                                  int& alignedw, int &alignedh);
 size_t 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, size_t &size);
+
+
+bool isMacroTileEnabled(int format, int usage);
+
 int decideBufferHandlingMechanism(int format, const char *compositionUsed,
                                   int hasBlitEngine, int *needConversion,
                                   int *useBufferDirectly);
@@ -95,7 +106,16 @@
      * @return aligned width, aligned height
      */
     void getAlignedWidthAndHeight(int width, int height, int format,
-                                  int& alignedw, int &alignedh);
+                            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;
@@ -114,6 +134,8 @@
                                                 int padding_threshold,
                                                 int *aligned_w,
                                                 int *aligned_h);
+        // link to the surface padding library.
+        int (*LINK_adreno_isMacroTilingSupportedByGpu) (void);
 
 };
 #endif /* GR_H_ */
diff --git a/libgralloc/gralloc_priv.h b/libgralloc/gralloc_priv.h
index f6d244a..c56eca9 100644
--- a/libgralloc/gralloc_priv.h
+++ b/libgralloc/gralloc_priv.h
@@ -79,8 +79,12 @@
     /* 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_ATTRIBUTES,
 };
 
 #define GRALLOC_HEAP_MASK   (GRALLOC_USAGE_PRIVATE_UI_CONTIG_HEAP |\
@@ -110,6 +114,39 @@
     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*/
@@ -170,6 +207,8 @@
             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
         };
 
         // file-descriptors
diff --git a/libgralloc/mapper.cpp b/libgralloc/mapper.cpp
index a07bdc3..109c141 100644
--- a/libgralloc/mapper.cpp
+++ b/libgralloc/mapper.cpp
@@ -331,10 +331,11 @@
                 int *stride = va_arg(args, int *);
                 int alignedw = 0, alignedh = 0;
                 AdrenoMemInfo::getInstance().getAlignedWidthAndHeight(width,
-                                     0, format, alignedw, alignedh);
+                        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*);
@@ -350,6 +351,23 @@
                 }
                 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;
+
         default:
             break;
     }
diff --git a/libhwcomposer/Android.mk b/libhwcomposer/Android.mk
index 7b2092d..9749c69 100644
--- a/libhwcomposer/Android.mk
+++ b/libhwcomposer/Android.mk
@@ -23,11 +23,10 @@
                                  hwc_copybit.cpp  \
                                  hwc_qclient.cpp  \
                                  hwc_dump_layers.cpp \
-                                 hwc_ad.cpp
-
-ifeq ($(call is-board-platform-in-list, mpq8092 msm_bronze msm8916), true)
+                                 hwc_ad.cpp \
+                                 hwc_virtual.cpp
+ifeq ($(call is-board-platform-in-list, mpq8092), true)
     LOCAL_SRC_FILES += hwc_vpuclient.cpp
 endif
 
-
 include $(BUILD_SHARED_LIBRARY)
diff --git a/libhwcomposer/hwc.cpp b/libhwcomposer/hwc.cpp
index eb999f7..431757d 100644
--- a/libhwcomposer/hwc.cpp
+++ b/libhwcomposer/hwc.cpp
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2010 The Android Open Source Project
- * Copyright (C) 2012-2013, The Linux Foundation. All rights reserved.
+ * Copyright (C) 2012-2014, The Linux Foundation. All rights reserved.
  *
  * Not a Contribution, Apache license notifications and license are retained
  * for attribution purposes only.
@@ -39,6 +39,7 @@
 #include "hwc_ad.h"
 #include "profiler.h"
 #include "hwc_vpuclient.h"
+#include "hwc_virtual.h"
 
 using namespace qhwc;
 using namespace overlay;
@@ -104,17 +105,27 @@
 //Helper
 static void reset(hwc_context_t *ctx, int numDisplays,
                   hwc_display_contents_1_t** displays) {
+
+    ctx->numActiveDisplays = 0;
     for(int i = 0; i < HWC_NUM_DISPLAY_TYPES; 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 > 1)) {
+        if (LIKELY(list && list->numHwLayers > 0)) {
             for(uint32_t j = 0; j < list->numHwLayers; j++) {
                 if(list->hwLayers[j].compositionType != HWC_FRAMEBUFFER_TARGET)
                     list->hwLayers[j].compositionType = HWC_FRAMEBUFFER;
             }
+
+            /* 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;
         }
 
         if(ctx->mFBUpdate[i])
@@ -123,19 +134,45 @@
             ctx->mCopyBit[i]->reset();
         if(ctx->mLayerRotMap[i])
             ctx->mLayerRotMap[i]->reset();
+
     }
 
     ctx->mAD->reset();
     MDPComp::reset();
+    if(ctx->mHWCVirtual)
+        ctx->mHWCVirtual->destroy(ctx, numDisplays, displays);
 }
 
-//clear prev layer prop flags and realloc for current frame
-static void reset_layer_prop(hwc_context_t* ctx, int dpy, int numAppLayers) {
-    if(ctx->layerProp[dpy]) {
-       delete[] ctx->layerProp[dpy];
-       ctx->layerProp[dpy] = NULL;
+bool isEqual(float f1, float f2) {
+        return ((int)(f1*100) == (int)(f2*100)) ? true : false;
+}
+
+static void scaleDisplayFrame(hwc_context_t *ctx, int dpy,
+                            hwc_display_contents_1_t *list) {
+    float origXres = ctx->dpyAttr[dpy].xres_orig;
+    float origYres = ctx->dpyAttr[dpy].yres_orig;
+    float fakeXres = ctx->dpyAttr[dpy].xres;
+    float fakeYres = ctx->dpyAttr[dpy].yres;
+    float xresRatio = origXres / fakeXres;
+    float yresRatio = origYres / fakeYres;
+    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);
+        float layerWidth = displayFrame.right - displayFrame.left;
+        float layerHeight = displayFrame.bottom - displayFrame.top;
+        float sourceWidth = sourceCrop.right - sourceCrop.left;
+        float sourceHeight = sourceCrop.bottom - sourceCrop.top;
+
+        if (isEqual(layerWidth / sourceWidth, xresRatio) &&
+                isEqual(layerHeight / sourceHeight, yresRatio))
+            break;
+
+        displayFrame.left = xresRatio * displayFrame.left;
+        displayFrame.top = yresRatio * displayFrame.top;
+        displayFrame.right = displayFrame.left + layerWidth * xresRatio;
+        displayFrame.bottom = displayFrame.top + layerHeight * yresRatio;
     }
-    ctx->layerProp[dpy] = new LayerProp[numAppLayers];
 }
 
 static int hwc_prepare_primary(hwc_composer_device_1 *dev,
@@ -143,17 +180,28 @@
     ATRACE_CALL();
     hwc_context_t* ctx = (hwc_context_t*)(dev);
     const int dpy = HWC_DISPLAY_PRIMARY;
+    bool fbComp = false;
     if (LIKELY(list && list->numHwLayers > 1) &&
             ctx->dpyAttr[dpy].isActive) {
+
+        if (ctx->dpyAttr[dpy].customFBSize)
+            scaleDisplayFrame(ctx, dpy, list);
+
         reset_layer_prop(ctx, dpy, list->numHwLayers - 1);
         setListStats(ctx, list, dpy);
+
+        if (ctx->mVPUClient == NULL)
+            fbComp = (ctx->mMDPComp[dpy]->prepare(ctx, list) < 0);
 #ifdef VPU_TARGET
-        ctx->mVPUClient->prepare(ctx, list);
+        else
+            fbComp = (ctx->mVPUClient->prepare(ctx, dpy, list) < 0);
 #endif
-        if(ctx->mMDPComp[dpy]->prepare(ctx, list) < 0) {
+
+        if (fbComp) {
             const int fbZ = 0;
             ctx->mFBUpdate[dpy]->prepare(ctx, list, fbZ);
         }
+
         if (ctx->mMDP.version < qdutils::MDP_V4_0) {
             if(ctx->mCopyBit[dpy])
                 ctx->mCopyBit[dpy]->prepare(ctx, list, dpy);
@@ -193,39 +241,6 @@
     return 0;
 }
 
-static int hwc_prepare_virtual(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_VIRTUAL;
-
-    if (LIKELY(list && list->numHwLayers > 1) &&
-            ctx->dpyAttr[dpy].isActive &&
-            ctx->dpyAttr[dpy].connected) {
-        reset_layer_prop(ctx, dpy, 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;
-                ctx->mFBUpdate[dpy]->prepare(ctx, list, fbZ);
-            }
-        } else {
-            /* Virtual 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)
 {
@@ -245,7 +260,7 @@
     ctx->mRotMgr->configBegin();
     overlay::Writeback::configBegin();
 
-    for (int32_t i = numDisplays; i >= 0; i--) {
+    for (int32_t i = (numDisplays-1); i >= 0; i--) {
         hwc_display_contents_1_t *list = displays[i];
         int dpy = getDpyforExternalDisplay(ctx, i);
         switch(dpy) {
@@ -256,7 +271,8 @@
                 ret = hwc_prepare_external(dev, list);
                 break;
             case HWC_DISPLAY_VIRTUAL:
-                ret = hwc_prepare_virtual(dev, list);
+                if(ctx->mHWCVirtual)
+                    ret = ctx->mHWCVirtual->prepare(dev, list);
                 break;
             default:
                 ret = -EINVAL;
@@ -439,8 +455,11 @@
         value[0] = 0;
         break;
     case HWC_DISPLAY_TYPES_SUPPORTED:
-        if(ctx->mMDP.hasOverlay)
-            supported |= HWC_DISPLAY_EXTERNAL_BIT;
+        if(ctx->mMDP.hasOverlay) {
+            supported |= HWC_DISPLAY_VIRTUAL_BIT;
+            if(!qdutils::MDPVersion::getInstance().is8x26())
+                supported |= HWC_DISPLAY_EXTERNAL_BIT;
+        }
         value[0] = supported;
         break;
     case HWC_FORMAT_RB_SWAP:
@@ -475,13 +494,15 @@
         if(ctx->mHwcDebug[dpy])
             ctx->mHwcDebug[dpy]->dumpLayers(list);
 
-        if (!ctx->mMDPComp[dpy]->draw(ctx, list)) {
+        if (ctx->mVPUClient != NULL) {
+#ifdef VPU_TARGET
+            ctx->mVPUClient->predraw(ctx, dpy, list);
+#endif
+        }
+        else if (!ctx->mMDPComp[dpy]->draw(ctx, list)) {
             ALOGE("%s: MDPComp draw failed", __FUNCTION__);
             ret = -1;
         }
-#ifdef VPU_TARGET
-        ctx->mVPUClient->draw(ctx, list);
-#endif
 
         //TODO We dont check for SKIP flag on this layer because we need PAN
         //always. Last layer is always FB
@@ -502,6 +523,11 @@
             ALOGE("%s: display commit fail for %d dpy!", __FUNCTION__, dpy);
             ret = -1;
         }
+
+#ifdef VPU_TARGET
+        if (ctx->mVPUClient != NULL)
+            ctx->mVPUClient->draw(ctx, dpy, list);
+#endif
     }
 
     closeAcquireFds(list);
@@ -567,82 +593,13 @@
     return ret;
 }
 
-static int hwc_set_virtual(hwc_context_t *ctx,
-                            hwc_display_contents_1_t* list)
-{
-    ATRACE_CALL();
-    int ret = 0;
-
-    const int dpy = HWC_DISPLAY_VIRTUAL;
-
-
-    if (LIKELY(list) && ctx->dpyAttr[dpy].isActive &&
-            ctx->dpyAttr[dpy].connected &&
-            !ctx->dpyAttr[dpy].isPause) {
-        uint32_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 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;
-        }
-
-        int extOnlyLayerIndex =
-            ctx->listStats[dpy].extOnlyLayerIndex;
-
-        private_handle_t *hnd = (private_handle_t *)fbLayer->handle;
-        if(extOnlyLayerIndex!= -1) {
-            hwc_layer_1_t *extLayer = &list->hwLayers[extOnlyLayerIndex];
-            hnd = (private_handle_t *)extLayer->handle;
-        } else if(copybitDone) {
-            hnd = ctx->mCopyBit[dpy]->getCurrentRenderBuffer();
-        }
-
-        if(hnd && !isYuvBuffer(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);
-
-    if (list && !ctx->mVirtualonExtActive && (list->retireFenceFd < 0) ) {
-        // SF assumes HWC waits for the acquire fence and returns a new fence
-        // that signals when we're done. Since we don't wait, and also don't
-        // touch the buffer, we can just handle the acquire fence back to SF
-        // as the retire fence.
-        list->retireFenceFd = list->outbufAcquireFenceFd;
-    }
-
-    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 (uint32_t i = 0; i <= numDisplays; i++) {
+    for (uint32_t i = 0; i < numDisplays; i++) {
         hwc_display_contents_1_t* list = displays[i];
         int dpy = getDpyforExternalDisplay(ctx, i);
         switch(dpy) {
@@ -653,7 +610,8 @@
                 ret = hwc_set_external(ctx, list);
                 break;
             case HWC_DISPLAY_VIRTUAL:
-                ret = hwc_set_virtual(ctx, list);
+                if(ctx->mHWCVirtual)
+                    ret = ctx->mHWCVirtual->set(ctx, list);
                 break;
             default:
                 ret = -EINVAL;
diff --git a/libhwcomposer/hwc_ad.cpp b/libhwcomposer/hwc_ad.cpp
index 104ffce..929ccc4 100644
--- a/libhwcomposer/hwc_ad.cpp
+++ b/libhwcomposer/hwc_ad.cpp
@@ -157,7 +157,7 @@
         const hwc_display_contents_1_t* list) {
     mDoable = false;
     if(mFeatureEnabled &&
-        !ctx->mExtDisplay->isConnected() &&
+        !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];
diff --git a/libhwcomposer/hwc_copybit.cpp b/libhwcomposer/hwc_copybit.cpp
index 47b9225..86cad8f 100644
--- a/libhwcomposer/hwc_copybit.cpp
+++ b/libhwcomposer/hwc_copybit.cpp
@@ -25,7 +25,7 @@
 #include "comptype.h"
 #include "gr.h"
 #include "cb_utils.h"
-
+#include "cb_swap_rect.h"
 using namespace qdutils;
 namespace qhwc {
 
@@ -188,8 +188,15 @@
             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/src_w;
             dy = (float)dst_h/src_h;
+
             if (dx > MAX_SCALE_FACTOR || dx < MIN_SCALE_FACTOR)
                 return false;
 
@@ -303,6 +310,9 @@
             ALOGD_IF(DEBUG_COPYBIT, "%s: Not Marked for copybit", __FUNCTION__);
             continue;
         }
+        if(layer->flags & HWC_SKIP_HWC_COMPOSITION){
+            continue;
+        }
         int ret = -1;
         if (list->hwLayers[i].acquireFenceFd != -1
                 && ctx->mMDP.version >= qdutils::MDP_V4_0) {
@@ -448,8 +458,8 @@
 
     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_w=%d src_crop_width=%d", __FUNCTION__, screen_w,
-                                src_crop_width,screen_w,src_crop_width);
+        screen_h=%d src_crop_height=%d", __FUNCTION__, screen_w,
+                                src_crop_width,screen_h,src_crop_height);
         return -1;
     }
 
diff --git a/libhwcomposer/hwc_fbupdate.cpp b/libhwcomposer/hwc_fbupdate.cpp
index d601f8f..0123452 100644
--- a/libhwcomposer/hwc_fbupdate.cpp
+++ b/libhwcomposer/hwc_fbupdate.cpp
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2010 The Android Open Source Project
- * Copyright (C) 2012, The Linux Foundation. All rights reserved.
+ * Copyright (C) 2012-2014, The Linux Foundation. All rights reserved.
  *
  * Not a Contribution, Apache license notifications and license are
  * retained for attribution purposes only.
@@ -45,11 +45,14 @@
 }
 
 IFBUpdate::IFBUpdate(hwc_context_t *ctx, const int& dpy) : mDpy(dpy) {
-    getBufferSizeAndDimensions(ctx->dpyAttr[dpy].xres,
-            ctx->dpyAttr[dpy].yres,
+    size_t size;
+    getBufferAttributes(ctx->dpyAttr[mDpy].xres,
+            ctx->dpyAttr[mDpy].yres,
             HAL_PIXEL_FORMAT_RGBA_8888,
+            0,
             mAlignedFBWidth,
-            mAlignedFBHeight);
+            mAlignedFBHeight,
+            mTileEnabled, size);
 }
 
 void IFBUpdate::reset() {
@@ -121,9 +124,9 @@
         }
         overlay::Overlay& ov = *(ctx->mOverlay);
 
-        ovutils::Whf info(mAlignedFBWidth,
-                mAlignedFBHeight,
-                ovutils::getMdpFormat(HAL_PIXEL_FORMAT_RGBA_8888));
+        ovutils::Whf info(mAlignedFBWidth, mAlignedFBHeight,
+                ovutils::getMdpFormat(HAL_PIXEL_FORMAT_RGBA_8888,
+                    mTileEnabled));
 
         //Request a pipe
         ovutils::eMdpPipeType type = ovutils::OV_MDP_PIPE_ANY;
@@ -164,12 +167,12 @@
         // Dont do wormhole calculation when extDownscale is enabled on External
         if(ctx->listStats[mDpy].isDisplayAnimating && mDpy) {
             sourceCrop = layer->displayFrame;
-            displayFrame = sourceCrop;
         } else if((!mDpy ||
-                   (mDpy && !extOrient
-                   && !ctx->dpyAttr[mDpy].mDownScaleMode))
-                   && (extOnlyLayerIndex == -1)) {
-            if(!qdutils::MDPVersion::getInstance().is8x26()) {
+                  (mDpy && !extOrient
+                  && !ctx->dpyAttr[mDpy].mDownScaleMode))
+                  && (extOnlyLayerIndex == -1)) {
+            if(!qdutils::MDPVersion::getInstance().is8x26() &&
+                !ctx->dpyAttr[mDpy].customFBSize) {
                 getNonWormholeRegion(list, sourceCrop);
                 displayFrame = sourceCrop;
             }
@@ -269,8 +272,8 @@
 
         ovutils::Whf info(mAlignedFBWidth,
                 mAlignedFBHeight,
-                ovutils::getMdpFormat(HAL_PIXEL_FORMAT_RGBA_8888));
-
+                ovutils::getMdpFormat(HAL_PIXEL_FORMAT_RGBA_8888,
+                    mTileEnabled));
         //Request left pipe
         ovutils::eDest destL = ov.nextPipe(ovutils::OV_MDP_PIPE_ANY, mDpy,
                 Overlay::MIXER_LEFT);
diff --git a/libhwcomposer/hwc_fbupdate.h b/libhwcomposer/hwc_fbupdate.h
index 355e429..4b449c8 100644
--- a/libhwcomposer/hwc_fbupdate.h
+++ b/libhwcomposer/hwc_fbupdate.h
@@ -53,6 +53,7 @@
     overlay::Rotator *mRot;
     int mAlignedFBWidth;
     int mAlignedFBHeight;
+    int mTileEnabled;
 };
 
 //Non-Split panel handler.
diff --git a/libhwcomposer/hwc_mdpcomp.cpp b/libhwcomposer/hwc_mdpcomp.cpp
index 8ecd322..dbd05ae 100644
--- a/libhwcomposer/hwc_mdpcomp.cpp
+++ b/libhwcomposer/hwc_mdpcomp.cpp
@@ -325,8 +325,8 @@
     int crop_h = crop.bottom - crop.top;
     int dst_w = dst.right - dst.left;
     int dst_h = dst.bottom - dst.top;
-    float w_dscale = ceilf((float)crop_w / (float)dst_w);
-    float h_dscale = ceilf((float)crop_h / (float)dst_h);
+    float w_scale = ((float)crop_w / (float)dst_w);
+    float h_scale = ((float)crop_h / (float)dst_h);
 
     /* 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
@@ -337,9 +337,12 @@
     if((crop_w < 5)||(crop_h < 5))
         return false;
 
-    if((w_dscale > 1.0f) || (h_dscale > 1.0f)) {
+    if((w_scale > 1.0f) || (h_scale > 1.0f)) {
         const uint32_t downscale =
             qdutils::MDPVersion::getInstance().getMaxMDPDownscale();
+        const float w_dscale = w_scale;
+        const float h_dscale = h_scale;
+
         if(ctx->mMDP.version >= qdutils::MDSS_V5) {
             /* Workaround for downscales larger than 4x.
              * Will be removed once decimator block is enabled for MDSS
@@ -358,6 +361,16 @@
         }
     }
 
+    if((w_scale < 1.0f) || (h_scale < 1.0f)) {
+        const uint32_t upscale =
+            qdutils::MDPVersion::getInstance().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;
 }
 
@@ -400,13 +413,13 @@
         ALOGD_IF(isDebug(),"%s: MDP Comp. not enabled.", __FUNCTION__);
         ret = false;
     } else if(qdutils::MDPVersion::getInstance().is8x26() &&
-            ctx->mVideoTransFlag && ctx->mVirtualDisplay->isConnected()) {
+            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(ctx->dpyAttr[HWC_DISPLAY_EXTERNAL].isConfiguring ||
-              ctx->dpyAttr[HWC_DISPLAY_VIRTUAL].isConfiguring) {
+    } else if(isSecondaryConfiguring(ctx)) {
         ALOGD_IF( isDebug(),"%s: External Display connection is pending",
                   __FUNCTION__);
         ret = false;
@@ -438,6 +451,7 @@
         if(!isValidRect(visibleRect)) {
             mCurrentFrame.drop[i] = true;
             mCurrentFrame.dropCount++;
+            continue;
         }
 
         const hwc_layer_1_t* layer =  &list->hwLayers[i];
@@ -459,17 +473,17 @@
         }else {
             /* Reset frame ROI when any layer which needs scaling also needs ROI
              * cropping */
-            if((res_w != dst_w || res_h != dst_h) &&
-                    needsScaling (layer)) {
+            if((res_w != dst_w || res_h != dst_h) && needsScaling (layer)) {
                 ALOGI("%s: Resetting ROI due to scaling", __FUNCTION__);
                 memset(&mCurrentFrame.drop, 0, sizeof(mCurrentFrame.drop));
                 mCurrentFrame.dropCount = 0;
                 return false;
             }
-        }
 
-        if (layer->blending == HWC_BLENDING_NONE)
-            visibleRect = deductRect(visibleRect, res);
+            /* deduct any opaque region from visibleRect */
+            if (layer->blending == HWC_BLENDING_NONE)
+                visibleRect = deductRect(visibleRect, res);
+        }
     }
     return true;
 }
@@ -528,6 +542,7 @@
                                 hwc_display_contents_1_t* list){
 
     const int numAppLayers = ctx->listStats[mDpy].numAppLayers;
+    int priDispW = ctx->dpyAttr[HWC_DISPLAY_PRIMARY].xres;
 
     if(sIdleFallBack && !ctx->listStats[mDpy].secureUI) {
         ALOGD_IF(isDebug(), "%s: Idle fallback dpy %d",__FUNCTION__, mDpy);
@@ -541,6 +556,24 @@
         return false;
     }
 
+    if(mDpy > HWC_DISPLAY_PRIMARY && (priDispW > MAX_DISPLAY_DIM) &&
+                              (ctx->dpyAttr[mDpy].xres < MAX_DISPLAY_DIM)) {
+        // 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 downscale mode which requires scaling.
+    if(ctx->dpyAttr[mDpy].mActionSafePresent
+            || ctx->dpyAttr[mDpy].mDownScaleMode) {
+        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;
@@ -706,7 +739,8 @@
     int stagesForMDP = min(sMaxPipesPerMixer, ctx->mOverlay->availablePipes(
             mDpy, Overlay::MIXER_DEFAULT));
     //If MDP has X possible stages, it can take X layers.
-    const int batchSize = numAppLayers - (stagesForMDP - 1); //1 for FB
+    const int batchSize = (numAppLayers - mCurrentFrame.dropCount) -
+                                               (stagesForMDP - 1); //1 for FB
 
     if(batchSize <= 0) {
         ALOGD_IF(isDebug(), "%s: Not attempting", __FUNCTION__);
@@ -714,20 +748,50 @@
     }
 
     int minBatchStart = -1;
+    int minBatchEnd = -1;
     size_t minBatchPixelCount = SIZE_MAX;
 
-    for(int i = 0; i <= numAppLayers - batchSize; i++) {
+    /* Iterate through the layer list to find out a contigous batch of batchSize
+     * non-dropped layers with loweest pixel count */
+    for(int i = 0; i <= (numAppLayers - batchSize); i++) {
+        if(mCurrentFrame.drop[i])
+            continue;
+
+        int batchCount = batchSize;
         uint32_t batchPixelCount = 0;
-        for(int j = i; j < i + batchSize; j++) {
-            hwc_layer_1_t* layer = &list->hwLayers[j];
-            hwc_rect_t crop = integerizeSourceCrop(layer->sourceCropf);
-            batchPixelCount += (crop.right - crop.left) *
+        int j = i;
+        for(; j < numAppLayers && batchCount; j++){
+            if(!mCurrentFrame.drop[j]) {
+                hwc_layer_1_t* layer = &list->hwLayers[j];
+                hwc_rect_t crop = integerizeSourceCrop(layer->sourceCropf);
+                hwc_rect_t dst = layer->displayFrame;
+
+                /* If we have a valid ROI, count pixels only for the MDP fetched
+                 * region of the buffer */
+                if((ctx->listStats[mDpy].roi.w != ctx->dpyAttr[mDpy].xres) ||
+                   (ctx->listStats[mDpy].roi.h != ctx->dpyAttr[mDpy].yres)) {
+                    hwc_rect_t roi;
+                    roi.left = ctx->listStats[mDpy].roi.x;
+                    roi.top = ctx->listStats[mDpy].roi.y;
+                    roi.right = roi.left + ctx->listStats[mDpy].roi.w;
+                    roi.bottom = roi.top + ctx->listStats[mDpy].roi.h;
+
+                    /* valid ROI means no scaling layer is composed. So check
+                     * only intersection to find actual fetched pixels */
+                    crop  = getIntersection(roi, dst);
+                }
+
+                batchPixelCount += (crop.right - crop.left) *
                     (crop.bottom - crop.top);
+                batchCount--;
+            }
         }
 
-        if(batchPixelCount < minBatchPixelCount) {
+        /* we dont want to program any batch of size lesser than batchSize */
+        if(!batchCount && (batchPixelCount < minBatchPixelCount)) {
             minBatchPixelCount = batchPixelCount;
             minBatchStart = i;
+            minBatchEnd = j-1;
         }
     }
 
@@ -737,8 +801,10 @@
         return false;
     }
 
+    /* non-dropped layers falling ouside the selected batch will be marked for
+     * MDP */
     for(int i = 0; i < numAppLayers; i++) {
-        if(i < minBatchStart || i >= minBatchStart + batchSize) {
+        if((i < minBatchStart || i > minBatchEnd) && !mCurrentFrame.drop[i] ) {
             hwc_layer_1_t* layer = &list->hwLayers[i];
             if(not isSupportedForMDPComp(ctx, layer)) {
                 ALOGD_IF(isDebug(), "%s: MDP unsupported layer found at %d",
@@ -752,10 +818,12 @@
 
     mCurrentFrame.fbZ = minBatchStart;
     mCurrentFrame.fbCount = batchSize;
-    mCurrentFrame.mdpCount = mCurrentFrame.layerCount - batchSize;
+    mCurrentFrame.mdpCount = mCurrentFrame.layerCount - mCurrentFrame.fbCount -
+             mCurrentFrame.dropCount;
 
-    ALOGD_IF(isDebug(), "%s: fbZ %d batchSize %d",
-                __FUNCTION__, mCurrentFrame.fbZ, batchSize);
+    ALOGD_IF(isDebug(), "%s: fbZ %d batchSize %d fbStart: %d fbEnd: %d",
+             __FUNCTION__, mCurrentFrame.fbZ, batchSize, minBatchStart,
+             minBatchEnd);
 
     if(sEnable4k2kYUVSplit){
         adjustForSourceSplit(ctx, list);
@@ -789,7 +857,9 @@
     const int fullScreenLayers = bwLeft * 1000000000 / (ctx->dpyAttr[mDpy].xres
             * ctx->dpyAttr[mDpy].yres * bpp * panelRefRate);
 
-    const int fbBatchSize = numAppLayers - (fullScreenLayers - 1);
+    const int fbBatchSize = (numAppLayers - mCurrentFrame.dropCount)
+            - (fullScreenLayers - 1);
+
     //If batch size is not at least 2, we aren't really preferring MDP, since
     //only 1 layer going to GPU could actually translate into an entire FB
     //needed to be fetched by MDP, thus needing more b/w rather than less.
@@ -798,28 +868,43 @@
         return false;
     }
 
-    //Top-most layers constitute FB batch
-    const int fbBatchStart = numAppLayers - fbBatchSize;
+    //Find top fbBatchSize non-dropped layers to get your batch
+    int fbStart = -1, fbEnd = -1, batchCount = fbBatchSize;
+    for(int i = numAppLayers - 1; i >= 0; i--) {
+        if(mCurrentFrame.drop[i])
+            continue;
 
-    //Bottom-most layers constitute MDP batch
-    for(int i = 0; i < fbBatchStart; i++) {
-        hwc_layer_1_t* layer = &list->hwLayers[i];
-        if(not isSupportedForMDPComp(ctx, layer)) {
-            ALOGD_IF(isDebug(), "%s: MDP unsupported layer found at %d",
-                    __FUNCTION__, i);
-            reset(ctx);
-            return false;
+        if(fbEnd < 0)
+            fbEnd = i;
+
+        if(!(--batchCount)) {
+            fbStart = i;
+            break;
         }
-        mCurrentFrame.isFBComposed[i] = false;
     }
 
-    mCurrentFrame.fbZ = fbBatchStart;
-    mCurrentFrame.fbCount = fbBatchSize;
-    mCurrentFrame.mdpCount = mCurrentFrame.layerCount - fbBatchSize;
+    //Bottom layers constitute MDP batch
+    for(int i = 0; i < fbStart; i++) {
+        if((i < fbStart || i > fbEnd) && !mCurrentFrame.drop[i] ) {
+            hwc_layer_1_t* layer = &list->hwLayers[i];
+            if(not isSupportedForMDPComp(ctx, layer)) {
+                ALOGD_IF(isDebug(), "%s: MDP unsupported layer found at %d",
+                         __FUNCTION__, i);
+                reset(ctx);
+                return false;
+            }
+            mCurrentFrame.isFBComposed[i] = false;
+        }
+    }
 
-    ALOGD_IF(isDebug(), "%s: FB Z %d, num app layers %d, MDP Batch Size %d",
-                __FUNCTION__, mCurrentFrame.fbZ, numAppLayers,
-                numAppLayers - fbBatchSize);
+    mCurrentFrame.fbZ = fbStart;
+    mCurrentFrame.fbCount = fbBatchSize;
+    mCurrentFrame.mdpCount = mCurrentFrame.layerCount - mCurrentFrame.fbCount
+                                                      - mCurrentFrame.dropCount;
+
+    ALOGD_IF(isDebug(), "%s: FB Z %d, app layers %d, non-dropped layers: %d, "
+             "MDP Batch Size %d",__FUNCTION__, mCurrentFrame.fbZ, numAppLayers,
+             numAppLayers - mCurrentFrame.dropCount, mCurrentFrame.mdpCount);
 
     if(sEnable4k2kYUVSplit){
         adjustForSourceSplit(ctx, list);
@@ -955,11 +1040,13 @@
         int& maxBatchCount) {
     int i = 0;
     int fbZOrder =-1;
+    int droppedLayerCt = 0;
     while (i < mCurrentFrame.layerCount) {
         int batchCount = 0;
         int batchStart = i;
         int batchEnd = i;
-        int fbZ = batchStart;
+        /* 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) {
@@ -974,6 +1061,7 @@
             } else {
                 if(mCurrentFrame.drop[i]) {
                     i++;
+                    droppedLayerCt++;
                     continue;
                 } else if(updatingLayersAbove <= 0) {
                     batchCount++;
@@ -1597,7 +1685,7 @@
 
     /* reset Invalidator */
     if(idleInvalidator && !sIdleFallBack && mCurrentFrame.mdpCount)
-        idleInvalidator->markForSleep();
+        idleInvalidator->handleUpdateEvent();
 
     overlay::Overlay& ov = *ctx->mOverlay;
     LayerProp *layerProp = ctx->layerProp[mDpy];
@@ -1944,7 +2032,7 @@
 
     /* reset Invalidator */
     if(idleInvalidator && !sIdleFallBack && mCurrentFrame.mdpCount)
-        idleInvalidator->markForSleep();
+        idleInvalidator->handleUpdateEvent();
 
     overlay::Overlay& ov = *ctx->mOverlay;
     LayerProp *layerProp = ctx->layerProp[mDpy];
diff --git a/libhwcomposer/hwc_mdpcomp.h b/libhwcomposer/hwc_mdpcomp.h
index 05a560b..bc41bd9 100644
--- a/libhwcomposer/hwc_mdpcomp.h
+++ b/libhwcomposer/hwc_mdpcomp.h
@@ -25,7 +25,7 @@
 #include <cutils/properties.h>
 #include <overlay.h>
 
-#define DEFAULT_IDLE_TIME 2000
+#define DEFAULT_IDLE_TIME 70
 #define MAX_PIPES_PER_MIXER 4
 
 namespace overlay {
@@ -45,7 +45,7 @@
     virtual bool draw(hwc_context_t *ctx, hwc_display_contents_1_t *list) = 0;
     /* dumpsys */
     void dump(android::String8& buf);
-
+    bool isGLESOnlyComp() { return (mCurrentFrame.mdpCount == 0); }
     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);
diff --git a/libhwcomposer/hwc_qclient.cpp b/libhwcomposer/hwc_qclient.cpp
index 50e94c9..8c5b079 100644
--- a/libhwcomposer/hwc_qclient.cpp
+++ b/libhwcomposer/hwc_qclient.cpp
@@ -1,5 +1,5 @@
 /*
- *  Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *  Copyright (c) 2013-14, 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
@@ -31,11 +31,13 @@
 #include <IQService.h>
 #include <hwc_utils.h>
 #include <hwc_vpuclient.h>
+#include <mdp_version.h>
 
 #define QCLIENT_DEBUG 0
 
 using namespace android;
 using namespace qService;
+using namespace qhwc;
 
 namespace qClient {
 
@@ -93,16 +95,19 @@
     return result;
 }
 
+#ifdef VPU_TARGET
 static android::status_t vpuCommand(hwc_context_t *ctx,
         uint32_t command,
         const Parcel* inParcel,
         Parcel* outParcel) {
     status_t result = NO_INIT;
-#ifdef VPU_TARGET
-    result = ctx->mVPUClient->processCommand(command, inParcel, outParcel);
+#ifdef QCOM_BSP
+    if(qdutils::MDPVersion::getInstance().is8092())
+        result = ctx->mVPUClient->processCommand(command, inParcel, outParcel);
 #endif
     return result;
 }
+#endif
 
 static void setExtOrientation(hwc_context_t *ctx, uint32_t orientation) {
     ctx->mExtOrientation = orientation;
@@ -165,14 +170,27 @@
     }
 }
 
+static void pauseWFD(hwc_context_t *ctx, uint32_t pause) {
+    int dpy = HWC_DISPLAY_VIRTUAL;
+    if(pause) {
+        //WFD Pause
+        handle_pause(ctx, dpy);
+    } else {
+        //WFD Resume
+        handle_resume(ctx, dpy);
+    }
+}
+
 status_t QClient::notifyCallback(uint32_t command, const Parcel* inParcel,
         Parcel* outParcel) {
     status_t ret = NO_ERROR;
 
+#ifdef VPU_TARGET
     if (command > IQService::VPU_COMMAND_LIST_START &&
         command < IQService::VPU_COMMAND_LIST_END) {
         return vpuCommand(mHwcContext, command, inParcel, outParcel);
     }
+#endif
 
     switch(command) {
         case IQService::SECURING:
@@ -202,6 +220,8 @@
             break;
         case IQService::SET_HSIC_DATA:
             setHSIC(mHwcContext, inParcel);
+        case IQService::PAUSE_WFD:
+            pauseWFD(mHwcContext, inParcel->readInt32());
             break;
         default:
             ret = NO_ERROR;
diff --git a/libhwcomposer/hwc_uevents.cpp b/libhwcomposer/hwc_uevents.cpp
index 51e5526..e51a1a4 100644
--- a/libhwcomposer/hwc_uevents.cpp
+++ b/libhwcomposer/hwc_uevents.cpp
@@ -1,7 +1,7 @@
 
 /*
  * Copyright (C) 2010 The Android Open Source Project
- * Copyright (C) 2012, The Linux Foundation. All rights reserved.
+ * Copyright (C) 2012-14, The Linux Foundation. All rights reserved.
  *
  * Not a Contribution, Apache license notifications and license are
  * retained for attribution purposes only.
@@ -50,13 +50,6 @@
 {
     ctx->mFBUpdate[dpy] = IFBUpdate::getObject(ctx, dpy);
     ctx->mMDPComp[dpy] =  MDPComp::getObject(ctx, dpy);
-    int compositionType =
-                qdutils::QCCompositionType::getInstance().getCompositionType();
-    if (compositionType & (qdutils::COMPOSITION_TYPE_DYN |
-                           qdutils::COMPOSITION_TYPE_MDP |
-                           qdutils::COMPOSITION_TYPE_C2D)) {
-        ctx->mCopyBit[dpy] = new CopyBit(ctx, dpy);
-    }
 }
 
 static void clear(hwc_context_t* ctx, int dpy)
@@ -65,10 +58,6 @@
         delete ctx->mFBUpdate[dpy];
         ctx->mFBUpdate[dpy] = NULL;
     }
-    if(ctx->mCopyBit[dpy]){
-        delete ctx->mCopyBit[dpy];
-        ctx->mCopyBit[dpy] = NULL;
-    }
     if(ctx->mMDPComp[dpy]) {
         delete ctx->mMDPComp[dpy];
         ctx->mMDPComp[dpy] = NULL;
@@ -117,6 +106,87 @@
     return -1;
 }
 
+void handle_pause(hwc_context_t* ctx, int dpy) {
+    {
+        Locker::Autolock _l(ctx->mDrawLock);
+        ctx->dpyAttr[dpy].isActive = true;
+        ctx->dpyAttr[dpy].isPause = true;
+        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.
+    {
+        Locker::Autolock _l(ctx->mDrawLock);
+        // Perform commit to unstage the pipes.
+        if (!Overlay::displayCommit(ctx->dpyAttr[dpy].fd)) {
+            ALOGE("%s: display commit fail! for %d dpy",
+                  __FUNCTION__, dpy);
+        }
+    }
+    return;
+}
+
+void handle_resume(hwc_context_t* ctx, int dpy) {
+    //Treat Resume as Online event
+    //Since external didnt have any pipes, force primary to give up
+    //its pipes; we don't allow inter-mixer pipe transfers.
+    {
+        Locker::Autolock _l(ctx->mDrawLock);
+
+        // A dynamic resolution change (DRC) can be made for a WiFi
+        // display. In order to support the resolution change, we
+        // need to reconfigure the corresponding display attributes.
+        // Since DRC is only on WiFi display, we only need to call
+        // configure() on the VirtualDisplay device.
+        if(dpy == HWC_DISPLAY_VIRTUAL)
+            ctx->mVirtualDisplay->configure();
+
+        ctx->dpyAttr[dpy].isConfiguring = true;
+        ctx->dpyAttr[dpy].isActive = true;
+        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.
+    {
+        Locker::Autolock _l(ctx->mDrawLock);
+        ctx->dpyAttr[dpy].isPause = false;
+        ctx->proc->invalidate(ctx->proc);
+    }
+    return;
+}
+
+static void teardownWfd(hwc_context_t* ctx) {
+    // Teardown WFD display
+    ALOGD_IF(UEVENT_DEBUG,"Received HDMI connection request when WFD is "
+            "active");
+    {
+        Locker::Autolock _l(ctx->mDrawLock);
+        clear(ctx, HWC_DISPLAY_VIRTUAL);
+        ctx->dpyAttr[HWC_DISPLAY_VIRTUAL].connected = false;
+        ctx->dpyAttr[HWC_DISPLAY_VIRTUAL].isActive = false;
+    }
+
+    ctx->mVirtualDisplay->teardown();
+
+    /* Need to send hotplug only when connected WFD in proprietary path */
+    if(ctx->mVirtualonExtActive) {
+        ALOGE_IF(UEVENT_DEBUG,"%s: Sending EXTERNAL OFFLINE"
+                "hotplug event for wfd display", __FUNCTION__);
+        ctx->proc->hotplug(ctx->proc, HWC_DISPLAY_EXTERNAL,
+                EXTERNAL_OFFLINE);
+        {
+            Locker::Autolock _l(ctx->mDrawLock);
+            ctx->mVirtualonExtActive = false;
+        }
+    }
+    /* Wait for few frames for SF to tear down the WFD session. */
+    usleep(ctx->dpyAttr[HWC_DISPLAY_PRIMARY].vsync_period
+            * 2 / 1000);
+}
+
 static void handle_uevent(hwc_context_t* ctx, const char* udata, int len)
 {
     bool bpanelReset = getPanelResetStatus(ctx, udata, len);
@@ -196,33 +266,22 @@
 
             if(dpy == HWC_DISPLAY_EXTERNAL) {
                 if(ctx->dpyAttr[HWC_DISPLAY_VIRTUAL].connected) {
-                    ALOGD_IF(UEVENT_DEBUG,"Received HDMI connection request"
-                             "when WFD is active");
-                    {
-                        Locker::Autolock _l(ctx->mDrawLock);
-                        clear(ctx, HWC_DISPLAY_VIRTUAL);
-                        ctx->dpyAttr[HWC_DISPLAY_VIRTUAL].connected = false;
-                        ctx->dpyAttr[HWC_DISPLAY_VIRTUAL].isActive = false;
+                    // Triple Display is supported on 8084 target
+                    // WFD can be initiated by Wfd-client or Settings app
+                    // 1. wfd-client use hdmi hotplug mechanism.
+                    //    If wfd is connected via wfd-client and if HDMI is
+                    //    connected, we have to teardown wfd session.
+                    //    (as SF support only one active External display
+                    //     at a given time).
+                    //    (ToDo: Once wfd-client migrates using virtual display
+                    //     apis, second condition is redundant).
+                    // 2. Settings app use virtual display mechanism.
+                    //    In this approach, there is no limitation of supporting
+                    //    triple display.
+                    if(!(qdutils::MDPVersion::getInstance().is8084() &&
+                                !ctx->mVirtualonExtActive)) {
+                        teardownWfd(ctx);
                     }
-
-                    ctx->mVirtualDisplay->teardown();
-
-                    /* Need to send hotplug only when connected WFD in
-                     * proprietary path */
-                    if(ctx->mVirtualonExtActive) {
-                        ALOGE_IF(UEVENT_DEBUG,"%s: Sending EXTERNAL OFFLINE"
-                                 "hotplug event", __FUNCTION__);
-                        ctx->proc->hotplug(ctx->proc, HWC_DISPLAY_EXTERNAL,
-                                           EXTERNAL_OFFLINE);
-                        {
-                            Locker::Autolock _l(ctx->mDrawLock);
-                            ctx->mVirtualonExtActive = false;
-                        }
-                    }
-                    /* Wait for few frames for SF to tear down
-                     * the WFD session. */
-                    usleep(ctx->dpyAttr[HWC_DISPLAY_PRIMARY].vsync_period
-                           * 2 / 1000);
                 }
                 ctx->mExtDisplay->configure();
             } else {
@@ -267,25 +326,8 @@
         case EXTERNAL_PAUSE:
             {   // pause case
                 ALOGD("%s Received Pause event",__FUNCTION__);
-                 {
-                     Locker::Autolock _l(ctx->mDrawLock);
-                     ctx->dpyAttr[dpy].isActive = true;
-                     ctx->dpyAttr[dpy].isPause = true;
-                     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.
-                 {
-                     Locker::Autolock _l(ctx->mDrawLock);
-                     // Perform commit to unstage the pipes.
-                     if (!Overlay::displayCommit(ctx->dpyAttr[dpy].fd)) {
-                         ALOGE("%s: display commit fail! for %d dpy",
-                                 __FUNCTION__, dpy);
-                     }
-                 }
-                 break;
+                handle_pause(ctx, dpy);
+                break;
             }
         case EXTERNAL_RESUME:
             {  // resume case
@@ -293,29 +335,7 @@
                 //Treat Resume as Online event
                 //Since external didnt have any pipes, force primary to give up
                 //its pipes; we don't allow inter-mixer pipe transfers.
-                {
-                    Locker::Autolock _l(ctx->mDrawLock);
-
-                    // A dynamic resolution change (DRC) can be made for a WiFi
-                    // display. In order to support the resolution change, we
-                    // need to reconfigure the corresponding display attributes.
-                    // Since DRC is only on WiFi display, we only need to call
-                    // configure() on the VirtualDisplay device.
-                    if(dpy == HWC_DISPLAY_VIRTUAL)
-                        ctx->mVirtualDisplay->configure();
-
-                    ctx->dpyAttr[dpy].isConfiguring = true;
-                    ctx->dpyAttr[dpy].isActive = true;
-                    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.
-                {
-                    Locker::Autolock _l(ctx->mDrawLock);
-                    ctx->dpyAttr[dpy].isPause = false;
-                    ctx->proc->invalidate(ctx->proc);
-                }
+                handle_resume(ctx, dpy);
                 break;
             }
     default:
diff --git a/libhwcomposer/hwc_utils.cpp b/libhwcomposer/hwc_utils.cpp
index 0663f67..f6476f5 100644
--- a/libhwcomposer/hwc_utils.cpp
+++ b/libhwcomposer/hwc_utils.cpp
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2010 The Android Open Source Project
- * Copyright (C) 2012-2013, The Linux Foundation All rights reserved.
+ * Copyright (C) 2012-2014, The Linux Foundation All rights reserved.
  *
  * Not a Contribution, Apache license notifications and license are retained
  * for attribution purposes only.
@@ -43,6 +43,7 @@
 #include "hwc_qclient.h"
 #include "QService.h"
 #include "comptype.h"
+#include "hwc_virtual.h"
 
 using namespace qClient;
 using namespace qService;
@@ -53,6 +54,34 @@
 
 namespace qhwc {
 
+bool isValidResolution(hwc_context_t *ctx, uint32_t xres, uint32_t yres)
+{
+    return !((xres > qdutils::MAX_DISPLAY_DIM &&
+                !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) {
+    //Store original display resolution.
+    ctx->dpyAttr[HWC_DISPLAY_PRIMARY].xres_orig = xres_orig;
+    ctx->dpyAttr[HWC_DISPLAY_PRIMARY].yres_orig = 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");
+        int xres = atoi(property);
+        int yres = atoi(yptr + 1);
+        if (isValidResolution(ctx,xres,yres) &&
+                 xres != xres_orig && yres != yres_orig) {
+            ctx->dpyAttr[HWC_DISPLAY_PRIMARY].xres = xres;
+            ctx->dpyAttr[HWC_DISPLAY_PRIMARY].yres = yres;
+            ctx->dpyAttr[HWC_DISPLAY_PRIMARY].customFBSize = true;
+        }
+    }
+}
+
 static int openFramebufferDevice(hwc_context_t *ctx)
 {
     struct fb_fix_screeninfo finfo;
@@ -116,6 +145,9 @@
     ctx->dpyAttr[HWC_DISPLAY_PRIMARY].ydpi = ydpi;
     ctx->dpyAttr[HWC_DISPLAY_PRIMARY].vsync_period = 1000000000l / fps;
 
+    //To change resolution of primary display
+    changeResolution(ctx, info.xres, info.yres);
+
     //Unblank primary on first boot
     if(ioctl(fb_fd, FBIOBLANK,FB_BLANK_UNBLANK) < 0) {
         ALOGE("%s: Failed to unblank display", __FUNCTION__);
@@ -142,16 +174,18 @@
     ctx->mFBUpdate[HWC_DISPLAY_PRIMARY] =
         IFBUpdate::getObject(ctx, HWC_DISPLAY_PRIMARY);
 
-    // Check if the target supports copybit compostion (dyn/mdp/c2d) to
+    // 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();
 
-    if (compositionType & (qdutils::COMPOSITION_TYPE_DYN |
-                           qdutils::COMPOSITION_TYPE_MDP |
-                           qdutils::COMPOSITION_TYPE_C2D)) {
-            ctx->mCopyBit[HWC_DISPLAY_PRIMARY] = new CopyBit(ctx,
-                    HWC_DISPLAY_PRIMARY);
+    // Only MDP copybit is used
+    if ((compositionType & (qdutils::COMPOSITION_TYPE_DYN |
+            qdutils::COMPOSITION_TYPE_MDP)) &&
+            (qdutils::MDPVersion::getInstance().getMDPVersion() ==
+            qdutils::MDP_V3_0_4)) {
+        ctx->mCopyBit[HWC_DISPLAY_PRIMARY] = new CopyBit(ctx,
+                                                         HWC_DISPLAY_PRIMARY);
     }
 
     ctx->mExtDisplay = new ExternalDisplay(ctx);
@@ -168,11 +202,15 @@
     ctx->mMDPComp[HWC_DISPLAY_PRIMARY] =
          MDPComp::getObject(ctx, HWC_DISPLAY_PRIMARY);
     ctx->dpyAttr[HWC_DISPLAY_PRIMARY].connected = true;
+    ctx->mHWCVirtual = HWCVirtualBase::getObject();
 
     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;
     }
 
     MDPComp::init(ctx);
@@ -181,6 +219,7 @@
     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.
@@ -193,8 +232,11 @@
     // Initialize device orientation to its default orientation
     ctx->deviceOrientation = 0;
     ctx->mBufferMirrorMode = false;
+    ctx->mVPUClient = NULL;
+
 #ifdef VPU_TARGET
-    ctx->mVPUClient = new VPUClient();
+    if(qdutils::MDPVersion::getInstance().is8092())
+        ctx->mVPUClient = new VPUClient(ctx);
 #endif
 
     ALOGI("Initializing Qualcomm Hardware Composer");
@@ -231,9 +273,8 @@
     }
 
 #ifdef VPU_TARGET
-    if(ctx->mVPUClient) {
+    if(ctx->mVPUClient != NULL)
         delete ctx->mVPUClient;
-    }
 #endif
 
     for(int i = 0; i < HWC_NUM_DISPLAY_TYPES; i++) {
@@ -254,6 +295,10 @@
             ctx->mLayerRotMap[i] = NULL;
         }
     }
+    if(ctx->mHWCVirtual) {
+        delete ctx->mHWCVirtual;
+        ctx->mHWCVirtual = NULL;
+    }
     if(ctx->mAD) {
         delete ctx->mAD;
         ctx->mAD = NULL;
@@ -285,22 +330,11 @@
     int w = rect.right - rect.left;
     int h = rect.bottom - rect.top;
 
-    // if external supports underscan, do nothing
-    // it will be taken care in the driver
-    if(ctx->mExtDisplay->isCEUnderscanSupported())
+    if(!ctx->dpyAttr[dpy].mActionSafePresent)
         return;
-
-    char value[PROPERTY_VALUE_MAX];
-    // Read action safe properties
-    property_get("persist.sys.actionsafe.width", value, "0");
-    int asWidthRatio = atoi(value);
-    property_get("persist.sys.actionsafe.height", value, "0");
-    int asHeightRatio = atoi(value);
-
-    if(!asWidthRatio && !asHeightRatio) {
-        //No action safe ratio set, return
-        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;
@@ -433,8 +467,8 @@
     xRatio = (inPos.x - viewFrame.left)/actualWidth;
     yRatio = (inPos.y - viewFrame.top)/actualHeight;
     // Use viewframe width and height to compute wRatio and hRatio.
-    wRatio = inPos.w/(viewFrame.right - viewFrame.left);
-    hRatio = inPos.h/(viewFrame.bottom - viewFrame.top);
+    wRatio = (float)inPos.w/(float)(viewFrame.right - viewFrame.left);
+    hRatio = (float)inPos.h/(float)(viewFrame.bottom - viewFrame.top);
 
 
     //Calculate the position...
@@ -626,7 +660,6 @@
 }
 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);
 
@@ -763,6 +796,7 @@
     ctx->listStats[dpy].secureUI = false;
     ctx->listStats[dpy].yuv4k2kCount = 0;
     ctx->mViewFrame[dpy] = (hwc_rect_t){0, 0, 0, 0};
+    ctx->dpyAttr[dpy].mActionSafePresent = isActionSafePresent(ctx, dpy);
 
     trimList(ctx, list, dpy);
     optimizeLayerRects(ctx, list, dpy);
@@ -920,6 +954,27 @@
         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
+    if(!dpy || ctx->mExtDisplay->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:
@@ -1078,7 +1133,8 @@
                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 = layer->sourceCrop;
+                  hwc_rect_t bottomCrop =
+                      integerizeSourceCrop(layer->sourceCropf);
                   int transform =layer->transform;
 
                   hwc_rect_t irect = getIntersection(bottomframe, topframe);
@@ -1088,7 +1144,11 @@
                      dest_rect  = deductRect(bottomframe, irect);
                      qhwc::calculate_crop_rects(bottomCrop, bottomframe,
                                                 dest_rect, transform);
-
+                     //Update layer sourceCropf
+                     layer->sourceCropf.left = bottomCrop.left;
+                     layer->sourceCropf.top = bottomCrop.top;
+                     layer->sourceCropf.right = bottomCrop.right;
+                     layer->sourceCropf.bottom = bottomCrop.bottom;
                   }
                }
                j--;
@@ -1123,12 +1183,19 @@
 }
 
 void closeAcquireFds(hwc_display_contents_1_t* list) {
-    for(uint32_t i = 0; list && 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;
+    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;
         }
     }
 }
@@ -1140,6 +1207,7 @@
     int acquireFd[MAX_NUM_APP_LAYERS];
     int count = 0;
     int releaseFd = -1;
+    int retireFd = -1;
     int fbFd = -1;
     bool swapzero = false;
     int mdpVersion = qdutils::MDPVersion::getInstance().getMDPVersion();
@@ -1148,6 +1216,8 @@
     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) {
@@ -1187,6 +1257,11 @@
     }
 
     //Accumulate acquireFenceFds for MDP
+    if(list->outbufAcquireFenceFd >= 0) {
+        //Writeback output buffer
+        acquireFd[count++] = list->outbufAcquireFenceFd;
+    }
+
     for(uint32_t i = 0; i < list->numHwLayers; i++) {
         if((list->hwLayers[i].compositionType == HWC_OVERLAY  ||
                         list->hwLayers[i].compositionType == HWC_BLIT) &&
@@ -1229,6 +1304,7 @@
               dpy, list->numHwLayers);
     }
 
+    LayerProp *layerProp = ctx->layerProp[dpy];
     for(uint32_t i = 0; i < list->numHwLayers; i++) {
         if(list->hwLayers[i].compositionType == HWC_OVERLAY ||
            list->hwLayers[i].compositionType == HWC_BLIT ||
@@ -1240,8 +1316,10 @@
                 // Release all the app layer fds immediately,
                 // if animation is in progress.
                 list->hwLayers[i].releaseFenceFd = -1;
-            } else if(list->hwLayers[i].releaseFenceFd < 0) {
-                //If rotator has not already populated this field.
+            } else if(list->hwLayers[i].releaseFenceFd < 0 &&
+                    !(layerProp[i].mFlags & HWC_VPUCOMP)) {
+                //If rotator has not already populated this field
+                // & if it's a not VPU layer
                 list->hwLayers[i].releaseFenceFd = dup(releaseFd);
             }
         }
@@ -1257,20 +1335,14 @@
 
     //Signals when MDP finishes reading rotator buffers.
     ctx->mLayerRotMap[dpy]->setReleaseFd(releaseFd);
+    close(releaseFd);
+    releaseFd = -1;
 
-    // if external is animating, close the relaseFd
-    if(isExtAnimating) {
-        close(releaseFd);
-        releaseFd = -1;
-    }
-
-    if(UNLIKELY(swapzero)){
+    if(UNLIKELY(swapzero)) {
         list->retireFenceFd = -1;
-        close(releaseFd);
     } else {
-        list->retireFenceFd = releaseFd;
+        list->retireFenceFd = retireFd;
     }
-
     return ret;
 }
 
@@ -1285,13 +1357,19 @@
                 ovutils::OV_MDP_BLEND_FG_PREMULT);
     }
 
+    if (layer->flags & HWC_VPU_PIPE) {
+        ovutils::setMdpFlags(mdpFlags, ovutils::OV_MDP_VPU_PIPE);
+    }
+
     if(isYuvBuffer(hnd)) {
         if(isSecureBuffer(hnd)) {
             ovutils::setMdpFlags(mdpFlags,
                     ovutils::OV_MDP_SECURE_OVERLAY_SESSION);
         }
+        // in mpq, deinterlacing is done in vpu
         if(metadata && (metadata->operation & PP_PARAM_INTERLACED) &&
-                metadata->interlaced) {
+                metadata->interlaced &&
+                (!qdutils::MDPVersion::getInstance().is8092())) {
             ovutils::setMdpFlags(mdpFlags,
                     ovutils::OV_MDP_DEINTERLACE);
         }
@@ -1476,8 +1554,19 @@
     eTransform orient = static_cast<eTransform>(transform);
     int downscale = 0;
     int rotFlags = ovutils::ROT_FLAGS_NONE;
-    Whf whf(getWidth(hnd), getHeight(hnd),
-            getMdpFormat(hnd->format), hnd->size);
+    uint32_t format = ovutils::getMdpFormat(hnd->format, isTileRendered(hnd));
+    Whf whf(getWidth(hnd), getHeight(hnd), format, hnd->size);
+    LayerProp *layerProp = ctx->layerProp[dpy];
+
+#ifdef VPU_TARGET
+    if(ctx->mVPUClient != NULL &&
+            ctx->mVPUClient->supportedVPULayer(dpy, layer)) {
+        whf.format = getMdpFormat(
+                ctx->mVPUClient->getLayerFormat(dpy, layer));
+        whf.w = ctx->mVPUClient->getWidth(dpy, layer);
+        whf.h = ctx->mVPUClient->getHeight(dpy, layer);
+    }
+#endif
 
     // Handle R/B swap
     if (layer->flags & HWC_FORMAT_RB_SWAP) {
@@ -1583,9 +1672,19 @@
     eTransform orient = static_cast<eTransform>(transform);
     const int downscale = 0;
     int rotFlags = ROT_FLAGS_NONE;
+    uint32_t format = ovutils::getMdpFormat(hnd->format, isTileRendered(hnd));
+    Whf whf(getWidth(hnd), getHeight(hnd), format, hnd->size);
+    LayerProp *layerProp = ctx->layerProp[dpy];
 
-    Whf whf(getWidth(hnd), getHeight(hnd),
-            getMdpFormat(hnd->format), hnd->size);
+#ifdef VPU_TARGET
+    if(ctx->mVPUClient != NULL &&
+            ctx->mVPUClient->supportedVPULayer(dpy, layer)) {
+        whf.format = getMdpFormat(
+                ctx->mVPUClient->getLayerFormat(dpy, layer));
+        whf.w = ctx->mVPUClient->getWidth(dpy, layer);
+        whf.h = ctx->mVPUClient->getHeight(dpy, layer);
+    }
+#endif
 
     // Handle R/B swap
     if (layer->flags & HWC_FORMAT_RB_SWAP) {
@@ -1828,7 +1927,7 @@
 
 bool canUseRotator(hwc_context_t *ctx, int dpy) {
     if(qdutils::MDPVersion::getInstance().is8x26() &&
-            ctx->mVirtualDisplay->isConnected() &&
+            isSecondaryConnected(ctx) &&
             !ctx->dpyAttr[HWC_DISPLAY_VIRTUAL].isPause) {
         /* 8x26 mdss driver supports multiplexing of DMA pipe
          * in LINE and BLOCK modes for writeback panels.
@@ -1864,6 +1963,41 @@
     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];
+}
+
+/* Since we fake non-Hybrid WFD solution as external display, this
+ * function helps us in determining the priority between external
+ * (hdmi/non-Hybrid WFD display) and virtual display devices(SSD/
+ * screenrecord). This can be removed once wfd-client migrates to
+ * using virtual-display api's.
+ */
+bool canUseMDPforVirtualDisplay(hwc_context_t* ctx,
+                                const hwc_display_contents_1_t *list) {
+
+    /* We rely on the fact that for pure virtual display solution
+     * list->outbuf will be a non-NULL handle.
+     *
+     * If there are three active displays (which means there is one
+     * primary, one external and one virtual active display)
+     * we give mdss/mdp hw resources(pipes,smp,etc) for external
+     * display(hdmi/non-Hybrid WFD display) rather than for virtual
+     * display(SSD/screenrecord)
+     */
+
+    if(list->outbuf and (ctx->numActiveDisplays == HWC_NUM_DISPLAY_TYPES)) {
+        return false;
+    }
+
+    return true;
+}
+
 void BwcPM::setBwc(hwc_context_t *ctx, const hwc_rect_t& crop,
             const hwc_rect_t& dst, const int& transform,
             ovutils::eMdpFlags& mdpFlags) {
diff --git a/libhwcomposer/hwc_utils.h b/libhwcomposer/hwc_utils.h
index cd84f73..ce1abeb 100644
--- a/libhwcomposer/hwc_utils.h
+++ b/libhwcomposer/hwc_utils.h
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2010 The Android Open Source Project
- * Copyright (C)2012-2013, The Linux Foundation. All rights reserved.
+ * Copyright (C)2012-2014, The Linux Foundation. All rights reserved.
  *
  * Not a Contribution, Apache license notifications and license are retained
  * for attribution purposes only.
@@ -35,6 +35,8 @@
 #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
 
 //Fwrd decls
 struct hwc_context_t;
@@ -59,6 +61,7 @@
 class HwcDebug;
 class AssertiveDisplay;
 class VPUClient;
+class HWCVirtualBase;
 
 
 struct MDPInfo {
@@ -89,6 +92,18 @@
     bool mDownScaleMode;
     // 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_orig;
+    uint32_t yres_orig;
+
 };
 
 struct ListStats {
@@ -130,12 +145,14 @@
 enum {
     HWC_MDPCOMP = 0x00000001,
     HWC_COPYBIT = 0x00000002,
+    HWC_VPUCOMP = 0x00000004,
 };
 
 // HAL specific features
 enum {
     HWC_COLOR_FILL = 0x00000008,
     HWC_FORMAT_RB_SWAP = 0x00000040,
+    HWC_VPU_PIPE = 0x00000200,
 };
 
 class LayerRotMap {
@@ -216,6 +233,11 @@
 bool isAlphaPresent(hwc_layer_1_t const* layer);
 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 canUseMDPforVirtualDisplay(hwc_context_t* ctx,
+                                const hwc_display_contents_1_t *list);
 
 //Helper function to dump logs
 void dumpsys_log(android::String8& buf, const char* fmt, ...);
@@ -230,6 +252,9 @@
 bool areLayersIntersecting(const hwc_layer_1_t* layer1,
         const hwc_layer_1_t* layer2);
 
+// 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);
 
@@ -255,6 +280,10 @@
 // BufferMirrirMode(Sidesync)
 int getMirrorModeOrientation(hwc_context_t *ctx);
 
+// Handles wfd Pause and resume events
+void handle_pause(hwc_context_t *ctx, int dpy);
+void handle_resume(hwc_context_t *ctx, int dpy);
+
 //Close acquireFenceFds of all layers of incoming list
 void closeAcquireFds(hwc_display_contents_1_t* list);
 
@@ -334,6 +363,11 @@
 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));
+}
+
 //Return true if buffer is marked locked
 static inline bool isBufferLocked(const private_handle_t* hnd) {
     return (hnd && (private_handle_t::PRIV_FLAGS_HWC_LOCK & hnd->flags));
@@ -448,6 +482,7 @@
     qhwc::AssertiveDisplay *mAD;
     qhwc::VPUClient *mVPUClient;
     eAnimationState mAnimationState[HWC_NUM_DISPLAY_TYPES];
+    qhwc::HWCVirtualBase *mHWCVirtual;
 
     // stores the primary device orientation
     int deviceOrientation;
@@ -465,15 +500,14 @@
     int mExtOrientation;
     //Flags the transition of a video session
     bool mVideoTransFlag;
-
     //Used for SideSync feature
     //which overrides the mExtOrientation
     bool mBufferMirrorMode;
-
     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;
 };
 
 namespace qhwc {
@@ -494,6 +528,16 @@
     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);
+}
+
 };
 
 #endif //HWC_UTILS_H
diff --git a/libhwcomposer/hwc_virtual.cpp b/libhwcomposer/hwc_virtual.cpp
new file mode 100644
index 0000000..600ba8d
--- /dev/null
+++ b/libhwcomposer/hwc_virtual.cpp
@@ -0,0 +1,272 @@
+/*
+ * 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 <utils/Trace.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"
+
+#define HWCVIRTUAL_LOG 0
+
+using namespace qhwc;
+using namespace overlay;
+
+HWCVirtualBase* HWCVirtualBase::getObject() {
+    char property[PROPERTY_VALUE_MAX];
+
+    if((property_get("persist.hwc.enable_vds", property, NULL) > 0)) {
+        if(atoi(property) != 0) {
+            ALOGD_IF(HWCVIRTUAL_LOG, "%s: VDS is enabled for Virtual display",
+                __FUNCTION__);
+            return new HWCVirtualVDS();
+        }
+    }
+    ALOGD_IF(HWCVIRTUAL_LOG, "%s: V4L2 is enabled for Virtual display",
+            __FUNCTION__);
+    return new HWCVirtualV4L2();
+}
+
+void HWCVirtualVDS::init(hwc_context_t *ctx) {
+    const int dpy = HWC_DISPLAY_VIRTUAL;
+    ctx->mFBUpdate[dpy] =
+            IFBUpdate::getObject(ctx, dpy);
+    ctx->mMDPComp[dpy] =  MDPComp::getObject(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;
+
+        if(ctx->mFBUpdate[dpy]) {
+            delete ctx->mFBUpdate[dpy];
+            ctx->mFBUpdate[dpy] = NULL;
+        }
+        if(ctx->mMDPComp[dpy]) {
+            delete ctx->mMDPComp[dpy];
+            ctx->mMDPComp[dpy] = NULL;
+        }
+    }
+}
+
+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, list->numHwLayers - 1);
+        uint32_t last = 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;
+            init(ctx);
+            //First round, just setup and return so primary can free pipes
+            return 0;
+        }
+
+        ctx->dpyAttr[dpy].isConfiguring = false;
+        ctx->dpyAttr[dpy].fd = Writeback::getInstance()->getFbFd();
+        private_handle_t *ohnd = (private_handle_t *)list->outbuf;
+        Writeback::getInstance()->configureDpyInfo(ohnd->width, ohnd->height);
+        setListStats(ctx, list, dpy);
+
+        if(ctx->mMDPComp[dpy]->prepare(ctx, list) < 0) {
+            const int fbZ = 0;
+            ctx->mFBUpdate[dpy]->prepare(ctx, list, fbZ);
+        }
+    }
+    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 = list->numHwLayers - 1;
+        hwc_layer_1_t *fbLayer = &list->hwLayers[last];
+
+        if(fbLayer->handle && !isSecondaryConfiguring(ctx) &&
+                !ctx->mMDPComp[dpy]->isGLESOnlyComp()) {
+            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));
+
+            int fd = -1; //FenceFD from the Copybit
+            hwc_sync(ctx, list, dpy, fd);
+
+            if (!ctx->mMDPComp[dpy]->draw(ctx, list)) {
+                ALOGE("%s: MDPComp draw failed", __FUNCTION__);
+                ret = -1;
+            }
+            if (!ctx->mFBUpdate[dpy]->draw(ctx,
+                        (private_handle_t *)fbLayer->handle)) {
+                ALOGE("%s: FBUpdate::draw fail!", __FUNCTION__);
+                ret = -1;
+            }
+
+            Writeback::getInstance()->queueBuffer(ohnd->fd, ohnd->offset);
+            if(!Overlay::displayCommit(ctx->dpyAttr[dpy].fd)) {
+                ALOGE("%s: display commit fail!", __FUNCTION__);
+                ret = -1;
+            }
+
+        } 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;
+}
+
+/* Implementation for HWCVirtualV4L2 class */
+
+int HWCVirtualV4L2::prepare(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_VIRTUAL;
+
+    if (LIKELY(list && list->numHwLayers > 1) &&
+            ctx->dpyAttr[dpy].isActive &&
+            ctx->dpyAttr[dpy].connected &&
+            canUseMDPforVirtualDisplay(ctx,list)) {
+        reset_layer_prop(ctx, dpy, 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;
+                ctx->mFBUpdate[dpy]->prepare(ctx, list, fbZ);
+            }
+        } else {
+            /* Virtual 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;
+}
+
+int HWCVirtualV4L2::set(hwc_context_t *ctx, hwc_display_contents_1_t *list) {
+    ATRACE_CALL();
+    int ret = 0;
+
+    const int dpy = HWC_DISPLAY_VIRTUAL;
+
+    if (LIKELY(list) && ctx->dpyAttr[dpy].isActive &&
+            ctx->dpyAttr[dpy].connected &&
+            (!ctx->dpyAttr[dpy].isPause) &&
+            canUseMDPforVirtualDisplay(ctx,list)) {
+        uint32_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 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;
+        }
+
+        int extOnlyLayerIndex =
+            ctx->listStats[dpy].extOnlyLayerIndex;
+
+        private_handle_t *hnd = (private_handle_t *)fbLayer->handle;
+        if(extOnlyLayerIndex!= -1) {
+            hwc_layer_1_t *extLayer = &list->hwLayers[extOnlyLayerIndex];
+            hnd = (private_handle_t *)extLayer->handle;
+        } else if(copybitDone) {
+            hnd = ctx->mCopyBit[dpy]->getCurrentRenderBuffer();
+        }
+
+        if(hnd && !isYuvBuffer(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);
+
+    if (list && !ctx->mVirtualonExtActive && (list->retireFenceFd < 0) ) {
+        // SF assumes HWC waits for the acquire fence and returns a new fence
+        // that signals when we're done. Since we don't wait, and also don't
+        // touch the buffer, we can just handle the acquire fence back to SF
+        // as the retire fence.
+        list->retireFenceFd = list->outbufAcquireFenceFd;
+    }
+
+    return ret;
+}
diff --git a/libhwcomposer/hwc_virtual.h b/libhwcomposer/hwc_virtual.h
new file mode 100644
index 0000000..502aa3b
--- /dev/null
+++ b/libhwcomposer/hwc_virtual.h
@@ -0,0 +1,86 @@
+/*
+ * 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 {
+namespace ovutils = overlay::utils;
+
+// Base and abstract class for VDS and V4L2 wfd design.
+class HWCVirtualBase {
+public:
+    explicit HWCVirtualBase(){};
+    virtual ~HWCVirtualBase(){};
+    // instantiates and returns the pointer to VDS or V4L2 object.
+    static HWCVirtualBase* getObject();
+    virtual int prepare(hwc_composer_device_1 *dev,
+                          hwc_display_contents_1_t* list) = 0;
+    virtual int set(hwc_context_t *ctx, hwc_display_contents_1_t *list) = 0;
+    virtual void init(hwc_context_t *ctx) = 0;
+    virtual void destroy(hwc_context_t *ctx, size_t numDisplays,
+                       hwc_display_contents_1_t** displays) = 0;
+};
+
+class HWCVirtualVDS : public HWCVirtualBase {
+public:
+    explicit HWCVirtualVDS(){};
+    virtual ~HWCVirtualVDS(){};
+    // Chooses composition type and configures pipe for each layer in virtual
+    // display list
+    virtual 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.
+    virtual 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.
+    virtual void init(hwc_context_t *ctx);
+    // Destroys mdpcomp, copybit and fbupdate objects and for virtual display
+    // during virtual display disconnect.
+    virtual void destroy(hwc_context_t *ctx, size_t numDisplays,
+                       hwc_display_contents_1_t** displays);
+};
+
+class HWCVirtualV4L2 : public HWCVirtualBase {
+public:
+    explicit HWCVirtualV4L2(){};
+    virtual ~HWCVirtualV4L2(){};
+    // Chooses composition type and configures pipe for each layer in virtual
+    // display list
+    virtual 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.
+    virtual 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. This function
+    // is no-op for V4L2 design
+    virtual void init(hwc_context_t *ctx) {};
+    // Destroys mdpcomp, copybit and fbupdate objects and for virtual display
+    // during virtual display disconnect. This function is no-op for V4L2 design
+    virtual void destroy(hwc_context_t *ctx, size_t numDisplays,
+                       hwc_display_contents_1_t** displays){};
+};
+
+}; //namespace
+#endif
diff --git a/libhwcomposer/hwc_vpuclient.cpp b/libhwcomposer/hwc_vpuclient.cpp
index 23c6841..6904efc 100644
--- a/libhwcomposer/hwc_vpuclient.cpp
+++ b/libhwcomposer/hwc_vpuclient.cpp
@@ -1,93 +1,964 @@
 /*
-* 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.
-*/
+ * 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.  INNO 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 INCONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING INANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
 
 #include <dlfcn.h>
 #include "hwc_vpuclient.h"
-#include "hwc_utils.h"
-#include <vpu/vpu.h>
 #include <binder/Parcel.h>
-
+#include "hwc_fbupdate.h"
+#include <vpu/vpu.h>
 
 using namespace vpu;
 using namespace android;
+using namespace overlay::utils;
+namespace ovutils = overlay::utils;
+
 namespace qhwc {
 
-VPUClient::VPUClient()
+VPUClient::VPUClient(hwc_context_t *ctx)
 {
     mVPULib = dlopen("libvpu.so", RTLD_NOW);
-    VPU* (*init)();
-    *(void **) &init =  dlsym(mVPULib, "getObject");
-    if(init)
-        mVPU = init();
-    else
-        mVPU = NULL;
+    VPU* (*getObject)();
+
+    mVPU = NULL;
+    if (mVPULib == NULL) {
+        ALOGE("%s: Cannot open libvpu.so object", __FUNCTION__);
+        return;
+    }
+
+    *(void **) &getObject =  dlsym(mVPULib, "getObject");
+    if (getObject) {
+        mVPU = getObject();
+        ALOGI("Initializing VPU client..");
+
+       // calling vpu init
+        if (mVPU->init() == NO_ERROR) {
+            // passing display attributes to libvpu
+            ALOGD_IF(isDebug(), "%s: VFM init successful!", __FUNCTION__);
+
+            DispAttr_t attr;
+            attr.width = ctx->dpyAttr[HWC_DISPLAY_PRIMARY].xres;
+            attr.height = ctx->dpyAttr[HWC_DISPLAY_PRIMARY].yres;
+            attr.fp100s = (ctx->dpyAttr[HWC_DISPLAY_PRIMARY].vsync_period) ?
+              1000000000/(ctx->dpyAttr[HWC_DISPLAY_PRIMARY].vsync_period/100):0;
+            mVPU->setDisplayAttr((DISPLAY_ID)HWC_DISPLAY_PRIMARY, attr);
+
+            ALOGD_IF(isDebug(),"%s: Display attr: width:%d height:%d fp100s:%d",
+                    __FUNCTION__, attr.width, attr.height, attr.fp100s);
+
+            // memsetting the pipe structure to 0
+            memset(mProp, 0, sizeof(mProp));
+
+            mDebugLogs = 0;
+            // enable logs
+            char property[PROPERTY_VALUE_MAX];
+            if ( property_get("debug.vpuclient.logs", property, NULL) > 0 )
+                mDebugLogs = atoi(property);
+
+            // allocating memory for LayerList
+            for (int i = 0; i < HWC_NUM_DISPLAY_TYPES; ++i)
+                vList[i] = (LayerList*) malloc(sizeof(LayerList));
+        }
+        else {
+            ALOGE("Error: VPU init failed!");
+            mVPU = NULL;
+        }
+    }
 }
 
 VPUClient::~VPUClient()
 {
+    // freeing LayerList
+    for (int i = 0; i < HWC_NUM_DISPLAY_TYPES; ++i) {
+        if (vList[i])
+            free(vList[i]);
+    }
+
     void (*destroy) (VPU*);
     *(void **) &destroy = dlsym(mVPULib, "deleteObject");
     dlclose(mVPULib);
 }
 
-int VPUClient::prepare(hwc_context_t *ctx,
-                                hwc_display_contents_1_t* list)
+void setLayer(hwc_layer_1_t *layer, Layer *vLayer)
 {
-    int err = 0;
-    if(!mVPU)
-        return err;
-    // * Check VPU status
-    // * Check session availability
-    // * Other individual checks
-    // Do not pass hwc context/list
-    // Mark buffers to be drawn for VPU
-    return err;
+    // setting handle info in vLayer
+    vLayer->handle = (private_handle_t *)(layer->handle);
+
+    if (vLayer->handle) {
+        vLayer->srcStride.width = getWidth(vLayer->handle);
+        vLayer->srcStride.height = getHeight(vLayer->handle);
+    }
+
+    // setting source crop
+    hwc_rect_t sourceRect = integerizeSourceCrop(layer->sourceCropf);
+    vLayer->srcRect.left = sourceRect.left;
+    vLayer->srcRect.top  = sourceRect.top;
+    vLayer->srcRect.right = sourceRect.right;
+    vLayer->srcRect.bottom = sourceRect.bottom;
+
+    // setting destination crop
+    vLayer->tgtRect.left = layer->displayFrame.left;
+    vLayer->tgtRect.top = layer->displayFrame.top;
+    vLayer->tgtRect.right = layer->displayFrame.right;
+    vLayer->tgtRect.bottom = layer->displayFrame.bottom;
+
+    if (layer->flags & HWC_GEOMETRY_CHANGED)
+        vLayer->inFlags |= GEOMETRY_CHANGED;
+
+    vLayer->acquireFenceFd = layer->acquireFenceFd;
+
+    if (layer->compositionType == HWC_FRAMEBUFFER_TARGET || isSkipLayer(layer))
+        vLayer->inFlags |= SKIP_LAYER;
 }
 
-int VPUClient::draw(hwc_context_t *ctx,
-                             hwc_display_contents_1_t* list)
+int VPUClient::setupVpuSession(hwc_context_t *ctx, int display,
+                                            hwc_display_contents_1_t* list)
+{
+    memset(vList[display], 0, sizeof(LayerList));
+    memset(mProp, 0, sizeof(mProp));
+    mNumVpuLayers = 0;
+
+    // setting up the layer
+    LayerList *vpuList = vList[display];
+    vpuList->numLayers = list->numHwLayers;
+    for (unsigned int i=0; i<(list->numHwLayers); ++i) {
+        hwc_layer_1_t *layer = &list->hwLayers[i];
+        Layer *vLayer = &vpuList->layers[i];
+        VpuLayerProp* prop = &mProp[display][i];
+
+        // Storing the sourceCropf, as it's going to be changed for overlay Set
+        // will be restored after overlay set in prepare.
+        prop->sourceCropf = layer->sourceCropf;
+
+        // filling up the vpu list
+        setLayer(layer, vLayer);
+        ALOGD_IF(isDebug2(), "%s:Done setting lyr:%d for VFM", __FUNCTION__, i);
+    }
+
+    if (mVPU->setupVpuSession((DISPLAY_ID)display, vpuList) != NO_ERROR) {
+        //error in vpu prepare
+        ALOGE("%s: ERROR in VPU::setupVpuSession", __FUNCTION__);
+        return -1;
+    }
+    ALOGD_IF(isDebug2(), "%s: Done VFM: setupVpuSession", __FUNCTION__);
+
+    mGpuFallback = true;
+    LayerProp *layerProp = ctx->layerProp[display];
+    // check if the pipeID is already set for this layer, then will need to
+    // ensure that it is reserved in overlay
+    for (unsigned int i=0; i<(vpuList->numLayers); ++i) {
+        hwc_layer_1_t *layer = &list->hwLayers[i];
+        Layer *vLayer = &vpuList->layers[i];
+        VpuLayerProp* prop = &mProp[display][i];
+
+        if (vLayer->outFlags & VPU_LAYER) {
+            ALOGD_IF(isDebug(), "%s: VPU supported layer:%d", __FUNCTION__, i);
+
+            mNumVpuLayers++;
+            mGpuFallback = false;
+            // Reserving the pipe used in last iteration for the same layer
+            if ((vLayer->outFlags & RESERVE_PREV_PIPES) &&
+                                            vLayer->sDestPipes.numPipes > 0) {
+                prop->pipeCount = vLayer->sDestPipes.numPipes;
+                if (prop->pipeCount == 1) {
+                    setPipeId(prop, vLayer->sDestPipes.pipe[0]);
+                    ALOGD_IF(isDebug(), "%s: VPU: Reserved pipe:%d",
+                            __FUNCTION__, prop->pipeID[0]);
+                }
+                else if (prop->pipeCount == 2) {
+                    setPipeId(prop, vLayer->sDestPipes.pipe[0],
+                                                    vLayer->sDestPipes.pipe[1]);
+                    ALOGD_IF(isDebug(), "%s: VPU: Reserved lpipe:%d, rpipe:%d",
+                            __FUNCTION__, prop->pipeID[0], prop->pipeID[1]);
+                }
+                else {
+                    ALOGE("%s: Invalid pipeCount for resevation", __FUNCTION__);
+                }
+            }
+            else {
+                ALOGD_IF(isDebug(), "%s: 1st vid frame for VPU", __FUNCTION__);
+                prop->firstBuffer = true;
+            }
+
+            // marking the layer pipes for vpu.
+            prop->vpuLayer = true;
+            prop->layer = layer;
+            layer->flags |= HWC_VPU_PIPE;
+
+            // getting image width and height
+            prop->width = layer->displayFrame.right - layer->displayFrame.left;
+            prop->height = layer->displayFrame.bottom - layer->displayFrame.top;
+
+            //setting source crop = dest crop (only for layers drawn by vpu,
+            // since we know it will be scaled up/down by vpu)
+            layer->sourceCropf.left = 0.0;
+            layer->sourceCropf.top = 0.0;
+            layer->sourceCropf.right = (float) prop->width;
+            layer->sourceCropf.bottom = (float) prop->height;
+
+            // setting the flag so that mdpComp wont recognize it as the MDPCOMP
+            layerProp[i].mFlags |= HWC_VPUCOMP;
+
+            // TODO: need to get the proper solution for color fill
+
+            // storing locally the vpu supported format from VFM
+            prop->format = vLayer->vpuOutPixFmt;
+            ALOGD_IF(isDebug(), "%s: MDP: sourceCropf: w:%d h:%d format:%d",
+                    __FUNCTION__, prop->width, prop->height, prop->format);
+        }
+    }
+    return 0;
+}
+
+bool VPUClient::allocResLayerPipes(hwc_context_t* ctx, int dpy,
+                                         hwc_display_contents_1_t* list)
+{
+    overlay::Overlay& ov = *ctx->mOverlay;
+    for (unsigned int i=0; i<(list->numHwLayers); ++i) {
+        int pipeid = -1;
+        VpuLayerProp* prop = &mProp[dpy][i];
+
+        // checking if there is already a reserved pipe for this layer
+        // then use the same allocated pipe for this layer
+        getPipeId(prop, pipeid);
+
+        if (pipeid != -1) {
+            // there is a reserved pipe for this layer.
+            ovutils::eDest dest = ov.reservePipe(pipeid);
+            if (dest == ovutils::OV_INVALID) {
+                ALOGE("%s: Unable to get reserved pipe: layer#%d",
+                        __FUNCTION__, i);
+                return false;
+            }
+
+            // setting dest locally
+            setDest(prop, dest);
+            ALOGD_IF(isDebug(), "%s: Reserving pipe:%d, dest:%d ", __FUNCTION__,
+                    pipeid, dest);
+        }
+        else {
+            ALOGD_IF(isDebug2(), "%s: No reserved pipe for layer:%d",
+                    __FUNCTION__, i);
+        }
+    }
+    return true;
+}
+
+bool VPUClient::allocLayerPipes(hwc_context_t* ctx, int dpy,
+                                         hwc_display_contents_1_t* list)
+{
+    // checking if the pipes are reserved for any layer,
+    // if yes, then updating the index of the pipes
+    if (!allocResLayerPipes(ctx, dpy, list)) {
+        ALOGE("%s: Reserved pipe alloc failed", __FUNCTION__);
+        return false;
+    }
+
+    for (unsigned int i=0; i<(list->numHwLayers); ++i) {
+        hwc_layer_1_t* layer = &list->hwLayers[i];
+        private_handle_t *hnd = (private_handle_t *)layer->handle;
+        VpuLayerProp* prop = &mProp[dpy][i];
+        int pipe = -1;
+        overlay::Overlay& ov = *ctx->mOverlay;
+
+        // only care about the layers supported by VPU
+        if (!prop->vpuLayer)
+            continue;
+
+        // continue if this layer has reserved pipe
+        getPipeId(prop, pipe);
+        if (pipe != -1)
+            continue;
+
+        ovutils::eDest dest = ov.nextPipe(ovutils::OV_MDP_PIPE_VG, dpy,
+                overlay::Overlay::MIXER_DEFAULT);
+        if (dest == ovutils::OV_INVALID) {
+            ALOGE("%s: Unable to allocate pipe for layer#%d", __FUNCTION__, i);
+            return false;
+        }
+
+        // setting dest locally
+        setDest(prop, dest);
+        ALOGD_IF(isDebug(), "%s: Newly allocated pipe_dest:%d", __FUNCTION__,
+                dest);
+    }
+    return true;
+}
+
+bool VPUClient::allocResLayerPipesSplit(hwc_context_t* ctx, int dpy,
+                                         hwc_display_contents_1_t* list)
+{
+    overlay::Overlay& ov = *ctx->mOverlay;
+    for (unsigned int i=0; i<(list->numHwLayers); ++i) {
+        int lpipeid = -1;
+        int rpipeid = -1;
+        VpuLayerProp* prop = &mProp[dpy][i];
+
+        // checking if there is already a reserved pipe for this layer
+        // then use the same allocated pipe for this layer
+        getPipeId(prop, lpipeid, rpipeid);
+
+        if (lpipeid != -1 && rpipeid != -1) {
+            ovutils::eDest ldest = ov.reservePipe(lpipeid);
+            if (ldest == ovutils::OV_INVALID) {
+                ALOGD_IF(isDebug(), "%s: Unable to get reserved pipe-lsplit: "
+                         "layer#%d", __FUNCTION__, i);
+                return false;
+            }
+
+            ovutils::eDest rdest = ov.reservePipe(rpipeid);
+            if (rdest == ovutils::OV_INVALID) {
+                ALOGD_IF(isDebug(), "%s: Unable to get reserved pipe-rsplit: "
+                         "layer#%d", __FUNCTION__, i);
+                return false;
+            }
+
+            setDest(prop, ldest, rdest);
+            ALOGD_IF(isDebug(), "%s: Reserve lpipe:%d, ldest:%d, rpipe:%d, "
+                    "rdest:%d", __FUNCTION__, lpipeid, ldest, rpipeid, rdest);
+        }
+        else if (lpipeid != -1 || rpipeid != -1) {
+            ALOGE("%s: Bug: only one pipe reserved!", __FUNCTION__);
+            return false;
+        }
+    }
+    return true;
+}
+
+bool VPUClient::allocLayerPipesSplit(hwc_context_t* ctx, int dpy,
+                                         hwc_display_contents_1_t* list)
+{
+    // checking if the pipes are reserved for any layer,
+    // if yes, then updating the index of the pipes
+    if (!allocResLayerPipesSplit(ctx, dpy, list)) {
+        ALOGE("%s: Reserved pipe alloc failed", __FUNCTION__);
+        return false;
+    }
+
+    for (unsigned int i=0; i<(list->numHwLayers); ++i) {
+        hwc_layer_1_t* layer = &list->hwLayers[i];
+        private_handle_t *hnd = (private_handle_t *)layer->handle;
+        VpuLayerProp* prop = &mProp[dpy][i];
+        int lpipe, rpipe;
+        overlay::Overlay& ov = *ctx->mOverlay;
+
+        // only care about the layers supported by VPU
+        if (!prop->vpuLayer)
+            continue;
+
+        // only care about the layers supported by VPU
+        getPipeId(prop, lpipe, rpipe);
+        if (lpipe != -1 && rpipe != -1)
+            continue;
+
+        ovutils::eDest ldest = ov.nextPipe(ovutils::OV_MDP_PIPE_VG, dpy,
+                overlay::Overlay::MIXER_LEFT);
+        if (ldest == ovutils::OV_INVALID) {
+            ALOGE("%s: Unable to allocate pipe for layer#%d", __FUNCTION__, i);
+            return false;
+        }
+
+        ovutils::eDest rdest = ov.nextPipe(ovutils::OV_MDP_PIPE_VG, dpy,
+                overlay::Overlay::MIXER_RIGHT);
+        if (rdest == ovutils::OV_INVALID) {
+            ALOGE("%s: Unable to allocate pipe for layer#%d", __FUNCTION__, i);
+            return false;
+        }
+
+        // setting dests locally
+        setDest(prop, ldest, rdest);
+        ALOGD_IF(isDebug(), "%s: Newly allocated ldest:%d rdest:%d",
+                __FUNCTION__, ldest, rdest);
+    }
+    return true;
+}
+
+bool VPUClient::configureLayers(hwc_context_t* ctx, int dpy,
+                                         hwc_display_contents_1_t* list)
+{
+    for (unsigned int i=0; i<(list->numHwLayers); ++i) {
+        VpuLayerProp* prop = &mProp[dpy][i];
+        hwc_layer_1_t* layer = &list->hwLayers[i];
+
+        if (!prop->vpuLayer)
+            continue;
+
+        eMdpFlags mdpFlags = OV_MDP_BACKEND_COMPOSITION;
+        eZorder zOrder = static_cast<eZorder>(i);
+        eIsFg isFg = IS_FG_OFF;
+        setPipeCount(prop, 1);
+        eDest dest = (eDest) getDest(prop, 0);
+
+        ALOGD_IF(isDebug(),"%s: configuring: layer:%p z_order:%d dest_pipe:%d",
+                __FUNCTION__, layer, zOrder, dest);
+
+        if (configureNonSplit(ctx, layer, dpy, mdpFlags, zOrder, isFg,
+                            dest, NULL)) {
+            ALOGE("%s: Failed to configure overlay for layer %d",
+                    __FUNCTION__, i);
+            return false;
+        }
+        ALOGD_IF(isDebug2(), "%s: layer:%d configured!", __FUNCTION__, i);
+
+        // Pipe is successfully allocated for this layer; retrieving it from
+        // overlay
+        int pipeId = ctx->mOverlay->getPipeId((eDest) getDest(prop, 0));
+        setPipeId(prop, pipeId);
+
+        ALOGD_IF(isDebug(), "%s: allocated pipe:%d layer:%d", __FUNCTION__,
+                    pipeId, i);
+    }
+    return true;
+}
+
+bool VPUClient::configureLayersSplit(hwc_context_t* ctx, int dpy,
+                                         hwc_display_contents_1_t* list)
+{
+    for (unsigned int i=0; i<(list->numHwLayers); ++i) {
+        VpuLayerProp* prop = &mProp[dpy][i];
+        hwc_layer_1_t* layer = &list->hwLayers[i];
+
+        if (!prop->vpuLayer)
+            continue;
+
+        eMdpFlags mdpFlags = OV_MDP_BACKEND_COMPOSITION;
+        eZorder zOrder = static_cast<eZorder>(i);
+        eIsFg isFg = IS_FG_OFF;
+        setPipeCount(prop, 2);
+        eDest ldest = (eDest) getDest(prop, 0);
+        eDest rdest = (eDest) getDest(prop, 1);
+
+        ALOGD_IF(isDebug(),"%s: configuring: layer:%p z_order:%d dest_pipeL:%d"
+                "dest_pipeR:%d",__FUNCTION__, layer, zOrder, ldest, rdest);
+
+        if (configureSplit(ctx, layer, dpy, mdpFlags, zOrder, isFg, ldest,
+                            rdest, NULL)) {
+            ALOGE("%s: Failed to configure overlay for layer %d",
+                    __FUNCTION__, i);
+            return false;
+        }
+        ALOGD_IF(isDebug2(), "%s: layer:%d configured!", __FUNCTION__, i);
+
+        // Pipe is successfully allocated for this layer; retrieving it from
+        // overlay
+        int lpipeId = ctx->mOverlay->getPipeId((eDest) getDest(prop, 0));
+        int rpipeId = ctx->mOverlay->getPipeId((eDest) getDest(prop, 1));
+        setPipeId(prop, lpipeId, rpipeId);
+
+        ALOGD_IF(isDebug(), "%s: allocated l-pipe:%d - r-pipe:%d for layer:%d",
+                __FUNCTION__, lpipeId, rpipeId, i);
+    }
+    return true;
+}
+
+void VPUClient::setMDPCompLayerFlags(hwc_context_t *ctx, int dpy,
+                                   hwc_display_contents_1_t* list)
+{
+    LayerProp *layerProp = ctx->layerProp[dpy];
+
+    // disableGpu only disables gpu for video layer. The expected behavior is to
+    // show a blank screen in case VPU doesnt support a video layer, and gpu
+    // fallback is disabled by the user.
+    bool disableGpu = false;
+    char property[PROPERTY_VALUE_MAX];
+    if ((property_get("persist.hwc.noGpuFallback", property, NULL) > 0) &&
+        (!strncmp(property, "1", PROPERTY_VALUE_MAX ) ||
+            (!strncasecmp(property,"true", PROPERTY_VALUE_MAX )))) {
+        ALOGD_IF(isDebug(), "%s: GPU fallback is disabled through prop",
+                __FUNCTION__);
+        disableGpu = true;
+    }
+
+    // no layers are supported by vpu
+    if (mGpuFallback && !disableGpu) {
+        ALOGD_IF(isDebug(), "%s: No VPU supported layers - Falling back to GPU",
+                __FUNCTION__);
+        return;
+    }
+
+    for (unsigned int i=0; i<(list->numHwLayers); ++i) {
+        hwc_layer_1_t* layer = &(list->hwLayers[i]);
+        VpuLayerProp* prop = &mProp[dpy][i];
+        private_handle_t *hnd = (private_handle_t *)layer->handle;
+
+        // mark vpu layers as HWC_OVERLAY, and those video layers that
+        // are not supported by vpu and gpu fallback is disabled by the
+        // user.
+        if (prop->vpuLayer || (isYuvBuffer(hnd) && disableGpu)) {
+            layer->compositionType = HWC_OVERLAY;
+            layer->hints |= HWC_HINT_CLEAR_FB;
+            ALOGD_IF(isDebug(), "%s: Marking layer:%d as overlay",
+                    __FUNCTION__, i);
+        }
+    }
+}
+
+int VPUClient::prepare(hwc_context_t *ctx, int display,
+            hwc_display_contents_1_t* list)
+{
+    if (!mVPU) {
+        return -1;
+    }
+
+    const int numLayers = ctx->listStats[display].numAppLayers;
+    //number of app layers exceeds MAX_NUM_APP_LAYERS fall back to GPU
+    //do not cache the information for next draw cycle.
+    if (numLayers > MAX_NUM_APP_LAYERS) {
+        ALOGE("%s: Number of App layers exceeded the limit ",__FUNCTION__);
+        return -1;
+    }
+
+    if (setupVpuSession(ctx, display, list)) {
+        ALOGD_IF(isDebug(), "%s: Vpu session setup failed! ",__FUNCTION__);
+        return -1;
+    }
+
+    LayerProp *layerProp = ctx->layerProp[display];
+    bool isSplit = isDisplaySplit(ctx, display);
+    ALOGD_IF(isDebug2(), "%s: Split Pipe:%d ", __FUNCTION__,
+            isSplit ? 1 : 0);
+
+    // setting up the layer
+    LayerList *vpuList = vList[display];
+    vpuList->numLayers = list->numHwLayers;
+
+    // Prepare FB Update at z-0
+    if (numLayers > mNumVpuLayers) {
+        if (!ctx->mFBUpdate[display]->prepare(ctx, list, mNumVpuLayers)) {
+            ALOGD_IF(isDebug(), "%s configure framebuffer failed",
+                    __FUNCTION__);
+            return -1;
+        }
+    }
+
+    // Allocate pipe for layers
+    if (!isSplit ? !allocLayerPipes(ctx, display, list) :
+                 !allocLayerPipesSplit(ctx, display, list)) {
+        ALOGD_IF(isDebug(), "%s: Unable to allocate MDP pipes", __FUNCTION__);
+        return -1;
+    }
+
+    // Configure layers
+    if (!isSplit ? !configureLayers(ctx, display, list) :
+                 !configureLayersSplit(ctx, display, list)) {
+        ALOGD_IF(isDebug(), "%s: Unable to configure MDP pipes", __FUNCTION__);
+        return -1;
+    }
+
+    // Set layer flags for MDP/VPU composition
+    setMDPCompLayerFlags(ctx, display, list);
+
+    for (unsigned int i=0; i<(list->numHwLayers); ++i) {
+        VpuLayerProp* prop = &mProp[display][i];
+
+        if (!prop->vpuLayer)
+            continue;
+
+        hwc_layer_1_t *layer = &list->hwLayers[i];
+        Layer *vLayer = &vpuList->layers[i];
+
+        // re-storing the sourceCropf, as it was changed in setVpuSession for
+        // overlay set
+        layer->sourceCropf = prop->sourceCropf;
+
+        // updating the pipe info inside vfm list
+        if ( prop->pipeCount > 0  && prop->pipeCount <= MAX_PIPES_PER_LAYER ) {
+            vLayer->sDestPipes.numPipes = prop->pipeCount;
+
+            for (int j=0; j < prop->pipeCount; ++j) {
+                // Setting pipe for VPU
+                vLayer->sDestPipes.pipe[j] = prop->pipeID[j];
+            }
+        }
+    }
+
+    if (mVPU->prepare((DISPLAY_ID)display, vpuList) != NO_ERROR) {
+        //error in vpu prepare
+        ALOGE("%s: ERROR in VPU::prepare", __func__);
+        return -1;
+    }
+    return 0;
+}
+
+bool VPUClient::queueHandle(hwc_context_t* ctx, VpuLayerProp* prop,
+        private_handle_t* hnd)
+{
+    overlay::Overlay& ov = *ctx->mOverlay;
+    ovutils::eDest dest = (eDest) getDest(prop, 0);
+
+    int fd = hnd->fd;
+    uint32_t offset = hnd->offset;
+
+    if (dest != ovutils::OV_INVALID) {
+        if (!ov.queueBuffer(fd, offset, dest)) {
+            ALOGE("%s: queueBuffer failed", __FUNCTION__);
+            return false;
+        }
+        else {
+            ALOGD_IF(isDebug(), "%s: Queue handle successful: hnd:0x%x "
+                    "dest:%d", __FUNCTION__, (unsigned int) hnd, dest);
+        }
+    }
+    else {
+        ALOGE("%s: Invalid Dest: dest:%d", __FUNCTION__, dest);
+        return false;
+    }
+    return true;
+}
+
+bool VPUClient::queueHandleSplit(hwc_context_t* ctx, VpuLayerProp* prop,
+        private_handle_t* hnd)
+{
+    overlay::Overlay& ov = *ctx->mOverlay;
+    ovutils::eDest ldest = (eDest) getDest(prop, 0);
+    ovutils::eDest rdest = (eDest) getDest(prop, 1);
+
+    int fd = hnd->fd;
+    uint32_t offset = hnd->offset;
+
+    // play left mixer
+    if (ldest != ovutils::OV_INVALID) {
+        ALOGD_IF(isDebug(), "%s: Queuing left mixer", __FUNCTION__);
+        if (!ov.queueBuffer(fd, offset, ldest)) {
+            ALOGE("%s: queueBuffer failed for left mixer ", __FUNCTION__);
+            return false;
+        }
+        else {
+            ALOGD_IF(isDebug(), "%s: Queue left-handle successful: hnd:0x%x "
+                    "ldest:%d", __FUNCTION__, (unsigned int) hnd, ldest);
+        }
+    }
+    else {
+        ALOGE("%s: Invalid l-Split Dest", __FUNCTION__);
+        return false;
+    }
+
+    // play right mixer
+    if (rdest != ovutils::OV_INVALID) {
+        ALOGD_IF(isDebug(), "%s: Queuing right mixer", __FUNCTION__);
+        if (!ov.queueBuffer(fd, offset, rdest)) {
+            ALOGE("%s: queueBuffer failed for right mixer ", __FUNCTION__);
+            return false;
+        }
+        else {
+            ALOGD_IF(isDebug(), "%s: Queue right-handle successful: hnd:0x%x "
+                    "rdest:%d", __FUNCTION__, (unsigned int) hnd, rdest);
+        }
+    }
+    else {
+        ALOGE("%s: Invalid r-Split Dest", __FUNCTION__);
+        return false;
+    }
+    return true;
+}
+
+bool VPUClient::drawDummyLayers(hwc_context_t* ctx, int dpy,
+                    hwc_display_contents_1_t* list)
 {
     int err = 0;
-    if(!mVPU)
-        return err;
-    // Queue buffers to VPU
-    return err;
+    for (unsigned int i=0; i<(list->numHwLayers); ++i) {
+        VpuLayerProp* prop = &mProp[dpy][i];
+
+        if (!prop->vpuLayer)
+            continue;
+
+        // displaying blank screen for the first frame
+        if (prop->firstBuffer) {
+            ALOGD_IF(isDebug(), "%s: Displaying first (blank) frame",
+                    __FUNCTION__);
+            prop->firstBuffer = false;
+
+            if (mHnd[dpy][i] != NULL)
+                free_buffer(mHnd[dpy][i]);
+
+            // TO-FIX: out dummy buffer is currently allocated based on
+            // RGB888 format
+            err = alloc_buffer(&mHnd[dpy][i], prop->width, prop->height,
+                HAL_PIXEL_FORMAT_RGB_888, GRALLOC_USAGE_PRIVATE_IOMMU_HEAP);
+            if (err == -1) {
+                ALOGE("%s: Dummy buffer allocation failed!", __FUNCTION__);
+                return false;
+            }
+
+            private_handle_t* hnd = mHnd[dpy][i];
+            if (prop->format == HAL_PIXEL_FORMAT_RGB_888) {
+                ALOGD_IF(isDebug(), "%s: Format: RGB888", __FUNCTION__);
+                memset((void*)hnd->base, 0x0, hnd->size);
+            }
+            else if (prop->format ==
+                    HAL_PIXEL_FORMAT_YCbCr_422_I_10BIT_COMPRESSED) {
+                ALOGD_IF(isDebug(), "%s: Format: 10BIT_BWC", __FUNCTION__);
+                memset((void*)hnd->base, 0xaa, hnd->size);
+            }
+            else {
+                ALOGE("%s: Error! Wrong VPU out format - layer:%d",
+                        __FUNCTION__, i);
+                return false;
+            }
+
+            bool isSplit = isDisplaySplit(ctx, dpy);
+            if (!isSplit ? !queueHandle(ctx, prop, hnd) :
+                        !queueHandleSplit(ctx, prop, hnd)) {
+                ALOGD_IF(isDebug(), "%s: Error in queue handle: layer:%d",
+                        __FUNCTION__, i);
+                return false;
+            }
+            else {
+                ALOGD_IF(isDebug(), "%s: queue handle successful: hnd:0x%x "
+                        "layer:%d", __FUNCTION__, (unsigned int) hnd, i);
+            }
+        }
+    }
+    return true;
+}
+
+int VPUClient::predraw(hwc_context_t *ctx, int display,
+                                        hwc_display_contents_1_t* list)
+{
+    if (!mVPU) {
+        return -1;
+    }
+
+    if (!ctx || !list) {
+        ALOGE("%s: invalid contxt or list",__FUNCTION__);
+        return -1;
+    }
+
+    if (ctx->listStats[display].numAppLayers > MAX_NUM_APP_LAYERS) {
+        ALOGE("%s: Exceeding max layer count", __FUNCTION__);
+        return -1;
+    }
+
+    // Although all the video layers are composed through VPU, but still need to
+    // queue the first buffer (blank screen) to mdp in order to initialize the
+    // settings
+    if (!drawDummyLayers(ctx, display, list)) {
+        ALOGE("%s: Failed to draw the first layer through overlay",
+                __FUNCTION__);
+        return -1;
+    }
+    return 0;
+}
+
+int VPUClient::draw(hwc_context_t *ctx, int display,
+                                        hwc_display_contents_1_t* list)
+{
+    if (!mVPU) {
+        return -1;
+    }
+
+    LayerList *vpuList = vList[display];
+    vpuList->numLayers = list->numHwLayers;
+
+    for (unsigned int i=0; i<(list->numHwLayers); ++i) {
+        hwc_layer_1_t *layer = &list->hwLayers[i];
+        Layer *vLayer = &vpuList->layers[i];
+
+        // setting layer info again for the update content.
+        setLayer(layer, vLayer);
+    }
+
+    // queuing the buffer to VPU
+    if (mVPU->draw((DISPLAY_ID)display, vpuList) != NO_ERROR) {
+        //error in vpu draw
+        ALOGE("%s: ERROR in VPU::draw", __func__);
+        return -1;
+    }
+
+    ALOGD_IF(isDebug2(), "%s: Done VFM draw", __FUNCTION__);
+
+    LayerProp *layerProp = ctx->layerProp[display];
+    // setting releaseFenceFd for the vpu layer
+    for (unsigned int i=0; i<(vpuList->numLayers); ++i) {
+
+        VpuLayerProp* prop = &mProp[display][i];
+        if (!prop->vpuLayer)
+            continue;
+
+        hwc_layer_1_t *layer = &list->hwLayers[i];
+        Layer *vLayer = &vpuList->layers[i];
+
+        // TODO: Fix properly once the releaseFenceFd is implemented
+        layer->releaseFenceFd = vLayer->releaseFenceFd;
+        ALOGD_IF(isDebug(), "%s: releaseFd:%d for layer:%d", __FUNCTION__,
+                layer->releaseFenceFd, i);
+    }
+    return 0;
+}
+
+int VPUClient::getLayerIdx(int dpy, hwc_layer_1_t *layer)
+{
+    for (int i=0; i < MAX_NUM_APP_LAYERS; ++i) {
+        VpuLayerProp* prop = &mProp[dpy][i];
+
+        if (!prop->vpuLayer)
+            continue;
+
+        if (prop->layer == layer) {
+            ALOGD_IF(isDebug2(), "%s: OUT - dpy:%d", __FUNCTION__, dpy);
+            return i;
+        }
+    }
+    return -1;
+}
+
+int VPUClient::getLayerFormat(int dpy, hwc_layer_1_t *layer)
+{
+    if (!mVPU) {
+        return -1;
+    }
+
+    int idx = -1;
+    if ((idx = getLayerIdx(dpy, layer)) == -1) {
+        ALOGE("%s: Layer not found!", __FUNCTION__);
+        return -1;
+    }
+
+    VpuLayerProp* prop = &mProp[dpy][idx];
+    ALOGD_IF(isDebug(), "%s: layer:%d format:0x%x", __FUNCTION__, idx,
+            (unsigned int) prop->format);
+
+    return prop->format;
+}
+
+int VPUClient::getWidth(int dpy, hwc_layer_1_t *layer)
+{
+    if (!mVPU) {
+        return -1;
+    }
+
+    int idx = -1;
+    if ((idx = getLayerIdx(dpy, layer)) == -1) {
+        ALOGE("%s: Layer not found!", __FUNCTION__);
+        return -1;
+    }
+
+    VpuLayerProp* prop = &mProp[dpy][idx];
+    ALOGD_IF(isDebug(), "%s: layer:%d width:%d", __FUNCTION__, idx,
+            prop->width);
+
+    return prop->width;
+}
+
+int VPUClient::getHeight(int dpy, hwc_layer_1_t *layer)
+{
+    if (!mVPU) {
+        return -1;
+    }
+
+    int idx = -1;
+    if ((idx = getLayerIdx(dpy, layer)) == -1) {
+        ALOGE("%s: Layer not found!", __FUNCTION__);
+        return -1;
+    }
+
+    VpuLayerProp* prop = &mProp[dpy][idx];
+    ALOGD_IF(isDebug(), "%s: layer:%d height:%d", __FUNCTION__, idx,
+            prop->height);
+
+    return prop->height;
+}
+
+// TODO: getter function has side-effect. Need to cleanup
+void VPUClient::getPipeId(VpuLayerProp* prop, int &pipe)
+{
+    pipe = (prop->pipeCount == 1) ? (prop->pipeID[0]) : -1;
+}
+
+void VPUClient::getPipeId(VpuLayerProp* prop, int &lPipe, int &rPipe)
+{
+    lPipe = (prop->pipeCount == 2) ? (prop->pipeID[0]) : -1;
+    rPipe = (prop->pipeCount == 2) ? (prop->pipeID[1]) : -1;
+}
+
+int VPUClient::getDest(VpuLayerProp* prop, int pipenum)
+{
+    return (prop->pipeCount > 0) ? (prop->dest[pipenum]) : -1;
+}
+
+void VPUClient::setPipeCount(VpuLayerProp* prop, int count)
+{
+    prop->pipeCount = count;
+}
+
+void VPUClient::setPipeId(VpuLayerProp* prop, int lPipeId, int rPipeId)
+{
+    prop->pipeCount = 2;
+    prop->pipeID[0] = lPipeId;
+    prop->pipeID[1] = rPipeId;
+}
+
+void VPUClient::setPipeId(VpuLayerProp* prop, int pipeId)
+{
+    prop->pipeCount = 1;
+    prop->pipeID[0] = pipeId;
+}
+
+void VPUClient::setDest(VpuLayerProp* prop, int lDest, int rDest)
+{
+    prop->dest[0] = lDest;
+    prop->dest[1] = rDest;
+}
+
+void VPUClient::setDest(VpuLayerProp* prop, int dest)
+{
+    prop->dest[0] = dest;
+}
+
+bool VPUClient::supportedVPULayer(VpuLayerProp* prop)
+{
+    if (!prop->vpuLayer)
+        return false;
+
+    return true;
+}
+
+bool VPUClient::supportedVPULayer(int dpy, hwc_layer_1_t *layer)
+{
+    if (!mVPU) {
+        return false;
+    }
+
+    int idx = -1;
+    if ((idx = getLayerIdx(dpy, layer)) == -1) {
+        ALOGD_IF(isDebug(), "%s: Layer not found!", __FUNCTION__);
+        return false;
+    }
+    return true;
 }
 
 int VPUClient::processCommand(uint32_t command,
-        const Parcel* inParcel, Parcel* outParcel)
+                              const Parcel* inParcel, Parcel* outParcel)
 {
-    if(!mVPU)
+    if (!mVPU)
         return 0;
-    //XXX: Enable when VPU enables it
-    //return mVPU->processCommand(command, inParcel, outParcel);
-    return 0;
+
+    return mVPU->processCommand(command, inParcel, outParcel);
 }
 
 }; // namespace qhwc
diff --git a/libhwcomposer/hwc_vpuclient.h b/libhwcomposer/hwc_vpuclient.h
index 9985517..bb2a4b6 100644
--- a/libhwcomposer/hwc_vpuclient.h
+++ b/libhwcomposer/hwc_vpuclient.h
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2013 The Linux Foundation. All rights reserved.
+* 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
@@ -31,13 +31,20 @@
 #define HWC_VPU_H
 
 #include <sys/types.h>
+#include "hwc_utils.h"
+
+#define MAX_PIPES_PER_LAYER 2
 
 //Forward declarations
 struct hwc_display_contents_1;
 typedef struct hwc_display_contents_1 hwc_display_contents_1_t;
+struct hwc_layer_1;
+typedef struct hwc_layer_1 hwc_layer_1_t;
 struct hwc_context_t;
+
 namespace vpu {
 class VPU;
+struct LayerList;
 };
 namespace android {
 class Parcel;
@@ -47,21 +54,91 @@
 
 class VPUClient {
 public:
-    VPUClient();
+    VPUClient(hwc_context_t *ctx);
 
     ~VPUClient();
 
-    int prepare(hwc_context_t *ctx, hwc_display_contents_1_t* list);
-
-    int draw(hwc_context_t *ctx, hwc_display_contents_1_t* list);
-
+    int setupVpuSession(hwc_context_t *ctx, int display,
+                            hwc_display_contents_1_t* list);
+    int prepare(hwc_context_t *ctx, int display,
+                            hwc_display_contents_1_t* list);
+    int predraw(hwc_context_t *ctx, int display,
+                            hwc_display_contents_1_t* list);
+    int draw(hwc_context_t *ctx, int display,
+                            hwc_display_contents_1_t* list);
     int processCommand(uint32_t command,
-            const android::Parcel* inParcel, android::Parcel* outParcel);
+        const android::Parcel* inParcel, android::Parcel* outParcel);
+    int getLayerFormat(int dpy, hwc_layer_1_t *layer);
+    int getWidth(int dpy, hwc_layer_1_t *layer);
+    int getHeight(int dpy, hwc_layer_1_t *layer);
+    bool supportedVPULayer(int dpy, hwc_layer_1_t *layer);
 
 private:
     vpu::VPU *mVPU;
     void* mVPULib;
 
+    /* VpuLayerProp struct:
+     *  This struct corresponds to only one layer
+     *  pipeCount: number of pipes required for a layer
+     *  pipeID[]: pipe ids corresponding to the layer
+     */
+    struct VpuLayerProp {
+        int format;
+        int width;
+        int height;
+        int pipeCount;
+        bool vpuLayer;
+        bool firstBuffer;
+        hwc_frect_t sourceCropf;
+        hwc_layer_1_t *layer;
+        int pipeID[MAX_PIPES_PER_LAYER];
+        int dest[MAX_PIPES_PER_LAYER];
+    };
+    int mNumVpuLayers;  /* total num of vpu supported layers */
+    int mGpuFallback;   /* all layers are not supported by vpu */
+
+    VpuLayerProp mProp[HWC_NUM_DISPLAY_TYPES][MAX_NUM_APP_LAYERS];
+    int mDebugLogs;
+    private_handle_t *mHnd[HWC_NUM_DISPLAY_TYPES][MAX_NUM_APP_LAYERS];
+    vpu::LayerList *vList[HWC_NUM_DISPLAY_TYPES];
+
+    /* Private debug functions */
+    int32_t isDebug() { return (mDebugLogs >= 1); }
+    int32_t isDebug2() { return (mDebugLogs >= 2); }
+
+    /* Private Get/Set functions */
+    int getLayerIdx(int dpy, hwc_layer_1_t *layer);
+    void getPipeId(VpuLayerProp* prop, int &pipe);
+    void getPipeId(VpuLayerProp* prop, int &lPipe, int &rPipe);
+    int getDest(VpuLayerProp* prop, int pipenum);
+    void setPipeCount(VpuLayerProp* prop, int count);
+    void setPipeId(VpuLayerProp* prop, int lPipeId, int rPipeId);
+    void setPipeId(VpuLayerProp* prop, int pipeId);
+    void setDest(VpuLayerProp* prop, int lDest, int rDest);
+    void setDest(VpuLayerProp* prop, int dest);
+
+    /* Private implementations */
+    bool supportedVPULayer(VpuLayerProp* prop);
+    bool allocResLayerPipes(hwc_context_t* ctx, int dpy,
+                            hwc_display_contents_1_t* list);
+    bool allocLayerPipes(hwc_context_t* ctx, int dpy,
+                            hwc_display_contents_1_t* list);
+    bool allocResLayerPipesSplit(hwc_context_t* ctx, int dpy,
+                            hwc_display_contents_1_t* list);
+    bool allocLayerPipesSplit(hwc_context_t* ctx, int dpy,
+                            hwc_display_contents_1_t* list);
+    bool configureLayers(hwc_context_t* ctx, int dpy,
+                            hwc_display_contents_1_t* list);
+    bool configureLayersSplit(hwc_context_t* ctx, int dpy,
+                            hwc_display_contents_1_t* list);
+    void setMDPCompLayerFlags(hwc_context_t *ctx, int dpy,
+                            hwc_display_contents_1_t* list);
+    bool drawDummyLayers(hwc_context_t* ctx, int dpy,
+                            hwc_display_contents_1_t* list);
+    bool queueHandle(hwc_context_t* ctx, VpuLayerProp* prop,
+                            private_handle_t* hnd);
+    bool queueHandleSplit(hwc_context_t* ctx, VpuLayerProp* prop,
+                            private_handle_t* hnd);
 }; // class VPU
 }; // namespace qhwc
 #endif /* end of include guard: HWC_VPU_H */
diff --git a/liblight/lights.c b/liblight/lights.c
index ccfbe10..229777a 100644
--- a/liblight/lights.c
+++ b/liblight/lights.c
@@ -1,5 +1,6 @@
 /*
  * 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.
@@ -115,6 +116,9 @@
 {
     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);
@@ -125,12 +129,15 @@
 set_speaker_light_locked(struct light_device_t* dev,
         struct light_state_t const* state)
 {
-    int len;
-    int alpha, red, green, blue;
+    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;
@@ -217,6 +224,9 @@
         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);
diff --git a/libmemtrack/memtrack_msm.c b/libmemtrack/memtrack_msm.c
index 6626b89..8adff96 100644
--- a/libmemtrack/memtrack_msm.c
+++ b/libmemtrack/memtrack_msm.c
@@ -22,15 +22,19 @@
 
 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,
-                                enum memtrack_type type,
+                                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);
     }
diff --git a/liboverlay/overlayCtrlData.h b/liboverlay/overlayCtrlData.h
index 1b26b66..dbf328a 100644
--- a/liboverlay/overlayCtrlData.h
+++ b/liboverlay/overlayCtrlData.h
@@ -49,13 +49,9 @@
 public:
 
     /* ctor */
-    explicit Ctrl();
+    explicit Ctrl(const int& dpy);
     /* dtor close */
     ~Ctrl();
-    /* init fd etc*/
-    bool init(uint32_t dpy);
-    /* close underlying mdp */
-    bool close();
 
     /* set source using whf, orient and wait flag */
     void setSource(const utils::PipeArgs& args);
@@ -90,20 +86,16 @@
 
 private:
     // mdp ctrl struct(info e.g.)
-    MdpCtrl mMdp;
+    MdpCtrl *mMdp;
 };
 
 
 class Data : utils::NoCopy {
 public:
     /* init, reset */
-    explicit Data();
+    explicit Data(const int& dpy);
     /* calls close */
     ~Data();
-    /* init fd etc */
-    bool init(uint32_t dpy);
-    /* calls underlying mdp close */
-    bool close();
     /* set overlay pipe id in the mdp struct */
     void setPipeId(int id);
     /* get overlay id in the mdp struct */
@@ -117,72 +109,46 @@
 
 private:
     // mdp data struct
-    MdpData mMdp;
-};
-
-/* This class just creates a Ctrl Data pair to be used by a pipe.
- * Although this was legacy design, this separation still makes sense, since we
- * need to use the Ctrl channel in hwc_prepare (i.e config stage) and Data
- * channel in hwc_set (i.e draw stage)
- */
-struct CtrlData {
-    Ctrl ctrl;
-    Data data;
+    MdpData *mMdp;
 };
 
 //-------------Inlines-------------------------------
 
-inline Ctrl::Ctrl() {
-    mMdp.reset();
+inline Ctrl::Ctrl(const int& dpy) : mMdp(new MdpCtrl(dpy)) {
 }
 
 inline Ctrl::~Ctrl() {
-    close();
-}
-
-inline bool Ctrl::close() {
-    if(!mMdp.close())
-        return false;
-    return true;
-}
-
-inline bool Ctrl::init(uint32_t dpy) {
-    // MDP/FD init
-    if(!mMdp.init(dpy)) {
-        ALOGE("Ctrl failed to init dpy=%d", dpy);
-        return false;
-    }
-    return true;
+    delete mMdp;
 }
 
 inline void Ctrl::setSource(const utils::PipeArgs& args)
 {
-    mMdp.setSource(args);
+    mMdp->setSource(args);
 }
 
 inline void Ctrl::setPosition(const utils::Dim& dim)
 {
-    mMdp.setPosition(dim);
+    mMdp->setPosition(dim);
 }
 
 inline void Ctrl::setTransform(const utils::eTransform& orient)
 {
-    mMdp.setTransform(orient);
+    mMdp->setTransform(orient);
 }
 
 inline void Ctrl::setCrop(const utils::Dim& d)
 {
-    mMdp.setCrop(d);
+    mMdp->setCrop(d);
 }
 
 inline void Ctrl::setColor(const uint32_t color)
 {
-    mMdp.setColor(color);
+    mMdp->setColor(color);
 }
 
 inline bool Ctrl::setVisualParams(const MetaData_t &metadata)
 {
-    if (!mMdp.setVisualParams(metadata)) {
+    if (!mMdp->setVisualParams(metadata)) {
         ALOGE("Ctrl setVisualParams failed in MDP setVisualParams");
         return false;
     }
@@ -191,12 +157,12 @@
 
 inline void Ctrl::dump() const {
     ALOGE("== Dump Ctrl start ==");
-    mMdp.dump();
+    mMdp->dump();
     ALOGE("== Dump Ctrl end ==");
 }
 
 inline bool Ctrl::commit() {
-    if(!mMdp.set()) {
+    if(!mMdp->set()) {
         ALOGE("Ctrl commit failed set overlay");
         return false;
     }
@@ -204,71 +170,56 @@
 }
 
 inline int Ctrl::getPipeId() const {
-    return mMdp.getPipeId();
+    return mMdp->getPipeId();
 }
 
 inline int Ctrl::getFd() const {
-    return mMdp.getFd();
+    return mMdp->getFd();
 }
 
 inline void Ctrl::updateSrcFormat(const uint32_t& rotDstFmt) {
-    mMdp.updateSrcFormat(rotDstFmt);
+    mMdp->updateSrcFormat(rotDstFmt);
 }
 
 inline utils::Dim Ctrl::getCrop() const {
-    return mMdp.getSrcRectDim();
+    return mMdp->getSrcRectDim();
 }
 
 inline utils::Dim Ctrl::getPosition() const {
-    return mMdp.getDstRectDim();
+    return mMdp->getDstRectDim();
 }
 
 inline void Ctrl::setDownscale(int dscale_factor) {
-    mMdp.setDownscale(dscale_factor);
+    mMdp->setDownscale(dscale_factor);
 }
 
 inline void Ctrl::getDump(char *buf, size_t len) {
-    mMdp.getDump(buf, len);
+    mMdp->getDump(buf, len);
 }
 
-inline Data::Data() {
-    mMdp.reset();
+inline Data::Data(const int& dpy) : mMdp(new MdpData(dpy)) {
 }
 
-inline Data::~Data() { close(); }
-
-inline void Data::setPipeId(int id) { mMdp.setPipeId(id); }
-
-inline int Data::getPipeId() const { return mMdp.getPipeId(); }
-
-inline bool Data::init(uint32_t dpy) {
-    if(!mMdp.init(dpy)) {
-        ALOGE("Data cannot init mdp");
-        return false;
-    }
-    return true;
+inline Data::~Data() {
+    delete mMdp;
 }
 
-inline bool Data::close() {
-    if(!mMdp.close()) {
-        ALOGE("Data close failed");
-        return false;
-    }
-    return true;
-}
+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);
+    return mMdp->play(fd, offset);
 }
 
 inline void Data::dump() const {
     ALOGE("== Dump Data MDP start ==");
-    mMdp.dump();
+    mMdp->dump();
     ALOGE("== Dump Data MDP end ==");
 }
 
 inline void Data::getDump(char *buf, size_t len) {
-    mMdp.getDump(buf, len);
+    mMdp->getDump(buf, len);
 }
 
 } // overlay
diff --git a/liboverlay/overlayMdp.cpp b/liboverlay/overlayMdp.cpp
index 006e05d..3ec0405 100644
--- a/liboverlay/overlayMdp.cpp
+++ b/liboverlay/overlayMdp.cpp
@@ -1,6 +1,6 @@
 /*
 * Copyright (C) 2008 The Android Open Source Project
-* Copyright (c) 2010-2013, The Linux Foundation. All rights reserved.
+* 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.
@@ -45,7 +45,7 @@
 namespace ovutils = overlay::utils;
 namespace overlay {
 
-bool MdpCtrl::init(uint32_t dpy) {
+bool MdpCtrl::init(const int& dpy) {
     int fbnum = Overlay::getFbForDpy(dpy);
     if( fbnum < 0 ) {
         ALOGE("%s: Invalid FB for the display: %d",__FUNCTION__, dpy);
@@ -64,14 +64,11 @@
 
 void MdpCtrl::reset() {
     utils::memset0(mOVInfo);
-    utils::memset0(mLkgo);
     mOVInfo.id = MSMFB_NEW_REQUEST;
-    mLkgo.id = MSMFB_NEW_REQUEST;
     mOrientation = utils::OVERLAY_TRANSFORM_0;
     mDownscale = 0;
     mDpy = 0;
 #ifdef USES_POST_PROCESSING
-    mPPChanged = false;
     memset(&mParams, 0, sizeof(struct compute_params));
     mParams.params.conv_params.order = hsic_order_hsc_i;
     mParams.params.conv_params.interface = interface_rec601;
@@ -210,21 +207,15 @@
 
     doDownscale();
 
-    if(this->ovChanged()) {
-        if(!mdp_wrapper::setOverlay(mFd.getFD(), mOVInfo)) {
-            ALOGE("MdpCtrl failed to setOverlay, restoring last known "
-                  "good ov info");
-            mdp_wrapper::dump("== Bad OVInfo is: ", mOVInfo);
-            mdp_wrapper::dump("== Last good known OVInfo is: ", mLkgo);
-            this->restore();
+    if(!mdp_wrapper::setOverlay(mFd.getFD(), mOVInfo)) {
+        ALOGE("MdpCtrl failed to setOverlay");
+        mdp_wrapper::dump("== Bad OVInfo is: ", mOVInfo);
 #ifdef USES_QSEED_SCALAR
-            if(Overlay::getScalar()) {
-                Overlay::getScalar()->configAbort(mDpy);
-            }
-#endif
-            return false;
+        if(Overlay::getScalar()) {
+            Overlay::getScalar()->configAbort(mDpy);
         }
-        this->save();
+#endif
+        return false;
     }
 
 #ifdef USES_QSEED_SCALAR
@@ -283,8 +274,9 @@
 }
 
 bool MdpCtrl::setVisualParams(const MetaData_t& data) {
-    bool needUpdate = false;
+    ALOGD_IF(0, "In %s: data.operation = %d", __FUNCTION__, data.operation);
 #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) {
@@ -392,7 +384,6 @@
 
     if (needUpdate) {
         display_pp_compute_params(&mParams, &mOVInfo.overlay_pp_cfg);
-        mPPChanged = true;
     }
 #endif
     return true;
@@ -400,7 +391,7 @@
 
 
 //// MdpData ////////////
-bool MdpData::init(uint32_t dpy) {
+bool MdpData::init(const int& dpy) {
     int fbnum = Overlay::getFbForDpy(dpy);
     if( fbnum < 0 ) {
         ALOGE("%s: Invalid FB for the display: %d",__FUNCTION__, dpy);
diff --git a/liboverlay/overlayMdp.h b/liboverlay/overlayMdp.h
index 3cb6a41..daaeaf2 100644
--- a/liboverlay/overlayMdp.h
+++ b/liboverlay/overlayMdp.h
@@ -36,11 +36,11 @@
 class MdpCtrl {
 public:
     /* ctor reset */
-    explicit MdpCtrl();
+    explicit MdpCtrl(const int& dpy);
     /* dtor close */
     ~MdpCtrl();
     /* init underlying device using fbnum for dpy */
-    bool init(uint32_t dpy);
+    bool init(const int& dpy);
     /* unset overlay, reset and close fd */
     bool close();
     /* reset and set ov id to -1 / MSMFB_NEW_REQUEST */
@@ -116,17 +116,8 @@
     int getUserData() const;
     /* sets user_data[0] */
     void setUserData(int v);
-    /* return true if current overlay is different
-     * than last known good overlay */
-    bool ovChanged() const;
-    /* save mOVInfo to be last known good ov*/
-    void save();
-    /* restore last known good ov to be the current */
-    void restore();
 
     utils::eTransform mOrientation; //Holds requested orientation
-    /* last good known ov info */
-    mdp_overlay   mLkgo;
     /* Actual overlay mdp structure */
     mdp_overlay   mOVInfo;
     /* FD for the mdp fbnum */
@@ -137,8 +128,6 @@
 #ifdef USES_POST_PROCESSING
     /* PP Compute Params */
     struct compute_params mParams;
-    /* indicate if PP params have been changed */
-    bool mPPChanged;
 #endif
 };
 
@@ -171,11 +160,11 @@
 class MdpData {
 public:
     /* ctor reset data */
-    explicit MdpData();
+    explicit MdpData(const int& dpy);
     /* dtor close*/
     ~MdpData();
     /* init FD */
-    bool init(uint32_t dpy);
+    bool init(const int& dpy);
     /* memset0 the underlying mdp object */
     void reset();
     /* close fd, and reset */
@@ -207,8 +196,9 @@
 
 /////   MdpCtrl  //////
 
-inline MdpCtrl::MdpCtrl() {
+inline MdpCtrl::MdpCtrl(const int& dpy) {
     reset();
+    init(dpy);
 }
 
 inline MdpCtrl::~MdpCtrl() {
@@ -265,37 +255,6 @@
     }
 }
 
-inline bool MdpCtrl::ovChanged() const {
-#ifdef USES_POST_PROCESSING
-    // Some pp params are stored as pointer address,
-    // so can't compare their content directly.
-    if (mPPChanged) {
-        return true;
-    }
-#endif
-    // 0 means same
-    if(0 == ::memcmp(&mOVInfo, &mLkgo, sizeof (mdp_overlay))) {
-        return false;
-    }
-    return true;
-}
-
-inline void MdpCtrl::save() {
-    if(static_cast<ssize_t>(mOVInfo.id) == MSMFB_NEW_REQUEST) {
-        ALOGE("MdpCtrl current ov has id -1, will not save");
-        return;
-    }
-    mLkgo = mOVInfo;
-}
-
-inline void MdpCtrl::restore() {
-    if(static_cast<ssize_t>(mLkgo.id) == MSMFB_NEW_REQUEST) {
-        ALOGE("MdpCtrl Lkgo ov has id -1, will not restore");
-        return;
-    }
-    mOVInfo = mLkgo;
-}
-
 inline overlay::utils::Whf MdpCtrl::getSrcWhf() const {
     return utils::Whf(  mOVInfo.src.width,
                         mOVInfo.src.height,
@@ -388,7 +347,10 @@
 
 ///////    MdpData   //////
 
-inline MdpData::MdpData() { reset(); }
+inline MdpData::MdpData(const int& dpy) {
+    reset();
+    init(dpy);
+}
 
 inline MdpData::~MdpData() { close(); }
 
diff --git a/liboverlay/overlayMdpRot.cpp b/liboverlay/overlayMdpRot.cpp
index ce2ef5b..3e549b1 100755
--- a/liboverlay/overlayMdpRot.cpp
+++ b/liboverlay/overlayMdpRot.cpp
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2008 The Android Open Source Project
- * Copyright (c) 2010-2013, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2010-2014, The Linux Foundation. All rights reserved.
  * Not a Contribution, Apache license notifications and license are retained
  * for attribution purposes only.
  *
@@ -94,7 +94,7 @@
     mRotImgInfo.dst.height = whf.h;
 }
 
-void MdpRot::setCrop(const utils::Dim& crop) {
+void MdpRot::setCrop(const utils::Dim& /*crop*/) {
     // NO-OP for non-mdss rotator due to possible h/w limitations
 }
 
diff --git a/liboverlay/overlayMdssRot.cpp b/liboverlay/overlayMdssRot.cpp
index c6d5332..083e507 100644
--- a/liboverlay/overlayMdssRot.cpp
+++ b/liboverlay/overlayMdssRot.cpp
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2008 The Android Open Source Project
- * Copyright (c) 2010-2013, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2010-2014, The Linux Foundation. All rights reserved.
  * Not a Contribution, Apache license notifications and license are retained
  * for attribution purposes only.
  *
@@ -92,7 +92,8 @@
     mRotInfo.dst_rect.h = crop.h;
 }
 
-void MdssRot::setDownscale(int ds) {}
+void MdssRot::setDownscale(int /*ds*/) {
+}
 
 void MdssRot::setFlags(const utils::eMdpFlags& flags) {
     mRotInfo.flags = flags;
diff --git a/liboverlay/overlayUtils.cpp b/liboverlay/overlayUtils.cpp
index 1377182..5cc4c03 100644
--- a/liboverlay/overlayUtils.cpp
+++ b/liboverlay/overlayUtils.cpp
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
+* 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
@@ -36,6 +36,7 @@
 #include "overlayUtils.h"
 #include "mdpWrapper.h"
 #include "mdp_version.h"
+#include <hardware/hwcomposer_defs.h>
 
 // just a helper static thingy
 namespace {
@@ -145,6 +146,34 @@
     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:
+            // Currenty Driver doesnt support 565 tile format
+            return MDP_RGB_565;
+        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) {
@@ -394,7 +423,7 @@
     getDump(buf, len, "\tdst_rect", ov.dst_rect);
 }
 
-void getDump(char *buf, size_t len, const char *prefix,
+void getDump(char *buf, size_t /*len*/, const char *prefix,
         const msmfb_img& ov) {
     char str_src[256] = {'\0'};
     snprintf(str_src, 256,
@@ -404,7 +433,7 @@
     strncat(buf, str_src, strlen(str_src));
 }
 
-void getDump(char *buf, size_t len, const char *prefix,
+void getDump(char *buf, size_t /*len*/, const char *prefix,
         const mdp_rect& ov) {
     char str_rect[256] = {'\0'};
     snprintf(str_rect, 256,
@@ -423,7 +452,7 @@
     getDump(buf, len, "\tdata", ov.data);
 }
 
-void getDump(char *buf, size_t len, const char *prefix,
+void getDump(char *buf, size_t /*len*/, const char *prefix,
         const msmfb_data& ov) {
     char str_data[256] = {'\0'};
     snprintf(str_data, 256,
diff --git a/liboverlay/overlayUtils.h b/liboverlay/overlayUtils.h
index 904d607..24fba33 100644
--- a/liboverlay/overlayUtils.h
+++ b/liboverlay/overlayUtils.h
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
+* 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
@@ -272,6 +272,7 @@
     OV_MDSS_MDP_BWC_EN = MDP_BWC_EN,
     OV_MDSS_MDP_DUAL_PIPE = MDSS_MDP_DUAL_PIPE,
     OV_MDP_SOLID_FILL = MDP_SOLID_FILL,
+    OV_MDP_VPU_PIPE = MDP_VPU_PIPE,
 };
 
 enum eZorder {
@@ -408,6 +409,7 @@
 };
 
 int getMdpFormat(int format);
+int getMdpFormat(int format, bool tileEnabled);
 int getHALFormat(int mdpFormat);
 int getDownscaleFactor(const int& src_w, const int& src_h,
         const int& dst_w, const int& dst_h);
@@ -545,6 +547,14 @@
     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_IMGTYPE_LIMIT] = STR(MDP_IMGTYPE_LIMIT);
 
     if(format < 0 || format >= MDP_IMGTYPE_LIMIT) {
diff --git a/liboverlay/pipes/overlayGenPipe.cpp b/liboverlay/pipes/overlayGenPipe.cpp
index e0b580b..394a56e 100644
--- a/liboverlay/pipes/overlayGenPipe.cpp
+++ b/liboverlay/pipes/overlayGenPipe.cpp
@@ -32,73 +32,40 @@
 
 namespace overlay {
 
-GenericPipe::GenericPipe(int dpy) : mDpy(dpy), mRotDownscaleOpt(false),
-    pipeState(CLOSED) {
-    init();
+GenericPipe::GenericPipe(const int& dpy) : mDpy(dpy), mRotDownscaleOpt(false),
+    pipeState(CLOSED), mCtrl(new Ctrl(dpy)), mData(new Data(dpy)) {
 }
 
 GenericPipe::~GenericPipe() {
-    close();
-}
-
-bool GenericPipe::init()
-{
-    ALOGE_IF(DEBUG_OVERLAY, "GenericPipe init");
-    mRotDownscaleOpt = false;
-
-    if(!mCtrlData.ctrl.init(mDpy)) {
-        ALOGE("GenericPipe failed to init ctrl");
-        return false;
-    }
-
-    if(!mCtrlData.data.init(mDpy)) {
-        ALOGE("GenericPipe failed to init data");
-        return false;
-    }
-
-    return true;
-}
-
-bool GenericPipe::close() {
-    bool ret = true;
-
-    if(!mCtrlData.ctrl.close()) {
-        ALOGE("GenericPipe failed to close ctrl");
-        ret = false;
-    }
-    if (!mCtrlData.data.close()) {
-        ALOGE("GenericPipe failed to close data");
-        ret = false;
-    }
-
+    delete mCtrl;
+    delete mData;
     setClosed();
-    return ret;
 }
 
 void GenericPipe::setSource(const utils::PipeArgs& args) {
     mRotDownscaleOpt = args.rotFlags & utils::ROT_DOWNSCALE_ENABLED;
-    mCtrlData.ctrl.setSource(args);
+    mCtrl->setSource(args);
 }
 
 void GenericPipe::setCrop(const overlay::utils::Dim& d) {
-    mCtrlData.ctrl.setCrop(d);
+    mCtrl->setCrop(d);
 }
 
 void GenericPipe::setColor(const uint32_t color) {
-    mCtrlData.ctrl.setColor(color);
+    mCtrl->setColor(color);
 }
 
 void GenericPipe::setTransform(const utils::eTransform& orient) {
-    mCtrlData.ctrl.setTransform(orient);
+    mCtrl->setTransform(orient);
 }
 
 void GenericPipe::setPosition(const utils::Dim& d) {
-    mCtrlData.ctrl.setPosition(d);
+    mCtrl->setPosition(d);
 }
 
 bool GenericPipe::setVisualParams(const MetaData_t &metadata)
 {
-        return mCtrlData.ctrl.setVisualParams(metadata);
+        return mCtrl->setVisualParams(metadata);
 }
 
 bool GenericPipe::commit() {
@@ -106,14 +73,14 @@
     int downscale_factor = utils::ROT_DS_NONE;
 
     if(mRotDownscaleOpt) {
-        ovutils::Dim src(mCtrlData.ctrl.getCrop());
-        ovutils::Dim dst(mCtrlData.ctrl.getPosition());
+        ovutils::Dim src(mCtrl->getCrop());
+        ovutils::Dim dst(mCtrl->getPosition());
         downscale_factor = ovutils::getDownscaleFactor(
                 src.w, src.h, dst.w, dst.h);
     }
 
-    mCtrlData.ctrl.setDownscale(downscale_factor);
-    ret = mCtrlData.ctrl.commit();
+    mCtrl->setDownscale(downscale_factor);
+    ret = mCtrl->commit();
 
     pipeState = ret ? OPEN : CLOSED;
     return ret;
@@ -122,36 +89,35 @@
 bool GenericPipe::queueBuffer(int fd, uint32_t offset) {
     //TODO Move pipe-id transfer to CtrlData class. Make ctrl and data private.
     OVASSERT(isOpen(), "State is closed, cannot queueBuffer");
-    int pipeId = mCtrlData.ctrl.getPipeId();
+    int pipeId = mCtrl->getPipeId();
     OVASSERT(-1 != pipeId, "Ctrl ID should not be -1");
     // set pipe id from ctrl to data
-    mCtrlData.data.setPipeId(pipeId);
+    mData->setPipeId(pipeId);
 
-    return mCtrlData.data.queueBuffer(fd, offset);
+    return mData->queueBuffer(fd, offset);
 }
 
 int GenericPipe::getCtrlFd() const {
-    return mCtrlData.ctrl.getFd();
+    return mCtrl->getFd();
 }
 
 utils::Dim GenericPipe::getCrop() const
 {
-    return mCtrlData.ctrl.getCrop();
+    return mCtrl->getCrop();
 }
 
 void GenericPipe::dump() const
 {
     ALOGE("== Dump Generic pipe start ==");
     ALOGE("pipe state = %d", (int)pipeState);
-    mCtrlData.ctrl.dump();
-    mCtrlData.data.dump();
-
+    mCtrl->dump();
+    mData->dump();
     ALOGE("== Dump Generic pipe end ==");
 }
 
 void GenericPipe::getDump(char *buf, size_t len) {
-    mCtrlData.ctrl.getDump(buf, len);
-    mCtrlData.data.getDump(buf, len);
+    mCtrl->getDump(buf, len);
+    mData->getDump(buf, len);
 }
 
 bool GenericPipe::isClosed() const  {
@@ -168,7 +134,7 @@
 }
 
 int GenericPipe::getPipeId() {
-    return mCtrlData.ctrl.getPipeId();
+    return mCtrl->getPipeId();
 }
 
 } //namespace overlay
diff --git a/liboverlay/pipes/overlayGenPipe.h b/liboverlay/pipes/overlayGenPipe.h
index ecdd001..57e1758 100644
--- a/liboverlay/pipes/overlayGenPipe.h
+++ b/liboverlay/pipes/overlayGenPipe.h
@@ -38,11 +38,9 @@
 class GenericPipe : utils::NoCopy {
 public:
     /* ctor */
-    explicit GenericPipe(int dpy);
+    explicit GenericPipe(const int& dpy);
     /* dtor */
     ~GenericPipe();
-    bool init();
-    bool close();
     /* Control APIs */
     /* set source using whf, orient and wait flag */
     void setSource(const utils::PipeArgs& args);
@@ -82,8 +80,6 @@
     bool setClosed();
 
     int mDpy;
-    /* Ctrl/Data aggregator */
-    CtrlData mCtrlData;
     //Whether we will do downscale opt. This is just a request. If the frame is
     //not a candidate, we might not do it.
     bool mRotDownscaleOpt;
@@ -93,6 +89,8 @@
         OPEN
     };
     ePipeState pipeState;
+    Ctrl *mCtrl;
+    Data *mData;
 };
 
 } //namespace overlay
diff --git a/libqdutils/Android.mk b/libqdutils/Android.mk
index 06f4f00..2907ccf 100644
--- a/libqdutils/Android.mk
+++ b/libqdutils/Android.mk
@@ -13,7 +13,8 @@
 LOCAL_SRC_FILES               := profiler.cpp mdp_version.cpp \
                                  idle_invalidator.cpp \
                                  comptype.cpp qd_utils.cpp \
-                                 cb_utils.cpp display_config.cpp
+                                 cb_utils.cpp display_config.cpp \
+                                 cb_swap_rect.cpp
 include $(BUILD_SHARED_LIBRARY)
 
 include $(CLEAR_VARS)
diff --git a/libqdutils/cb_swap_rect.cpp b/libqdutils/cb_swap_rect.cpp
new file mode 100644
index 0000000..8c8efec
--- /dev/null
+++ b/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/libqdutils/cb_swap_rect.h b/libqdutils/cb_swap_rect.h
new file mode 100644
index 0000000..daaeb37
--- /dev/null
+++ b/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/libqdutils/cb_utils.cpp b/libqdutils/cb_utils.cpp
index d8eec2a..3d07c4f 100644
--- a/libqdutils/cb_utils.cpp
+++ b/libqdutils/cb_utils.cpp
@@ -26,9 +26,10 @@
 */
 
 #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);
@@ -44,15 +45,23 @@
 
     uint32_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);
 
-    for (uint32_t i = 0 ; i < last; i++) {
-        //TODO Work on using hwc clear instead of gpu for HWC_BLIT
-        //If layer is marked for HWC_BLIT clear is done by GPU
-        if(list->hwLayers[i].compositionType == HWC_BLIT)
-            return 0;
+    if(cb_swap_rect::getInstance().checkSwapRectFeature_on() == true){
+      wormholeRegion.set(0,0);
+      for(uint32_t i = 0 ; i < last; i++) {
+         if((list->hwLayers[i].blending == HWC_BLENDING_NONE) ||
+           !(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 (uint32_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) ||
@@ -63,21 +72,27 @@
         displayFrame.bottom);
         Region tmpRegion(tmpRect);
         wormholeRegion.subtractSelf(wormholeRegion.intersect(tmpRegion));
-    }
-    if (wormholeRegion.isEmpty()) {
+     }
+   }
+   if(wormholeRegion.isEmpty()){
         return 0;
-    }
-    //TO DO :- 1. remove union and call clear for each rect.
-    //      :- 2. support swap ract feature.
-    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};
-        getUnion(clearWormholeRect, tmpWormRect, clearWormholeRect);
+   }
+   //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};
+       int dst_w =  clearWormholeRect.right -  clearWormholeRect.left;
+       int dst_h =  clearWormholeRect.bottom -  clearWormholeRect.top;
 
-    }
-    return 1;
+       if (!(dst_w || dst_h))
+             clearWormholeRect = tmpWormRect;
+       else
+             getUnion(clearWormholeRect, tmpWormRect, clearWormholeRect);
+
+   }
+   return 1;
 }
 
 }//namespace qdutils
diff --git a/libqdutils/display_config.cpp b/libqdutils/display_config.cpp
index 45b0211..60f1f68 100644
--- a/libqdutils/display_config.cpp
+++ b/libqdutils/display_config.cpp
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2013 The Linux Foundation. All rights reserved.
+* 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
@@ -37,7 +37,7 @@
 
 int isExternalConnected(void) {
     int ret;
-    status_t err = FAILED_TRANSACTION;
+    status_t err = (status_t) FAILED_TRANSACTION;
     sp<IQService> binder = getBinder();
     Parcel inParcel, outParcel;
     if(binder != NULL) {
@@ -54,7 +54,7 @@
 }
 
 int getDisplayAttributes(int dpy, DisplayAttributes_t& dpyattr) {
-    status_t err = FAILED_TRANSACTION;
+    status_t err = (status_t) FAILED_TRANSACTION;
     sp<IQService> binder = getBinder();
     Parcel inParcel, outParcel;
     inParcel.writeInt32(dpy);
@@ -76,7 +76,7 @@
 }
 
 int setHSIC(int dpy, const HSICData_t& hsic_data) {
-    status_t err = FAILED_TRANSACTION;
+    status_t err = (status_t) FAILED_TRANSACTION;
     sp<IQService> binder = getBinder();
     Parcel inParcel, outParcel;
     inParcel.writeInt32(dpy);
@@ -93,7 +93,7 @@
 }
 
 int getDisplayVisibleRegion(int dpy, hwc_rect_t &rect) {
-    status_t err = FAILED_TRANSACTION;
+    status_t err = (status_t) FAILED_TRANSACTION;
     sp<IQService> binder = getBinder();
     Parcel inParcel, outParcel;
     inParcel.writeInt32(dpy);
diff --git a/libqdutils/idle_invalidator.cpp b/libqdutils/idle_invalidator.cpp
index 97176a4..b53f1a3 100644
--- a/libqdutils/idle_invalidator.cpp
+++ b/libqdutils/idle_invalidator.cpp
@@ -54,16 +54,43 @@
 }
 
 bool IdleInvalidator::threadLoop() {
+    struct timeval lastUpdateTime;
     ALOGD_IF(II_DEBUG, "%s", __func__);
-    usleep(mSleepTime * 500);
+
+    {
+        //If we are here, update(s) happened, i.e mSleepAgain is set
+        Locker::Autolock _l(mLock);
+        mSleepAgain = false;
+        lastUpdateTime = mLastUpdateTime;
+    }
+
+    struct timeval currentTime;
+    gettimeofday(&currentTime, NULL);
+    int timeSinceUpdateUs = (currentTime.tv_sec - lastUpdateTime.tv_sec) *
+            1000000 + (currentTime.tv_usec - lastUpdateTime.tv_usec);
+    int sleepDurationUs = mSleepTime * 1000 - timeSinceUpdateUs;
+
+    //Sleep only if the duration required is > 1ms, otherwise its not worth it.
+    if(sleepDurationUs > 1000) {
+        usleep(sleepDurationUs);
+        ALOGD_IF(II_DEBUG, "Slept for %d ms", sleepDurationUs / 1000);
+    }
 
     Locker::Autolock _l(mLock);
+    //If an update happened while we were asleep, sleep again
     if(mSleepAgain) {
         //We need to sleep again!
         mSleepAgain = false;
         return true;
     }
 
+#if II_DEBUG
+    gettimeofday(&currentTime, NULL);
+    timeSinceUpdateUs = (currentTime.tv_sec - lastUpdateTime.tv_sec) *
+            1000000 + (currentTime.tv_usec - lastUpdateTime.tv_usec);
+    ALOGD("Idle refresh after %dms", timeSinceUpdateUs / 1000);
+#endif
+
     mHandler((void*)mHwcContext);
     return false;
 }
@@ -77,8 +104,9 @@
     ALOGD_IF(II_DEBUG, "%s", __func__);
 }
 
-void IdleInvalidator::markForSleep() {
+void IdleInvalidator::handleUpdateEvent() {
     Locker::Autolock _l(mLock);
+    gettimeofday(&mLastUpdateTime, NULL);
     mSleepAgain = true;
     //Triggers the threadLoop to run, if not already running.
     run(threadName, android::PRIORITY_AUDIO);
diff --git a/libqdutils/idle_invalidator.h b/libqdutils/idle_invalidator.h
index abd9b29..f41c15e 100644
--- a/libqdutils/idle_invalidator.h
+++ b/libqdutils/idle_invalidator.h
@@ -38,6 +38,7 @@
 
 class IdleInvalidator : public android::Thread {
     void *mHwcContext;
+    struct timeval mLastUpdateTime;
     bool mSleepAgain;
     unsigned int mSleepTime;
     static InvalidatorHandler mHandler;
@@ -49,7 +50,7 @@
     /* init timer obj */
     int init(InvalidatorHandler reg_handler, void* user_data, unsigned int
              idleSleepTime);
-    void markForSleep();
+    void handleUpdateEvent();
     /*Overrides*/
     virtual bool        threadLoop();
     virtual int         readyToRun();
diff --git a/libqdutils/mdp_version.cpp b/libqdutils/mdp_version.cpp
index b219cd5..9e36980 100644
--- a/libqdutils/mdp_version.cpp
+++ b/libqdutils/mdp_version.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+ * 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
@@ -37,6 +37,25 @@
 
 #define TOKEN_PARAMS_DELIM  "="
 
+#ifndef MDSS_MDP_REV
+enum mdp_rev {
+    MDSS_MDP_HW_REV_100 = 0x10000000, //8974 v1
+    MDSS_MDP_HW_REV_101 = 0x10010000, //8x26
+    MDSS_MDP_HW_REV_102 = 0x10020000, //8974 v2
+    MDSS_MDP_HW_REV_103 = 0x10030000, //8084
+    MDSS_MDP_HW_REV_104 = 0x10040000, //Next version
+    MDSS_MDP_HW_REV_105 = 0x10050000, //Next version
+    MDSS_MDP_HW_REV_107 = 0x10070000, //Next version
+    MDSS_MDP_HW_REV_200 = 0x20000000, //8092
+    MDSS_MDP_HW_REV_206 = 0x20060000, //Future
+};
+#else
+enum mdp_rev {
+    MDSS_MDP_HW_REV_104 = 0x10040000, //Next version
+    MDSS_MDP_HW_REV_206 = 0x20060000, //Future
+};
+#endif
+
 MDPVersion::MDPVersion()
 {
     mMDPVersion = MDSS_V5;
@@ -47,6 +66,7 @@
     mFeatures = 0;
     mMDPUpscale = 0;
     mMDPDownscale = 0;
+    mMacroTileEnabled = false;
     mPanelType = NO_PANEL;
     mLowBw = 0;
     mHighBw = 0;
@@ -79,7 +99,7 @@
                                 char* tokenStr[], int *idx) {
     char *tmp_token = NULL;
     char *temp_ptr;
-    int ret = 0, index = 0;
+    int index = 0;
     if (!inputParams) {
         return -1;
     }
@@ -136,6 +156,14 @@
     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");
 
@@ -185,6 +213,11 @@
                                     strlen("decimation"))) {
                            mFeatures |= MDP_DECIMATION_EN;
                         }
+                        else if(!strncmp(tokens[i], "tile_format",
+                                    strlen("tile_format"))) {
+                           if(enableMacroTile)
+                               mMacroTileEnabled = true;
+                        }
                     }
                 }
             }
@@ -239,10 +272,39 @@
     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::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);
+}
+
 }; //namespace qdutils
 
diff --git a/libqdutils/mdp_version.h b/libqdutils/mdp_version.h
index 60a2985..853b9f5 100644
--- a/libqdutils/mdp_version.h
+++ b/libqdutils/mdp_version.h
@@ -63,17 +63,6 @@
 //                                        0000   -  minor number
 // 8x26 v1 minor number is 0000
 //      v2 minor number is 0001 etc..
-enum mdp_rev {
-    MDSS_MDP_HW_REV_100 = 0x10000000, //8974 v1
-    MDSS_MDP_HW_REV_101 = 0x10010000, //8x26
-    MDSS_MDP_HW_REV_102 = 0x10020000, //8974 v2
-    MDSS_MDP_HW_REV_103 = 0x10030000, //8084
-    MDSS_MDP_HW_REV_104 = 0x10040000, //Next version
-    MDSS_MDP_HW_REV_105 = 0x10050000, //Next version
-    MDSS_MDP_HW_REV_107 = 0x10070000, //Next version
-    MDSS_MDP_HW_REV_200 = 0x20000000, //8092
-    MDSS_MDP_HW_REV_206 = 0x20060000, //Future
-};
 
 enum {
     MAX_DISPLAY_DIM = 2048,
@@ -117,28 +106,17 @@
     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(); }
     unsigned long getLowBw() { return mLowBw; }
     unsigned long getHighBw() { return mHighBw; }
-
-    bool is8x26() {
-        return (mMdpRev >= MDSS_MDP_HW_REV_101 and
-                mMdpRev < MDSS_MDP_HW_REV_102);
-    }
-    bool is8x74v2() {
-        return (mMdpRev >= MDSS_MDP_HW_REV_102 and
-                mMdpRev < MDSS_MDP_HW_REV_103);
-    }
-    bool is8084() {
-        return (mMdpRev >= MDSS_MDP_HW_REV_103 and
-                mMdpRev < MDSS_MDP_HW_REV_104);
-    }
-    bool is8092() {
-        return (mMdpRev >= MDSS_MDP_HW_REV_200 and
-                mMdpRev < MDSS_MDP_HW_REV_206);
-    }
+    bool is8x26();
+    bool is8x74v2();
+    bool is8084();
+    bool is8092();
 
 private:
     bool updateSysFsInfo();
@@ -157,6 +135,7 @@
     uint32_t mFeatures;
     uint32_t mMDPDownscale;
     uint32_t mMDPUpscale;
+    bool mMacroTileEnabled;
     Split mSplit;
     unsigned long mLowBw; //kbps
     unsigned long mHighBw; //kbps
diff --git a/libqdutils/profiler.cpp b/libqdutils/profiler.cpp
index 031fdc3..997c839 100644
--- a/libqdutils/profiler.cpp
+++ b/libqdutils/profiler.cpp
@@ -28,6 +28,9 @@
  */
 
 #define LOG_NDDEBUG 0
+#define __STDC_FORMAT_MACROS 1
+#include <inttypes.h>
+
 #include "profiler.h"
 
 #ifdef DEBUG_CALC_FPS
@@ -104,7 +107,7 @@
     debug_fps_metadata.curr_frame = 0;
 
     ALOGD("period: %d", debug_fps_metadata.period);
-    ALOGD("ignorethresh_us: %lld", debug_fps_metadata.ignorethresh_us);
+    ALOGD("ignorethresh_us: %"PRId64, debug_fps_metadata.ignorethresh_us);
 }
 
 void CalcFps::print_fps(float fps)
@@ -124,7 +127,7 @@
         for (unsigned int i = 0;
              i < ((debug_fps_metadata.framearrival_steps / 6) + 1);
              i++) {
-            ALOGD("%lld %lld %lld %lld %lld %lld",
+            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],
diff --git a/libqdutils/qdMetaData.cpp b/libqdutils/qdMetaData.cpp
index f39eef9..ecbf873 100644
--- a/libqdutils/qdMetaData.cpp
+++ b/libqdutils/qdMetaData.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+ * 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
@@ -31,6 +31,8 @@
 #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,
@@ -106,7 +108,7 @@
             break;
     }
     if(munmap(base, size))
-        ALOGE("%s: failed to unmap ptr 0x%x, err %d", __func__, (int)base,
+        ALOGE("%s: failed to unmap ptr 0x%"PRIdPTR", err %d", __func__, (intptr_t)base,
                                                                         errno);
     return 0;
 }
diff --git a/libqdutils/qd_utils.cpp b/libqdutils/qd_utils.cpp
index 5a457d0..0698b33 100644
--- a/libqdutils/qd_utils.cpp
+++ b/libqdutils/qd_utils.cpp
@@ -31,7 +31,6 @@
 
 
 #define MAX_FRAME_BUFFER_NAME_SIZE      (80)
-#define MAX_DISPLAY_DEVICES             (3)
 
 int getHDMINode(void)
 {
@@ -40,7 +39,7 @@
     char msmFbTypePath[MAX_FRAME_BUFFER_NAME_SIZE];
     int j = 0;
 
-    for(j = 0; j < MAX_DISPLAY_DEVICES; j++) {
+    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");
@@ -58,7 +57,7 @@
         }
     }
 
-    if (j < MAX_DISPLAY_DEVICES)
+    if (j < HWC_NUM_DISPLAY_TYPES)
         return j;
     else
         ALOGE("%s: Failed to find HDMI node", __func__);
diff --git a/libqdutils/qd_utils.h b/libqdutils/qd_utils.h
index cca55d5..db6d367 100644
--- a/libqdutils/qd_utils.h
+++ b/libqdutils/qd_utils.h
@@ -42,6 +42,7 @@
 #include <sys/poll.h>
 #include <sys/resource.h>
 #include <cutils/properties.h>
+#include <hardware/hwcomposer.h>
 
 #define EDID_RAW_DATA_SIZE 640
 
diff --git a/libqservice/IQService.cpp b/libqservice/IQService.cpp
index d2180bb..096444f 100644
--- a/libqservice/IQService.cpp
+++ b/libqservice/IQService.cpp
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2010 The Android Open Source Project
- * Copyright (C) 2012-2013, The Linux Foundation. All rights reserved.
+ * Copyright (C) 2012-2014, The Linux Foundation. All rights reserved.
  *
  * Not a Contribution, Apache license notifications and license are
  * retained for attribution purposes only.
@@ -55,7 +55,7 @@
     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 = android::FAILED_TRANSACTION;
+        status_t err = (status_t) android::FAILED_TRANSACTION;
         Parcel data;
         Parcel *reply = outParcel;
         data.writeInterfaceToken(IQService::getInterfaceDescriptor());
@@ -80,7 +80,7 @@
     IPCThreadState* ipc = IPCThreadState::self();
     const int callerPid = ipc->getCallingPid();
     const int callerUid = ipc->getCallingUid();
-    const size_t MAX_BUF_SIZE = 1024;
+    const int MAX_BUF_SIZE = 1024;
     char callingProcName[MAX_BUF_SIZE] = {0};
 
     getProcName(callerPid, callingProcName, MAX_BUF_SIZE);
diff --git a/libqservice/IQService.h b/libqservice/IQService.h
index f8e58ab..33c3ca0 100644
--- a/libqservice/IQService.h
+++ b/libqservice/IQService.h
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2010 The Android Open Source Project
- * Copyright (C) 2012-2013, The Linux Foundation. All rights reserved.
+ * Copyright (C) 2012-2014, The Linux Foundation. All rights reserved.
  *
  * Not a Contribution, Apache license notifications and license are
  * retained for attribution purposes only.
@@ -49,6 +49,7 @@
         GET_DISPLAY_ATTRIBUTES,  // Get display attributes
         SET_HSIC_DATA,           // Set HSIC on dspp
         GET_DISPLAY_VISIBLE_REGION,  // Get the visibleRegion for dpy
+        PAUSE_WFD,               // Pause/Resume WFD
         VPU_COMMAND_LIST_START = 100, //Reserved block for VPU commands
         VPU_COMMAND_LIST_END   = 200,
         COMMAND_LIST_END = 400,
diff --git a/libqservice/QService.cpp b/libqservice/QService.cpp
index aac5788..e4af422 100644
--- a/libqservice/QService.cpp
+++ b/libqservice/QService.cpp
@@ -1,5 +1,5 @@
 /*
- *  Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+ *  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
@@ -54,7 +54,7 @@
 
 status_t QService::dispatch(uint32_t command, const Parcel* inParcel,
         Parcel* outParcel) {
-    status_t err = FAILED_TRANSACTION;
+    status_t err = (status_t) FAILED_TRANSACTION;
     if (mClient.get()) {
         ALOGD_IF(QSERVICE_DEBUG, "Dispatching command: %d", command);
         err = mClient->notifyCallback(command, inParcel, outParcel);
diff --git a/libqservice/QServiceUtils.h b/libqservice/QServiceUtils.h
index 3d1adc0..a5f4f7f 100644
--- a/libqservice/QServiceUtils.h
+++ b/libqservice/QServiceUtils.h
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2013 The Linux Foundation. All rights reserved.
+* Copyright (c) 2013-14 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
@@ -49,7 +49,7 @@
 }
 
 inline android::status_t sendSingleParam(uint32_t command, uint32_t value) {
-    android::status_t err = android::FAILED_TRANSACTION;
+    android::status_t err = (status_t) android::FAILED_TRANSACTION;
     android::sp<qService::IQService> binder = getBinder();
     android::Parcel inParcel, outParcel;
     inParcel.writeInt32(value);
@@ -83,4 +83,8 @@
     return sendSingleParam(qService::IQService::BUFFER_MIRRORMODE, enable);
 }
 
+inline android::status_t pauseWFD(uint32_t pause) {
+    return sendSingleParam(qService::IQService::PAUSE_WFD, pause);
+}
+
 #endif /* end of include guard: QSERVICEUTILS_H */