Merge "libgralloc: Add support for custom buffer size."
diff --git a/libcopybit/Android.mk b/libcopybit/Android.mk
index 55d421b..73bfa86 100644
--- a/libcopybit/Android.mk
+++ b/libcopybit/Android.mk
@@ -1,4 +1,4 @@
-# Copyright (C) 2012 The Android Open Source Project
+# Copyright (C) 2008 The Android Open Source Project
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
diff --git a/libexternal/external.cpp b/libexternal/external.cpp
index b9abc31..1a41775 100644
--- a/libexternal/external.cpp
+++ b/libexternal/external.cpp
@@ -86,9 +86,16 @@
     if(mFd == -1)
         return -1;
     readResolution();
-    //Get the best mode and set
     // TODO: Move this to activate
-    setResolution(getBestMode());
+    /* Used for changing the resolution
+     * getUserMode will get the preferred
+     * mode set thru adb shell */
+    int mode = getUserMode();
+    if (mode == -1) {
+        //Get the best mode and set
+        mode = getBestMode();
+    }
+    setResolution(mode);
     setDpyHdmiAttr();
     setExternalDisplay(true, mHdmiFbNum);
     return 0;
@@ -385,6 +392,8 @@
 
 int ExternalDisplay::getModeOrder(int mode)
 {
+    // XXX: We dont support interlaced modes but having
+    // it here for for future
     switch (mode) {
         default:
         case m1440x480i60_4_3:
@@ -424,6 +433,20 @@
     }
 }
 
+/// Returns the user mode set(if any) using adb shell
+int ExternalDisplay::getUserMode() {
+    /* Based on the property set the resolution */
+    char property_value[PROPERTY_VALUE_MAX];
+    property_get("hdmi.resolution", property_value, "-1");
+    int mode = atoi(property_value);
+    // We dont support interlaced modes
+    if(isValidMode(mode) && !isInterlacedMode(mode)) {
+        ALOGD_IF("%s: setting the HDMI mode = %d", __FUNCTION__, mode);
+        return mode;
+    }
+    return -1;
+}
+
 // Get the best mode for the current HD TV
 int ExternalDisplay::getBestMode() {
     int bestOrder = 0;
@@ -443,7 +466,30 @@
 
 inline bool ExternalDisplay::isValidMode(int ID)
 {
-    return ((ID >= m640x480p60_4_3) && (ID <= m1920x1080p30_16_9));
+    bool valid = false;
+    for (int i = 0; i < mModeCount; i++) {
+        if(ID == mEDIDModes[i]) {
+            valid = true;
+            break;
+        }
+    }
+    return valid;
+}
+
+// returns true if the mode(ID) is interlaced mode format
+bool ExternalDisplay::isInterlacedMode(int ID) {
+    bool interlaced = false;
+    switch(ID) {
+        case m1440x480i60_4_3:
+        case m1440x480i60_16_9:
+        case m1440x576i50_4_3:
+        case m1440x576i50_16_9:
+        case m1920x1080i60_16_9:
+            interlaced = true;
+        default:
+            interlaced = false;
+    }
+    return interlaced;
 }
 
 void ExternalDisplay::setResolution(int ID)
@@ -462,7 +508,7 @@
             mVInfo.right_margin, mVInfo.hsync_len, mVInfo.left_margin,
             mVInfo.lower_margin, mVInfo.vsync_len, mVInfo.upper_margin,
             mVInfo.pixclock/1000/1000);
-    //If its a valid mode and its a new ID - update var_screeninfo
+    //If its a new ID - update var_screeninfo
     if ((isValidMode(ID)) && mCurrentMode != ID) {
         const struct disp_mode_timing_type *mode =
             &supported_video_mode_lut[0];
diff --git a/libexternal/external.h b/libexternal/external.h
index 46c982d..d85ce44 100644
--- a/libexternal/external.h
+++ b/libexternal/external.h
@@ -55,7 +55,9 @@
     bool isValidMode(int ID);
     void handleUEvent(char* str, int len);
     int  getModeOrder(int mode);
+    int  getUserMode();
     int  getBestMode();
+    bool isInterlacedMode(int mode);
     void resetInfo();
     void setDpyHdmiAttr();
     void setDpyWfdAttr();
diff --git a/libgralloc/alloc_controller.cpp b/libgralloc/alloc_controller.cpp
index 823c1ae..669ea08 100644
--- a/libgralloc/alloc_controller.cpp
+++ b/libgralloc/alloc_controller.cpp
@@ -235,6 +235,11 @@
             alignedh = height;
             size = ALIGN(alignedw * alignedh * 2, 4096);
             break;
+        case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS:
+            alignedw = VENUS_Y_STRIDE(COLOR_FMT_NV12, width);
+            alignedh = VENUS_Y_SCANLINES(COLOR_FMT_NV12, height);
+            size = VENUS_BUFFER_SIZE(COLOR_FMT_NV12, width, height);
+            break;
         default:
             ALOGE("unrecognized pixel format: 0x%x", format);
             return -EINVAL;
diff --git a/libgralloc/gpu.cpp b/libgralloc/gpu.cpp
index 92e7193..f11a5fe 100644
--- a/libgralloc/gpu.cpp
+++ b/libgralloc/gpu.cpp
@@ -27,6 +27,7 @@
 #include "gpu.h"
 #include "memalloc.h"
 #include "alloc_controller.h"
+#include <qdMetaData.h>
 
 using namespace gralloc;
 
@@ -138,37 +139,52 @@
     data.pHandle = (unsigned int) pHandle;
     err = mAllocCtrl->allocate(data, usage);
 
-    if (usage & GRALLOC_USAGE_PRIVATE_UNSYNCHRONIZED) {
-        flags |= private_handle_t::PRIV_FLAGS_UNSYNCHRONIZED;
-    }
+    if (!err) {
+        /* allocate memory for enhancement data */
+        alloc_data eData;
+        eData.fd = -1;
+        eData.base = 0;
+        eData.offset = 0;
+        eData.size = ROUND_UP_PAGESIZE(sizeof(MetaData_t));
+        eData.pHandle = data.pHandle;
+        eData.align = getpagesize();
+        int eDataUsage = GRALLOC_USAGE_PRIVATE_SYSTEM_HEAP;
+        int eDataErr = mAllocCtrl->allocate(eData, eDataUsage);
+        ALOGE_IF(eDataErr, "gralloc failed for eDataErr=%s",
+                                          strerror(-eDataErr));
 
-    if (usage & GRALLOC_USAGE_PRIVATE_EXTERNAL_ONLY) {
-        flags |= private_handle_t::PRIV_FLAGS_EXTERNAL_ONLY;
-        //The EXTERNAL_BLOCK flag is always an add-on
-        if (usage & GRALLOC_USAGE_PRIVATE_EXTERNAL_BLOCK) {
-            flags |= private_handle_t::PRIV_FLAGS_EXTERNAL_BLOCK;
-        }if (usage & GRALLOC_USAGE_PRIVATE_EXTERNAL_CC) {
-            flags |= private_handle_t::PRIV_FLAGS_EXTERNAL_CC;
+        if (usage & GRALLOC_USAGE_PRIVATE_UNSYNCHRONIZED) {
+            flags |= private_handle_t::PRIV_FLAGS_UNSYNCHRONIZED;
         }
-    }
 
-    if (usage & GRALLOC_USAGE_HW_VIDEO_ENCODER ) {
-        flags |= private_handle_t::PRIV_FLAGS_VIDEO_ENCODER;
-    }
+        if (usage & GRALLOC_USAGE_PRIVATE_EXTERNAL_ONLY) {
+            flags |= private_handle_t::PRIV_FLAGS_EXTERNAL_ONLY;
+            //The EXTERNAL_BLOCK flag is always an add-on
+            if (usage & GRALLOC_USAGE_PRIVATE_EXTERNAL_BLOCK) {
+                flags |= private_handle_t::PRIV_FLAGS_EXTERNAL_BLOCK;
+            }
+            if (usage & GRALLOC_USAGE_PRIVATE_EXTERNAL_CC) {
+                flags |= private_handle_t::PRIV_FLAGS_EXTERNAL_CC;
+            }
+        }
 
-    if (usage & GRALLOC_USAGE_HW_CAMERA_WRITE) {
-        flags |= private_handle_t::PRIV_FLAGS_CAMERA_WRITE;
-    }
+        if (usage & GRALLOC_USAGE_HW_VIDEO_ENCODER ) {
+            flags |= private_handle_t::PRIV_FLAGS_VIDEO_ENCODER;
+        }
 
-    if (usage & GRALLOC_USAGE_HW_CAMERA_READ) {
-        flags |= private_handle_t::PRIV_FLAGS_CAMERA_READ;
-    }
+        if (usage & GRALLOC_USAGE_HW_CAMERA_WRITE) {
+            flags |= private_handle_t::PRIV_FLAGS_CAMERA_WRITE;
+        }
 
-    if (err == 0) {
+        if (usage & GRALLOC_USAGE_HW_CAMERA_READ) {
+            flags |= private_handle_t::PRIV_FLAGS_CAMERA_READ;
+        }
+
         flags |= data.allocType;
-        private_handle_t* hnd = new private_handle_t(data.fd, size, flags,
-                                                     bufferType, format, width,
-                                                     height);
+        int eBaseAddr = int(eData.base) + eData.offset;
+        private_handle_t *hnd = new private_handle_t(data.fd, size, flags,
+                bufferType, format, width, height, eData.fd, eData.offset,
+                eBaseAddr);
 
         hnd->offset = data.offset;
         hnd->base = int(data.base) + data.offset;
@@ -176,6 +192,7 @@
     }
 
     ALOGE_IF(err, "gralloc failed err=%s", strerror(-err));
+
     return err;
 }
 
@@ -262,6 +279,13 @@
                                         hnd->offset, hnd->fd);
         if(err)
             return err;
+        // free the metadata space
+        unsigned long size = ROUND_UP_PAGESIZE(sizeof(MetaData_t));
+        err = memalloc->free_buffer((void*)hnd->base_metadata,
+                                    (size_t) size, hnd->offset_metadata,
+                                    hnd->fd_metadata);
+        if (err)
+            return err;
     }
 
     // Release the genlock
diff --git a/libgralloc/gralloc_priv.h b/libgralloc/gralloc_priv.h
index 59fbd30..6ccc7e0 100644
--- a/libgralloc/gralloc_priv.h
+++ b/libgralloc/gralloc_priv.h
@@ -30,6 +30,9 @@
 
 #include <cutils/log.h>
 
+#define ROUND_UP_PAGESIZE(x) ( (((unsigned long)(x)) + PAGE_SIZE-1)  & \
+                               (~(PAGE_SIZE-1)) )
+
 enum {
     /* gralloc usage bits indicating the type
      * of allocation that should be used */
@@ -96,6 +99,7 @@
 enum {
     /* OEM specific HAL formats */
     HAL_PIXEL_FORMAT_NV12_ENCODEABLE        = 0x102,
+    HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS     = 0x7FA30C04,
     HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED     = 0x7FA30C03,
     HAL_PIXEL_FORMAT_YCbCr_420_SP           = 0x109,
     HAL_PIXEL_FORMAT_YCrCb_420_SP_ADRENO    = 0x7FA30C01,
@@ -166,6 +170,7 @@
         int     fd;
         // genlock handle to be dup'd by the binder
         int     genlockHandle;
+        int     fd_metadata;          // fd for the meta-data
         // ints
         int     magic;
         int     flags;
@@ -173,6 +178,7 @@
         int     offset;
         int     bufferType;
         int     base;
+        int     offset_metadata;
         // The gpu address mapped into the mmu.
         // If using ashmem, set to 0, they don't care
         int     gpuaddr;
@@ -182,19 +188,21 @@
         int     height;
         // local fd of the genlock device.
         int     genlockPrivFd;
+        int     base_metadata;
 
 #ifdef __cplusplus
-        static const int sNumInts = 12;
-        static const int sNumFds = 2;
+        static const int sNumInts = 14;
+        static const int sNumFds = 3;
         static const int sMagic = 'gmsm';
 
         private_handle_t(int fd, int size, int flags, int bufferType,
-                         int format,int width, int height) :
-            fd(fd), genlockHandle(-1), magic(sMagic),
-            flags(flags), size(size), offset(0),
-            bufferType(bufferType), base(0), gpuaddr(0),
-            pid(0), format(format),
-            width(width), height(height), genlockPrivFd(-1)
+                         int format,int width, int height, int eFd = -1,
+                         int eOffset = 0, int eBase = 0) :
+            fd(fd), genlockHandle(-1), fd_metadata(eFd), magic(sMagic),
+            flags(flags), size(size), offset(0), bufferType(bufferType),
+            base(0), offset_metadata(eOffset), gpuaddr(0), pid(getpid()),
+            format(format), width(width), height(height), genlockPrivFd(-1),
+            base_metadata(eBase)
         {
             version = sizeof(native_handle);
             numInts = sNumInts;
diff --git a/libgralloc/mapper.cpp b/libgralloc/mapper.cpp
index 3088ecc..176a84e 100644
--- a/libgralloc/mapper.cpp
+++ b/libgralloc/mapper.cpp
@@ -42,6 +42,7 @@
 #include "gr.h"
 #include "alloc_controller.h"
 #include "memalloc.h"
+#include <qdMetaData.h>
 
 using namespace gralloc;
 /*****************************************************************************/
@@ -68,22 +69,27 @@
         IMemAlloc* memalloc = getAllocator(hnd->flags) ;
         int err = memalloc->map_buffer(&mappedAddress, size,
                                        hnd->offset, hnd->fd);
-        if(err) {
+        if(err || mappedAddress == MAP_FAILED) {
             ALOGE("Could not mmap handle %p, fd=%d (%s)",
                   handle, hnd->fd, strerror(errno));
             hnd->base = 0;
             return -errno;
         }
 
-        if (mappedAddress == MAP_FAILED) {
-            ALOGE("Could not mmap handle %p, fd=%d (%s)",
-                  handle, hnd->fd, strerror(errno));
-            hnd->base = 0;
-            return -errno;
-        }
         hnd->base = intptr_t(mappedAddress) + hnd->offset;
         //LOGD("gralloc_map() succeeded fd=%d, off=%d, size=%d, vaddr=%p",
         //        hnd->fd, hnd->offset, hnd->size, mappedAddress);
+        mappedAddress = MAP_FAILED;
+        size = ROUND_UP_PAGESIZE(sizeof(MetaData_t));
+        err = memalloc->map_buffer(&mappedAddress, size,
+                                       hnd->offset_metadata, hnd->fd_metadata);
+        if(err || mappedAddress == MAP_FAILED) {
+            ALOGE("Could not mmap handle %p, fd=%d (%s)",
+                  handle, hnd->fd_metadata, strerror(errno));
+            hnd->base_metadata = 0;
+            return -errno;
+        }
+        hnd->base_metadata = intptr_t(mappedAddress) + hnd->offset_metadata;
     }
     *vaddr = (void*)hnd->base;
     return 0;
@@ -98,10 +104,17 @@
         void* base = (void*)hnd->base;
         size_t size = hnd->size;
         IMemAlloc* memalloc = getAllocator(hnd->flags) ;
-        if(memalloc != NULL)
+        if(memalloc != NULL) {
             err = memalloc->unmap_buffer(base, size, hnd->offset);
-        if (err) {
-            ALOGE("Could not unmap memory at address %p", base);
+            if (err) {
+                ALOGE("Could not unmap memory at address %p", base);
+            }
+            base = (void*)hnd->base_metadata;
+            size = ROUND_UP_PAGESIZE(sizeof(MetaData_t));
+            err = memalloc->unmap_buffer(base, size, hnd->offset_metadata);
+            if (err) {
+                ALOGE("Could not unmap memory at address %p", base);
+            }
         }
     }
     hnd->base = 0;
@@ -277,6 +290,12 @@
                                      hnd->size, hnd->offset, hnd->fd);
         ALOGE_IF(err < 0, "cannot flush handle %p (offs=%x len=%x, flags = 0x%x) err=%s\n",
                  hnd, hnd->offset, hnd->size, hnd->flags, strerror(errno));
+        unsigned long size = ROUND_UP_PAGESIZE(sizeof(MetaData_t));
+        err = memalloc->clean_buffer((void*)hnd->base_metadata, size,
+                hnd->offset_metadata, hnd->fd_metadata);
+        ALOGE_IF(err < 0, "cannot flush handle %p (offs=%x len=%lu, "
+                "flags = 0x%x) err=%s\n", hnd, hnd->offset_metadata, size,
+                hnd->flags, strerror(errno));
         hnd->flags &= ~private_handle_t::PRIV_FLAGS_NEEDS_FLUSH;
     }
 
diff --git a/libhwcomposer/hwc.cpp b/libhwcomposer/hwc.cpp
index a0a0c82..ac1be19 100644
--- a/libhwcomposer/hwc.cpp
+++ b/libhwcomposer/hwc.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-2013, The Linux Foundation. All rights reserved.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -93,9 +93,11 @@
                     list->hwLayers[j].compositionType = HWC_FRAMEBUFFER;
             }
         }
+
+        if(ctx->mFBUpdate[i])
+            ctx->mFBUpdate[i]->reset();
     }
     VideoOverlay::reset();
-    FBUpdate::reset();
 }
 
 //clear prev layer prop flags and realloc for current frame
@@ -115,20 +117,21 @@
 static int hwc_prepare_primary(hwc_composer_device_1 *dev,
         hwc_display_contents_1_t *list) {
     hwc_context_t* ctx = (hwc_context_t*)(dev);
+    const int dpy = HWC_DISPLAY_PRIMARY;
 
     if (LIKELY(list && list->numHwLayers > 1) &&
-        ctx->dpyAttr[HWC_DISPLAY_PRIMARY].isActive) {
+        ctx->dpyAttr[dpy].isActive) {
 
         uint32_t last = list->numHwLayers - 1;
         hwc_layer_1_t *fbLayer = &list->hwLayers[last];
         if(fbLayer->handle) {
-            setListStats(ctx, list, HWC_DISPLAY_PRIMARY);
-            reset_layer_prop(ctx, HWC_DISPLAY_PRIMARY);
-            if(!MDPComp::configure(ctx, list)) {
-                VideoOverlay::prepare(ctx, list, HWC_DISPLAY_PRIMARY);
-                FBUpdate::prepare(ctx, fbLayer, HWC_DISPLAY_PRIMARY);
+            setListStats(ctx, list, dpy);
+            reset_layer_prop(ctx, dpy);
+            if(!ctx->mMDPComp->prepare(ctx, list)) {
+                VideoOverlay::prepare(ctx, list, dpy);
+                ctx->mFBUpdate[dpy]->prepare(ctx, fbLayer);
             }
-            ctx->mLayerCache[HWC_DISPLAY_PRIMARY]->updateLayerCache(list);
+            ctx->mLayerCache[dpy]->updateLayerCache(list);
         }
     }
     return 0;
@@ -137,20 +140,21 @@
 static int hwc_prepare_external(hwc_composer_device_1 *dev,
         hwc_display_contents_1_t *list) {
     hwc_context_t* ctx = (hwc_context_t*)(dev);
+    const int dpy = HWC_DISPLAY_EXTERNAL;
 
     if (LIKELY(list && list->numHwLayers > 1) &&
-        ctx->dpyAttr[HWC_DISPLAY_EXTERNAL].isActive &&
-        ctx->dpyAttr[HWC_DISPLAY_EXTERNAL].connected) {
+        ctx->dpyAttr[dpy].isActive &&
+        ctx->dpyAttr[dpy].connected) {
 
         uint32_t last = list->numHwLayers - 1;
         hwc_layer_1_t *fbLayer = &list->hwLayers[last];
         if(fbLayer->handle) {
-            setListStats(ctx, list, HWC_DISPLAY_EXTERNAL);
-            reset_layer_prop(ctx, HWC_DISPLAY_EXTERNAL);
-
-            VideoOverlay::prepare(ctx, list, HWC_DISPLAY_EXTERNAL);
-            FBUpdate::prepare(ctx, fbLayer, HWC_DISPLAY_EXTERNAL);
-            ctx->mLayerCache[HWC_DISPLAY_EXTERNAL]->updateLayerCache(list);
+            setListStats(ctx, list, dpy);
+            reset_layer_prop(ctx, dpy);
+            VideoOverlay::prepare(ctx, list, dpy);
+            ctx->mFBUpdate[dpy]->prepare(ctx, fbLayer);
+            ctx->mLayerCache[dpy]->updateLayerCache(list);
+            ctx->mExtDispConfiguring = false;
         }
     }
     return 0;
@@ -173,15 +177,14 @@
                 ret = hwc_prepare_primary(dev, list);
                 break;
             case HWC_DISPLAY_EXTERNAL:
-
                 ret = hwc_prepare_external(dev, list);
                 break;
             default:
                 ret = -EINVAL;
         }
     }
-    ctx->mOverlay->configDone();
 
+    ctx->mOverlay->configDone();
     return ret;
 }
 
@@ -230,7 +233,12 @@
             break;
         case HWC_DISPLAY_EXTERNAL:
             if(blank) {
-                //TODO actual
+                // External Display post commits the changes to display
+                // Call this on blank, so that any pipe unsets gets committed
+                if (!ctx->mExtDisplay->post()) {
+                    ret = -1;
+                    ALOGE("%s:ctx->mExtDisplay->post fail!! ", __FUNCTION__);
+                }
             } else {
             }
             break;
@@ -282,18 +290,19 @@
 
 static int hwc_set_primary(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
     int ret = 0;
+    const int dpy = HWC_DISPLAY_PRIMARY;
 
     if (LIKELY(list && list->numHwLayers > 1) &&
-        ctx->dpyAttr[HWC_DISPLAY_PRIMARY].isActive) {
+        ctx->dpyAttr[dpy].isActive) {
         uint32_t last = list->numHwLayers - 1;
         hwc_layer_1_t *fbLayer = &list->hwLayers[last];
 
-        hwc_sync(ctx, list, HWC_DISPLAY_PRIMARY);
-        if (!VideoOverlay::draw(ctx, list, HWC_DISPLAY_PRIMARY)) {
+        hwc_sync(ctx, list, dpy);
+        if (!VideoOverlay::draw(ctx, list, dpy)) {
             ALOGE("%s: VideoOverlay::draw fail!", __FUNCTION__);
             ret = -1;
         }
-        if (!MDPComp::draw(ctx, list)) {
+        if (!ctx->mMDPComp->draw(ctx, list)) {
             ALOGE("%s: MDPComp::draw fail!", __FUNCTION__);
             ret = -1;
         }
@@ -303,7 +312,7 @@
         private_handle_t *hnd = (private_handle_t *)fbLayer->handle;
         if(fbLayer->compositionType == HWC_FRAMEBUFFER_TARGET && hnd) {
             if(!(fbLayer->flags & HWC_SKIP_LAYER)) {
-                if (!FBUpdate::draw(ctx, fbLayer, HWC_DISPLAY_PRIMARY)) {
+                if (!ctx->mFBUpdate[dpy]->draw(ctx, fbLayer)) {
                     ALOGE("%s: FBUpdate::draw fail!", __FUNCTION__);
                     ret = -1;
                 }
@@ -320,17 +329,19 @@
 static int hwc_set_external(hwc_context_t *ctx,
         hwc_display_contents_1_t* list) {
     int ret = 0;
+    const int dpy = HWC_DISPLAY_EXTERNAL;
+
     Locker::Autolock _l(ctx->mExtSetLock);
 
     if (LIKELY(list && list->numHwLayers > 1) &&
-        ctx->dpyAttr[HWC_DISPLAY_EXTERNAL].isActive &&
-        ctx->dpyAttr[HWC_DISPLAY_EXTERNAL].connected) {
+        ctx->dpyAttr[dpy].isActive &&
+        ctx->dpyAttr[dpy].connected) {
         uint32_t last = list->numHwLayers - 1;
         hwc_layer_1_t *fbLayer = &list->hwLayers[last];
 
-        hwc_sync(ctx, list, HWC_DISPLAY_EXTERNAL);
+        hwc_sync(ctx, list, dpy);
 
-        if (!VideoOverlay::draw(ctx, list, HWC_DISPLAY_EXTERNAL)) {
+        if (!VideoOverlay::draw(ctx, list, dpy)) {
             ALOGE("%s: VideoOverlay::draw fail!", __FUNCTION__);
             ret = -1;
         }
@@ -338,7 +349,7 @@
         private_handle_t *hnd = (private_handle_t *)fbLayer->handle;
         if(fbLayer->compositionType == HWC_FRAMEBUFFER_TARGET &&
                 !(fbLayer->flags & HWC_SKIP_LAYER) && hnd) {
-            if (!FBUpdate::draw(ctx, fbLayer, HWC_DISPLAY_EXTERNAL)) {
+            if (!ctx->mFBUpdate[dpy]->draw(ctx, fbLayer)) {
                 ALOGE("%s: FBUpdate::draw fail!", __FUNCTION__);
                 ret = -1;
             }
@@ -462,7 +473,7 @@
     dumpsys_log(buf, "Qualcomm HWC state:\n");
     dumpsys_log(buf, "  MDPVersion=%d\n", ctx->mMDP.version);
     dumpsys_log(buf, "  DisplayPanel=%c\n", ctx->mMDP.panel);
-    MDPComp::dump(buf);
+    ctx->mMDPComp->dump(buf);
     //XXX: Call Other dump functions
     strlcpy(buff, buf.string(), buff_len);
 }
diff --git a/libhwcomposer/hwc_fbupdate.cpp b/libhwcomposer/hwc_fbupdate.cpp
index 0d0787e..ecbf813 100644
--- a/libhwcomposer/hwc_fbupdate.cpp
+++ b/libhwcomposer/hwc_fbupdate.cpp
@@ -18,7 +18,7 @@
  * limitations under the License.
  */
 
-#define HWC_FB_UPDATE 0
+#define DEBUG_FBUPDATE 0
 #include <gralloc_priv.h>
 #include <fb_priv.h>
 #include "hwc_fbupdate.h"
@@ -28,30 +28,38 @@
 
 namespace ovutils = overlay::utils;
 
-//Static Members
-bool FBUpdate::sModeOn[] = {false};
-ovutils::eDest FBUpdate::sDest[] = {ovutils::OV_INVALID};
-
-void FBUpdate::reset() {
-    sModeOn[HWC_DISPLAY_PRIMARY] = false;
-    sModeOn[HWC_DISPLAY_EXTERNAL] = false;
-    sDest[HWC_DISPLAY_PRIMARY] = ovutils::OV_INVALID;
-    sDest[HWC_DISPLAY_EXTERNAL] = ovutils::OV_INVALID;
+IFBUpdate* IFBUpdate::getObject(const int& width, const int& dpy) {
+    if(width > MAX_DISPLAY_DIM) {
+        return new FBUpdateHighRes(dpy);
+    }
+    return new FBUpdateLowRes(dpy);
 }
 
-bool FBUpdate::prepare(hwc_context_t *ctx, hwc_layer_1_t *fblayer, int dpy) {
+inline void IFBUpdate::reset() {
+    mModeOn = false;
+}
+
+//================= Low res====================================
+FBUpdateLowRes::FBUpdateLowRes(const int& dpy): IFBUpdate(dpy) {}
+
+inline void FBUpdateLowRes::reset() {
+    IFBUpdate::reset();
+    mDest = ovutils::OV_INVALID;
+}
+
+bool FBUpdateLowRes::prepare(hwc_context_t *ctx, hwc_layer_1_t *fblayer) {
     if(!ctx->mMDP.hasOverlay) {
-        ALOGD_IF(HWC_FB_UPDATE, "%s, this hw doesnt support mirroring",
+        ALOGD_IF(DEBUG_FBUPDATE, "%s, this hw doesnt support overlays",
                 __FUNCTION__);
        return false;
     }
-
-    return (sModeOn[dpy] = configure(ctx, fblayer, dpy));
-
+    mModeOn = configure(ctx, fblayer);
+    ALOGD_IF(DEBUG_FBUPDATE, "%s, mModeOn = %d", __FUNCTION__, mModeOn);
+    return mModeOn;
 }
 
 // Configure
-bool FBUpdate::configure(hwc_context_t *ctx, hwc_layer_1_t *layer, int dpy)
+bool FBUpdateLowRes::configure(hwc_context_t *ctx, hwc_layer_1_t *layer)
 {
     bool ret = false;
     if (LIKELY(ctx->mOverlay)) {
@@ -64,12 +72,12 @@
         ovutils::Whf info(hnd->width, hnd->height, hnd->format, hnd->size);
 
         //Request an RGB pipe
-        ovutils::eDest dest = ov.nextPipe(ovutils::OV_MDP_PIPE_RGB, dpy);
+        ovutils::eDest dest = ov.nextPipe(ovutils::OV_MDP_PIPE_RGB, mDpy);
         if(dest == ovutils::OV_INVALID) { //None available
             return false;
         }
 
-        sDest[dpy] = dest;
+        mDest = dest;
 
         ovutils::eMdpFlags mdpFlags = ovutils::OV_MDP_FLAGS_NONE;
         if(ctx->mSecureMode) {
@@ -112,14 +120,14 @@
     return ret;
 }
 
-bool FBUpdate::draw(hwc_context_t *ctx, hwc_layer_1_t *layer, int dpy)
+bool FBUpdateLowRes::draw(hwc_context_t *ctx, hwc_layer_1_t *layer)
 {
-    if(!sModeOn[dpy]) {
+    if(!mModeOn) {
         return true;
     }
     bool ret = true;
     overlay::Overlay& ov = *(ctx->mOverlay);
-    ovutils::eDest dest = sDest[dpy];
+    ovutils::eDest dest = mDest;
     private_handle_t *hnd = (private_handle_t *)layer->handle;
     if (!ov.queueBuffer(hnd->fd, hnd->offset, dest)) {
         ALOGE("%s: queueBuffer failed for external", __FUNCTION__);
@@ -128,5 +136,138 @@
     return ret;
 }
 
+//================= High res====================================
+FBUpdateHighRes::FBUpdateHighRes(const int& dpy): IFBUpdate(dpy) {}
+
+inline void FBUpdateHighRes::reset() {
+    IFBUpdate::reset();
+    mDestLeft = ovutils::OV_INVALID;
+    mDestRight = ovutils::OV_INVALID;
+}
+
+bool FBUpdateHighRes::prepare(hwc_context_t *ctx, hwc_layer_1_t *fblayer) {
+    if(!ctx->mMDP.hasOverlay) {
+        ALOGD_IF(DEBUG_FBUPDATE, "%s, this hw doesnt support overlays",
+                __FUNCTION__);
+       return false;
+    }
+    ALOGD_IF(DEBUG_FBUPDATE, "%s, mModeOn = %d", __FUNCTION__, mModeOn);
+    mModeOn = configure(ctx, fblayer);
+    return mModeOn;
+}
+
+// Configure
+bool FBUpdateHighRes::configure(hwc_context_t *ctx, hwc_layer_1_t *layer)
+{
+    bool ret = false;
+    if (LIKELY(ctx->mOverlay)) {
+        overlay::Overlay& ov = *(ctx->mOverlay);
+        private_handle_t *hnd = (private_handle_t *)layer->handle;
+        if (!hnd) {
+            ALOGE("%s:NULL private handle for layer!", __FUNCTION__);
+            return false;
+        }
+        ovutils::Whf info(hnd->width, hnd->height, hnd->format, hnd->size);
+
+        //Request left RGB pipe
+        ovutils::eDest destL = ov.nextPipe(ovutils::OV_MDP_PIPE_RGB, mDpy);
+        if(destL == ovutils::OV_INVALID) { //None available
+            return false;
+        }
+        //Request right RGB pipe
+        ovutils::eDest destR = ov.nextPipe(ovutils::OV_MDP_PIPE_RGB, mDpy);
+        if(destR == ovutils::OV_INVALID) { //None available
+            return false;
+        }
+
+        mDestLeft = destL;
+        mDestRight = destR;
+
+        ovutils::eMdpFlags mdpFlagsL = ovutils::OV_MDP_FLAGS_NONE;
+        if(ctx->mSecureMode) {
+            ovutils::setMdpFlags(mdpFlagsL,
+                    ovutils::OV_MDP_SECURE_OVERLAY_SESSION);
+        }
+
+        ovutils::PipeArgs pargL(mdpFlagsL,
+                info,
+                ovutils::ZORDER_0,
+                ovutils::IS_FG_SET,
+                ovutils::ROT_FLAG_DISABLED);
+        ov.setSource(pargL, destL);
+
+        ovutils::eMdpFlags mdpFlagsR = mdpFlagsL;
+        ovutils::setMdpFlags(mdpFlagsR, ovutils::OV_MDSS_MDP_RIGHT_MIXER);
+        ovutils::PipeArgs pargR(mdpFlagsR,
+                info,
+                ovutils::ZORDER_0,
+                ovutils::IS_FG_SET,
+                ovutils::ROT_FLAG_DISABLED);
+        ov.setSource(pargR, destR);
+
+        hwc_rect_t sourceCrop = layer->sourceCrop;
+        ovutils::Dim dcropL(sourceCrop.left, sourceCrop.top,
+                (sourceCrop.right - sourceCrop.left) / 2,
+                sourceCrop.bottom - sourceCrop.top);
+        ovutils::Dim dcropR(
+                sourceCrop.left + (sourceCrop.right - sourceCrop.left) / 2,
+                sourceCrop.top,
+                (sourceCrop.right - sourceCrop.left) / 2,
+                sourceCrop.bottom - sourceCrop.top);
+        ov.setCrop(dcropL, destL);
+        ov.setCrop(dcropR, destR);
+
+        int transform = layer->transform;
+        ovutils::eTransform orient =
+                static_cast<ovutils::eTransform>(transform);
+        ov.setTransform(orient, destL);
+        ov.setTransform(orient, destR);
+
+        hwc_rect_t displayFrame = layer->displayFrame;
+        //For FB left, top will always be 0
+        //That should also be the case if using 2 mixers for single display
+        ovutils::Dim dpos(displayFrame.left,
+                displayFrame.top,
+                (displayFrame.right - displayFrame.left) / 2,
+                displayFrame.bottom - displayFrame.top);
+        ov.setPosition(dpos, destL);
+        ov.setPosition(dpos, destR);
+
+        ret = true;
+        if (!ov.commit(destL)) {
+            ALOGE("%s: commit fails for left", __FUNCTION__);
+            ret = false;
+        }
+        if (!ov.commit(destR)) {
+            ALOGE("%s: commit fails for right", __FUNCTION__);
+            ret = false;
+        }
+    }
+    return ret;
+}
+
+bool FBUpdateHighRes::draw(hwc_context_t *ctx, hwc_layer_1_t *layer)
+{
+    if(!mModeOn) {
+        return true;
+    }
+    bool ret = true;
+    overlay::Overlay& ov = *(ctx->mOverlay);
+    ovutils::eDest destL = mDestLeft;
+    ovutils::eDest destR = mDestRight;
+    private_handle_t *hnd = (private_handle_t *)layer->handle;
+    if (!ov.queueBuffer(hnd->fd, hnd->offset, destL)) {
+        ALOGE("%s: queue failed for left of dpy = %d",
+                __FUNCTION__, mDpy);
+        ret = false;
+    }
+    if (!ov.queueBuffer(hnd->fd, hnd->offset, destR)) {
+        ALOGE("%s: queue failed for right of dpy = %d",
+                __FUNCTION__, mDpy);
+        ret = false;
+    }
+    return ret;
+}
+
 //---------------------------------------------------------------------
 }; //namespace qhwc
diff --git a/libhwcomposer/hwc_fbupdate.h b/libhwcomposer/hwc_fbupdate.h
index 708eb6f..a30a3af 100644
--- a/libhwcomposer/hwc_fbupdate.h
+++ b/libhwcomposer/hwc_fbupdate.h
@@ -28,22 +28,50 @@
 namespace qhwc {
 namespace ovutils = overlay::utils;
 
-//Framebuffer update
-class FBUpdate {
-    public:
-        // Sets up members and prepares overlay if conditions are met
-        static bool prepare(hwc_context_t *ctx, hwc_layer_1_t *fblayer, int dpy);
-        // Draws layer if this feature is on
-        static bool draw(hwc_context_t *ctx, hwc_layer_1_t *fblayer, int dpy);
-        //Reset values
-        static void reset();
-    private:
-        //Configures overlay
-        static bool configure(hwc_context_t *ctx, hwc_layer_1_t *fblayer,
-            int dpy);
-        //Flags if this feature is on.
-        static bool sModeOn[HWC_NUM_DISPLAY_TYPES];
-        static ovutils::eDest sDest[HWC_NUM_DISPLAY_TYPES];
+//Framebuffer update Interface
+class IFBUpdate {
+public:
+    explicit IFBUpdate(const int& dpy) : mDpy(dpy) {}
+    virtual ~IFBUpdate() {};
+    // Sets up members and prepares overlay if conditions are met
+    virtual bool prepare(hwc_context_t *ctx, hwc_layer_1_t *fblayer) = 0;
+    // Draws layer
+    virtual bool draw(hwc_context_t *ctx, hwc_layer_1_t *fblayer) = 0;
+    //Reset values
+    virtual void reset();
+    //Factory method that returns a low-res or high-res version
+    static IFBUpdate *getObject(const int& width, const int& dpy);
+
+protected:
+    const int mDpy; // display to update
+    bool mModeOn; // if prepare happened
+};
+
+//Low resolution (<= 2048) panel handler.
+class FBUpdateLowRes : public IFBUpdate {
+public:
+    explicit FBUpdateLowRes(const int& dpy);
+    virtual ~FBUpdateLowRes() {};
+    bool prepare(hwc_context_t *ctx, hwc_layer_1_t *fblayer);
+    bool draw(hwc_context_t *ctx, hwc_layer_1_t *fblayer);
+    void reset();
+private:
+    bool configure(hwc_context_t *ctx, hwc_layer_1_t *fblayer);
+    ovutils::eDest mDest; //pipe to draw on
+};
+
+//High resolution (> 2048) panel handler.
+class FBUpdateHighRes : public IFBUpdate {
+public:
+    explicit FBUpdateHighRes(const int& dpy);
+    virtual ~FBUpdateHighRes() {};
+    bool prepare(hwc_context_t *ctx, hwc_layer_1_t *fblayer);
+    bool draw(hwc_context_t *ctx, hwc_layer_1_t *fblayer);
+    void reset();
+private:
+    bool configure(hwc_context_t *ctx, hwc_layer_1_t *fblayer);
+    ovutils::eDest mDestLeft; //left pipe to draw on
+    ovutils::eDest mDestRight; //right pipe to draw on
 };
 
 }; //namespace qhwc
diff --git a/libhwcomposer/hwc_mdpcomp.cpp b/libhwcomposer/hwc_mdpcomp.cpp
index 4200be9..2c0a77a 100644
--- a/libhwcomposer/hwc_mdpcomp.cpp
+++ b/libhwcomposer/hwc_mdpcomp.cpp
@@ -19,32 +19,74 @@
 #include "hwc_mdpcomp.h"
 #include <sys/ioctl.h>
 #include "external.h"
+#include "qdMetaData.h"
 
 namespace qhwc {
 
 namespace ovutils = overlay::utils;
-/****** Class MDPComp ***********/
 
-MDPComp::eState MDPComp::sMDPCompState = MDPCOMP_OFF;
-struct MDPComp::FrameInfo MDPComp::sCurrentFrame;
+//==============MDPComp========================================================
+
 IdleInvalidator *MDPComp::idleInvalidator = NULL;
 bool MDPComp::sIdleFallBack = false;
 bool MDPComp::sDebugLogs = false;
 bool MDPComp::sEnabled = false;
-int MDPComp::sActiveMax = 0;
-bool MDPComp::sSecuredVid = false;
 
-bool MDPComp::deinit() {
-    //XXX: Tear down MDP comp state
+MDPComp* MDPComp::getObject(const int& width) {
+    //For now. Later check for width > 2048
+    return new MDPCompLowRes();
+}
+
+void MDPComp::dump(android::String8& buf)
+{
+    dumpsys_log(buf, "  MDP Composition: ");
+    dumpsys_log(buf, "MDPCompState=%d\n", mState);
+    //XXX: Log more info
+}
+
+bool MDPComp::init(hwc_context_t *ctx) {
+
+    if(!ctx) {
+        ALOGE("%s: Invalid hwc context!!",__FUNCTION__);
+        return false;
+    }
+
+    if(!setupBasePipe(ctx)) {
+        ALOGE("%s: Failed to setup primary base pipe", __FUNCTION__);
+        return false;
+    }
+
+    char property[PROPERTY_VALUE_MAX];
+
+    sEnabled = false;
+    if((property_get("persist.hwc.mdpcomp.enable", property, NULL) > 0) &&
+            (!strncmp(property, "1", PROPERTY_VALUE_MAX ) ||
+             (!strncasecmp(property,"true", PROPERTY_VALUE_MAX )))) {
+        sEnabled = true;
+    }
+
+    sDebugLogs = false;
+    if(property_get("debug.mdpcomp.logs", property, NULL) > 0) {
+        if(atoi(property) != 0)
+            sDebugLogs = true;
+    }
+
+    unsigned long idle_timeout = DEFAULT_IDLE_TIME;
+    if(property_get("debug.mdpcomp.idletime", property, NULL) > 0) {
+        if(atoi(property) != 0)
+            idle_timeout = atoi(property);
+    }
+
+    //create Idle Invalidator
+    idleInvalidator = IdleInvalidator::getInstance();
+
+    if(idleInvalidator == NULL) {
+        ALOGE("%s: failed to instantiate idleInvalidator  object", __FUNCTION__);
+    } else {
+        idleInvalidator->init(timeout_handler, ctx, idle_timeout);
+    }
     return true;
 }
-bool MDPComp::isSkipPresent (hwc_context_t *ctx) {
-    return  ctx->listStats[HWC_DISPLAY_PRIMARY].skipCount;
-};
-
-bool MDPComp::isYuvPresent (hwc_context_t *ctx) {
-    return  ctx->listStats[HWC_DISPLAY_PRIMARY].yuvCount;
-};
 
 void MDPComp::timeout_handler(void *udata) {
     struct hwc_context_t* ctx = (struct hwc_context_t*)(udata);
@@ -63,179 +105,249 @@
     ctx->proc->invalidate(ctx->proc);
 }
 
-void MDPComp::reset(hwc_context_t *ctx, hwc_display_contents_1_t* list ) {
-    //Reset flags and states
-    unsetMDPCompLayerFlags(ctx, list);
-    sCurrentFrame.count = 0;
-    if(sCurrentFrame.pipeLayer) {
-        free(sCurrentFrame.pipeLayer);
-        sCurrentFrame.pipeLayer = NULL;
+void MDPComp::setMDPCompLayerFlags(hwc_context_t *ctx,
+        hwc_display_contents_1_t* list) {
+    const int dpy = HWC_DISPLAY_PRIMARY;
+    LayerProp *layerProp = ctx->layerProp[dpy];
+
+    for(int index = 0; index < ctx->listStats[dpy].numAppLayers; index++ ) {
+        hwc_layer_1_t* layer = &(list->hwLayers[index]);
+        layerProp[index].mFlags |= HWC_MDPCOMP;
+        layer->compositionType = HWC_OVERLAY;
+        layer->hints |= HWC_HINT_CLEAR_FB;
     }
 }
 
-void MDPComp::print_info(hwc_layer_1_t* layer)
-{
-     hwc_rect_t sourceCrop = layer->sourceCrop;
-     hwc_rect_t displayFrame = layer->displayFrame;
+void MDPComp::unsetMDPCompLayerFlags(hwc_context_t* ctx,
+        hwc_display_contents_1_t* list) {
+    const int dpy = HWC_DISPLAY_PRIMARY;
+    LayerProp *layerProp = ctx->layerProp[dpy];
 
-     int s_l = sourceCrop.left;
-     int s_t = sourceCrop.top;
-     int s_r = sourceCrop.right;
-     int s_b = sourceCrop.bottom;
+    for (int index = 0 ;
+            index < ctx->listStats[dpy].numAppLayers; index++) {
+        if(layerProp[index].mFlags & HWC_MDPCOMP) {
+            layerProp[index].mFlags &= ~HWC_MDPCOMP;
+        }
 
-     int d_l = displayFrame.left;
-     int d_t = displayFrame.top;
-     int d_r = displayFrame.right;
-     int d_b = displayFrame.bottom;
-
-     ALOGD_IF(isDebug(), "src:[%d,%d,%d,%d] (%d x %d) \
-                             dst:[%d,%d,%d,%d] (%d x %d)",
-                             s_l, s_t, s_r, s_b, (s_r - s_l), (s_b - s_t),
-                             d_l, d_t, d_r, d_b, (d_r - d_l), (d_b - d_t));
+        if(list->hwLayers[index].compositionType == HWC_OVERLAY) {
+            list->hwLayers[index].compositionType = HWC_FRAMEBUFFER;
+        }
+    }
 }
 
-void MDPComp::setVidInfo(hwc_layer_1_t *layer, ovutils::eMdpFlags &mdpFlags) {
+/*
+ * Sets up BORDERFILL as default base pipe and detaches RGB0.
+ * Framebuffer is always updated using PLAY ioctl.
+ */
+bool MDPComp::setupBasePipe(hwc_context_t *ctx) {
+    const int dpy = HWC_DISPLAY_PRIMARY;
+    int fb_stride = ctx->dpyAttr[dpy].stride;
+    int fb_width = ctx->dpyAttr[dpy].xres;
+    int fb_height = ctx->dpyAttr[dpy].yres;
+    int fb_fd = ctx->dpyAttr[dpy].fd;
+
+    mdp_overlay ovInfo;
+    msmfb_overlay_data ovData;
+    memset(&ovInfo, 0, sizeof(mdp_overlay));
+    memset(&ovData, 0, sizeof(msmfb_overlay_data));
+
+    ovInfo.src.format = MDP_RGB_BORDERFILL;
+    ovInfo.src.width  = fb_width;
+    ovInfo.src.height = fb_height;
+    ovInfo.src_rect.w = fb_width;
+    ovInfo.src_rect.h = fb_height;
+    ovInfo.dst_rect.w = fb_width;
+    ovInfo.dst_rect.h = fb_height;
+    ovInfo.id = MSMFB_NEW_REQUEST;
+
+    if (ioctl(fb_fd, MSMFB_OVERLAY_SET, &ovInfo) < 0) {
+        ALOGE("Failed to call ioctl MSMFB_OVERLAY_SET err=%s",
+                strerror(errno));
+        return false;
+    }
+
+    ovData.id = ovInfo.id;
+    if (ioctl(fb_fd, MSMFB_OVERLAY_PLAY, &ovData) < 0) {
+        ALOGE("Failed to call ioctl MSMFB_OVERLAY_PLAY err=%s",
+                strerror(errno));
+        return false;
+    }
+    return true;
+}
+
+void MDPComp::printInfo(hwc_layer_1_t* layer) {
+    hwc_rect_t sourceCrop = layer->sourceCrop;
+    hwc_rect_t displayFrame = layer->displayFrame;
+
+    int s_l = sourceCrop.left;
+    int s_t = sourceCrop.top;
+    int s_r = sourceCrop.right;
+    int s_b = sourceCrop.bottom;
+
+    int d_l = displayFrame.left;
+    int d_t = displayFrame.top;
+    int d_r = displayFrame.right;
+    int d_b = displayFrame.bottom;
+
+    ALOGD_IF(isDebug(), "src:[%d,%d,%d,%d] (%d x %d) \
+            dst:[%d,%d,%d,%d] (%d x %d)",
+            s_l, s_t, s_r, s_b, (s_r - s_l), (s_b - s_t),
+            d_l, d_t, d_r, d_b, (d_r - d_l), (d_b - d_t));
+}
+
+//=============MDPCompLowRes===================================================
+void MDPCompLowRes::reset(hwc_context_t *ctx,
+        hwc_display_contents_1_t* list ) {
+    //Reset flags and states
+    unsetMDPCompLayerFlags(ctx, list);
+    mCurrentFrame.count = 0;
+    if(mCurrentFrame.pipeLayer) {
+        free(mCurrentFrame.pipeLayer);
+        mCurrentFrame.pipeLayer = NULL;
+    }
+}
+
+void MDPCompLowRes::setVidInfo(hwc_layer_1_t *layer,
+        ovutils::eMdpFlags &mdpFlags) {
     private_handle_t *hnd = (private_handle_t *)layer->handle;
+    MetaData_t *metadata = (MetaData_t *)hnd->base_metadata;
 
     if(isSecureBuffer(hnd)) {
         ovutils::setMdpFlags(mdpFlags, ovutils::OV_MDP_SECURE_OVERLAY_SESSION);
-        sSecuredVid = true;
+    }
+    if((metadata->operation & PP_PARAM_INTERLACED) && metadata->interlaced) {
+        ovutils::setMdpFlags(mdpFlags, ovutils::OV_MDP_DEINTERLACE);
     }
 }
 
 /*
  * Configures pipe(s) for MDP composition
  */
-int MDPComp::prepare(hwc_context_t *ctx, hwc_layer_1_t *layer,
-                                            MdpPipeInfo& mdp_info) {
-
+int MDPCompLowRes::configure(hwc_context_t *ctx, hwc_layer_1_t *layer,
+        MdpPipeInfo& mdp_info) {
     int nPipeIndex = mdp_info.index;
+    const int dpy = HWC_DISPLAY_PRIMARY;
+    private_handle_t *hnd = (private_handle_t *)layer->handle;
+    overlay::Overlay& ov = *ctx->mOverlay;
 
-    if (ctx) {
+    if(!hnd) {
+        ALOGE("%s: layer handle is NULL", __FUNCTION__);
+        return -1;
+    }
 
-        private_handle_t *hnd = (private_handle_t *)layer->handle;
+    int hw_w = ctx->dpyAttr[dpy].xres;
+    int hw_h = ctx->dpyAttr[dpy].yres;
 
-        overlay::Overlay& ov = *ctx->mOverlay;
+    hwc_rect_t sourceCrop = layer->sourceCrop;
+    hwc_rect_t displayFrame = layer->displayFrame;
 
-        if(!hnd) {
-            ALOGE("%s: layer handle is NULL", __FUNCTION__);
-            return -1;
+    const int src_w = sourceCrop.right - sourceCrop.left;
+    const int src_h = sourceCrop.bottom - sourceCrop.top;
+
+    hwc_rect_t crop = sourceCrop;
+    int crop_w = crop.right - crop.left;
+    int crop_h = crop.bottom - crop.top;
+
+    hwc_rect_t dst = displayFrame;
+    int dst_w = dst.right - dst.left;
+    int dst_h = dst.bottom - dst.top;
+
+    if(dst.left < 0 || dst.top < 0 ||
+            dst.right > hw_w || dst.bottom > hw_h) {
+        ALOGD_IF(isDebug(),"%s: Destination has negative coordinates",
+                __FUNCTION__);
+        qhwc::calculate_crop_rects(crop, dst, hw_w, hw_h, 0);
+
+        //Update calulated width and height
+        crop_w = crop.right - crop.left;
+        crop_h = crop.bottom - crop.top;
+
+        dst_w = dst.right - dst.left;
+        dst_h = dst.bottom - dst.top;
+    }
+
+    if( (dst_w > hw_w)|| (dst_h > hw_h)) {
+        ALOGD_IF(isDebug(),"%s: Dest rect exceeds FB", __FUNCTION__);
+        printInfo(layer);
+        dst_w = hw_w;
+        dst_h = hw_h;
+    }
+
+    // Determine pipe to set based on pipe index
+    ovutils::eDest dest = (ovutils::eDest)mdp_info.index;
+
+    ovutils::eZorder zOrder = ovutils::ZORDER_0;
+
+    if(mdp_info.zOrder == 0 ) {
+        zOrder = ovutils::ZORDER_0;
+    } else if(mdp_info.zOrder == 1 ) {
+        zOrder = ovutils::ZORDER_1;
+    } else if(mdp_info.zOrder == 2 ) {
+        zOrder = ovutils::ZORDER_2;
+    } else if(mdp_info.zOrder == 3) {
+        zOrder = ovutils::ZORDER_3;
+    }
+
+    // Order order order
+    // setSource - just setting source
+    // setParameter - changes src w/h/f accordingly
+    // setCrop - ROI - src_rect
+    // setPosition - dst_rect
+    // commit - commit changes to mdp driver
+    // queueBuffer - not here, happens when draw is called
+
+    ovutils::Whf info(hnd->width, hnd->height, hnd->format, hnd->size);
+
+    ovutils::eMdpFlags mdpFlags = ovutils::OV_MDP_FLAGS_NONE;
+
+    if(isYuvBuffer(hnd))
+        setVidInfo(layer, mdpFlags);
+
+    ovutils::setMdpFlags(mdpFlags,ovutils::OV_MDP_BACKEND_COMPOSITION);
+
+    if(layer->blending == HWC_BLENDING_PREMULT) {
+        ovutils::setMdpFlags(mdpFlags,
+                ovutils::OV_MDP_BLEND_FG_PREMULT);
+    }
+
+    ovutils::eTransform orient = overlay::utils::OVERLAY_TRANSFORM_0 ;
+
+    if(!(layer->transform & HWC_TRANSFORM_ROT_90)) {
+        if(layer->transform & HWC_TRANSFORM_FLIP_H) {
+            ovutils::setMdpFlags(mdpFlags, ovutils::OV_MDP_FLIP_H);
         }
 
-        int hw_w = ctx->dpyAttr[HWC_DISPLAY_PRIMARY].xres;
-        int hw_h = ctx->dpyAttr[HWC_DISPLAY_PRIMARY].yres;
-
-        hwc_rect_t sourceCrop = layer->sourceCrop;
-        hwc_rect_t displayFrame = layer->displayFrame;
-
-        const int src_w = sourceCrop.right - sourceCrop.left;
-        const int src_h = sourceCrop.bottom - sourceCrop.top;
-
-        hwc_rect_t crop = sourceCrop;
-        int crop_w = crop.right - crop.left;
-        int crop_h = crop.bottom - crop.top;
-
-        hwc_rect_t dst = displayFrame;
-        int dst_w = dst.right - dst.left;
-        int dst_h = dst.bottom - dst.top;
-
-        if(dst.left < 0 || dst.top < 0 ||
-               dst.right > hw_w || dst.bottom > hw_h) {
-            ALOGD_IF(isDebug(),"%s: Destination has negative coordinates",
-                                                                  __FUNCTION__);
-            qhwc::calculate_crop_rects(crop, dst, hw_w, hw_h, 0);
-
-            //Update calulated width and height
-            crop_w = crop.right - crop.left;
-            crop_h = crop.bottom - crop.top;
-
-            dst_w = dst.right - dst.left;
-            dst_h = dst.bottom - dst.top;
+        if(layer->transform & HWC_TRANSFORM_FLIP_V) {
+            ovutils::setMdpFlags(mdpFlags,  ovutils::OV_MDP_FLIP_V);
         }
+    } else {
+        orient = static_cast<ovutils::eTransform>(layer->transform);
+    }
 
-        if( (dst_w > hw_w)|| (dst_h > hw_h)) {
-            ALOGD_IF(isDebug(),"%s: Dest rect exceeds FB", __FUNCTION__);
-            print_info(layer);
-            dst_w = hw_w;
-            dst_h = hw_h;
-        }
+    ovutils::PipeArgs parg(mdpFlags,
+            info,
+            zOrder,
+            ovutils::IS_FG_OFF,
+            ovutils::ROT_FLAG_DISABLED);
 
-        // Determine pipe to set based on pipe index
-        ovutils::eDest dest = (ovutils::eDest)mdp_info.index;
+    ov.setSource(parg, dest);
 
-        ovutils::eZorder zOrder = ovutils::ZORDER_0;
+    ov.setTransform(orient, dest);
 
-        if(mdp_info.zOrder == 0 ) {
-            zOrder = ovutils::ZORDER_0;
-        } else if(mdp_info.zOrder == 1 ) {
-            zOrder = ovutils::ZORDER_1;
-        } else if(mdp_info.zOrder == 2 ) {
-            zOrder = ovutils::ZORDER_2;
-        } else if(mdp_info.zOrder == 3) {
-            zOrder = ovutils::ZORDER_3;
-        }
+    ovutils::Dim dcrop(crop.left, crop.top, crop_w, crop_h);
+    ov.setCrop(dcrop, dest);
 
-        // Order order order
-        // setSource - just setting source
-        // setParameter - changes src w/h/f accordingly
-        // setCrop - ROI - src_rect
-        // setPosition - dst_rect
-        // commit - commit changes to mdp driver
-        // queueBuffer - not here, happens when draw is called
+    ovutils::Dim dim(dst.left, dst.top, dst_w, dst_h);
+    ov.setPosition(dim, dest);
 
-        ovutils::Whf info(hnd->width, hnd->height, hnd->format, hnd->size);
+    ALOGD_IF(isDebug(),"%s: MDP set: crop[%d,%d,%d,%d] dst[%d,%d,%d,%d] \
+            nPipe: %d zorder: %d",__FUNCTION__, dcrop.x,
+            dcrop.y,dcrop.w, dcrop.h, dim.x, dim.y, dim.w, dim.h,
+            mdp_info.index, mdp_info.zOrder);
 
-        ovutils::eMdpFlags mdpFlags = ovutils::OV_MDP_FLAGS_NONE;
-
-        if(isYuvBuffer(hnd))
-            setVidInfo(layer, mdpFlags);
-
-        ovutils::setMdpFlags(mdpFlags,ovutils::OV_MDP_BACKEND_COMPOSITION);
-
-        if(layer->blending == HWC_BLENDING_PREMULT) {
-            ovutils::setMdpFlags(mdpFlags,
-                    ovutils::OV_MDP_BLEND_FG_PREMULT);
-        }
-
-        ovutils::eTransform orient = overlay::utils::OVERLAY_TRANSFORM_0 ;
-
-        if(!(layer->transform & HWC_TRANSFORM_ROT_90)) {
-            if(layer->transform & HWC_TRANSFORM_FLIP_H) {
-                ovutils::setMdpFlags(mdpFlags, ovutils::OV_MDP_FLIP_H);
-            }
-
-            if(layer->transform & HWC_TRANSFORM_FLIP_V) {
-                ovutils::setMdpFlags(mdpFlags,  ovutils::OV_MDP_FLIP_V);
-            }
-        } else {
-            orient = static_cast<ovutils::eTransform>(layer->transform);
-        }
-
-        ovutils::PipeArgs parg(mdpFlags,
-                               info,
-                               zOrder,
-                               ovutils::IS_FG_OFF,
-                               ovutils::ROT_FLAG_DISABLED);
-
-        ov.setSource(parg, dest);
-
-        ov.setTransform(orient, dest);
-
-        ovutils::Dim dcrop(crop.left, crop.top, crop_w, crop_h);
-        ov.setCrop(dcrop, dest);
-
-        ovutils::Dim dim(dst.left, dst.top, dst_w, dst_h);
-        ov.setPosition(dim, dest);
-
-        ALOGD_IF(isDebug(),"%s: MDP set: crop[%d,%d,%d,%d] dst[%d,%d,%d,%d] \
-                       nPipe: %d zorder: %d",__FUNCTION__, dcrop.x,
-                       dcrop.y,dcrop.w, dcrop.h, dim.x, dim.y, dim.w, dim.h,
-                       mdp_info.index, mdp_info.zOrder);
-
-        if (!ov.commit(dest)) {
-            ALOGE("%s: commit failed", __FUNCTION__);
-            return -1;
-        }
+    if (!ov.commit(dest)) {
+        ALOGE("%s: commit failed", __FUNCTION__);
+        return -1;
     }
     return 0;
 }
@@ -250,15 +362,26 @@
  * 5. Overlay in use
  */
 
-bool MDPComp::isDoable(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
+bool MDPCompLowRes::isDoable(hwc_context_t *ctx,
+        hwc_display_contents_1_t* list) {
     //Number of layers
-    int numAppLayers = ctx->listStats[HWC_DISPLAY_PRIMARY].numAppLayers;
+    const int dpy = HWC_DISPLAY_PRIMARY;
+    int numAppLayers = ctx->listStats[dpy].numAppLayers;
 
-    if(numAppLayers < 1 || numAppLayers > (uint32_t)sActiveMax) {
+    overlay::Overlay& ov = *ctx->mOverlay;
+    int availablePipes = ov.availablePipes(dpy);
+
+    if(numAppLayers < 1 || numAppLayers > (uint32_t)availablePipes) {
         ALOGD_IF(isDebug(), "%s: Unsupported number of layers",__FUNCTION__);
         return false;
     }
 
+    if(ctx->mExtDispConfiguring) {
+        ALOGD_IF( isDebug(),"%s: External Display connection is pending",
+                __FUNCTION__);
+        return false;
+    }
+
     if(isSecuring(ctx)) {
         ALOGD_IF(isDebug(), "%s: MDP securing is active", __FUNCTION__);
         return false;
@@ -268,12 +391,12 @@
         return false;
 
     //Check for skip layers
-    if(isSkipPresent(ctx)) {
+    if(isSkipPresent(ctx, dpy)) {
         ALOGD_IF(isDebug(), "%s: Skip layers are present",__FUNCTION__);
         return false;
     }
 
-    if(ctx->listStats[HWC_DISPLAY_PRIMARY].needsAlphaScale) {
+    if(ctx->listStats[dpy].needsAlphaScale) {
         ALOGD_IF(isDebug(), "%s: frame needs alpha downscaling",__FUNCTION__);
         return false;
     }
@@ -299,75 +422,62 @@
     return true;
 }
 
-void MDPComp::setMDPCompLayerFlags(hwc_context_t *ctx,
-                                hwc_display_contents_1_t* list) {
-    LayerProp *layerProp = ctx->layerProp[HWC_DISPLAY_PRIMARY];
-
-    for(int index = 0 ; index < sCurrentFrame.count; index++ ) {
-        hwc_layer_1_t* layer = &(list->hwLayers[index]);
-        layerProp[index].mFlags |= HWC_MDPCOMP;
-        layer->compositionType = HWC_OVERLAY;
-        layer->hints |= HWC_HINT_CLEAR_FB;
-    }
-}
-
-int MDPComp::getMdpPipe(hwc_context_t *ctx, ePipeType type){
+int MDPCompLowRes::getMdpPipe(hwc_context_t *ctx, ePipeType type) {
+    const int dpy = HWC_DISPLAY_PRIMARY;
     overlay::Overlay& ov = *ctx->mOverlay;
     int mdp_pipe = -1;
 
     switch(type) {
-    case MDPCOMP_OV_ANY:
-    case MDPCOMP_OV_RGB:
-        mdp_pipe = ov.nextPipe(ovutils::OV_MDP_PIPE_RGB, HWC_DISPLAY_PRIMARY);
-        if(mdp_pipe != ovutils::OV_INVALID) {
-            return mdp_pipe;
-        }
+        case MDPCOMP_OV_ANY:
+        case MDPCOMP_OV_RGB:
+            mdp_pipe = ov.nextPipe(ovutils::OV_MDP_PIPE_RGB, dpy);
+            if(mdp_pipe != ovutils::OV_INVALID) {
+                return mdp_pipe;
+            }
 
-        if(type == MDPCOMP_OV_RGB) {
-            //Requested only for RGB pipe
+            if(type == MDPCOMP_OV_RGB) {
+                //Requested only for RGB pipe
+                return -1;
+            }
+        case  MDPCOMP_OV_VG:
+            mdp_pipe = ov.nextPipe(ovutils::OV_MDP_PIPE_VG, dpy);
+            if(mdp_pipe != ovutils::OV_INVALID) {
+                return mdp_pipe;
+            }
             return -1;
-        }
-    case  MDPCOMP_OV_VG:
-        mdp_pipe = ov.nextPipe(ovutils::OV_MDP_PIPE_VG, HWC_DISPLAY_PRIMARY);
-        if(mdp_pipe != ovutils::OV_INVALID) {
-            return mdp_pipe;
-        }
-        return -1;
-    default:
-        ALOGE("%s: Invalid pipe type",__FUNCTION__);
-        return -1;
+        default:
+            ALOGE("%s: Invalid pipe type",__FUNCTION__);
+            return -1;
     };
 }
 
-bool MDPComp::allocLayerPipes(hwc_context_t *ctx,
+bool MDPCompLowRes::allocLayerPipes(hwc_context_t *ctx,
         hwc_display_contents_1_t* list,
         FrameInfo& currentFrame) {
-
+    const int dpy = HWC_DISPLAY_PRIMARY;
     overlay::Overlay& ov = *ctx->mOverlay;
-
-    int layer_count = ctx->listStats[HWC_DISPLAY_PRIMARY].numAppLayers;
+    int layer_count = ctx->listStats[dpy].numAppLayers;
 
     currentFrame.count = layer_count;
-
     currentFrame.pipeLayer = (PipeLayerPair*)
-                          malloc(sizeof(PipeLayerPair) * currentFrame.count);
+            malloc(sizeof(PipeLayerPair) * currentFrame.count);
 
-    if(isYuvPresent(ctx)) {
-        int nYuvIndex = ctx->listStats[HWC_DISPLAY_PRIMARY].yuvIndex;
+    if(isYuvPresent(ctx, dpy)) {
+        int nYuvIndex = ctx->listStats[dpy].yuvIndex;
         hwc_layer_1_t* layer = &list->hwLayers[nYuvIndex];
         PipeLayerPair& info = currentFrame.pipeLayer[nYuvIndex];
         MdpPipeInfo& pipe_info = info.pipeIndex;
         pipe_info.index = getMdpPipe(ctx, MDPCOMP_OV_VG);
         if(pipe_info.index < 0) {
             ALOGD_IF(isDebug(), "%s: Unable to get pipe for Videos",
-                                                          __FUNCTION__);
+                    __FUNCTION__);
             return false;
         }
         pipe_info.zOrder = nYuvIndex;
     }
 
     for(int index = 0 ; index < layer_count ; index++ ) {
-        if(index  == ctx->listStats[HWC_DISPLAY_PRIMARY].yuvIndex )
+        if(index  == ctx->listStats[dpy].yuvIndex )
             continue;
 
         hwc_layer_1_t* layer = &list->hwLayers[index];
@@ -383,11 +493,12 @@
     return true;
 }
 
-bool MDPComp::setup(hwc_context_t* ctx, hwc_display_contents_1_t* list) {
+bool MDPCompLowRes::setup(hwc_context_t* ctx, hwc_display_contents_1_t* list) {
+    const int dpy = HWC_DISPLAY_PRIMARY;
     int nPipeIndex, vsync_wait, isFG;
-    int numHwLayers = ctx->listStats[HWC_DISPLAY_PRIMARY].numAppLayers;
+    int numHwLayers = ctx->listStats[dpy].numAppLayers;
 
-    FrameInfo &currentFrame = sCurrentFrame;
+    FrameInfo &currentFrame = mCurrentFrame;
     currentFrame.count = 0;
 
     if(currentFrame.pipeLayer) {
@@ -396,8 +507,8 @@
     }
 
     if(!ctx) {
-       ALOGE("%s: invalid context", __FUNCTION__);
-       return -1;
+        ALOGE("%s: invalid context", __FUNCTION__);
+        return -1;
     }
 
     if(!allocLayerPipes(ctx, list, currentFrame)) {
@@ -417,39 +528,22 @@
         hwc_layer_1_t* layer = &list->hwLayers[index];
         MdpPipeInfo& cur_pipe = currentFrame.pipeLayer[index].pipeIndex;
 
-        if( prepare(ctx, layer, cur_pipe) != 0 ) {
-           ALOGD_IF(isDebug(), "%s: MDPComp failed to configure overlay for \
-                                    layer %d with pipe index:%d",__FUNCTION__,
-                                    index, cur_pipe.index);
-           return false;
-         }
+        if(configure(ctx, layer, cur_pipe) != 0 ) {
+            ALOGD_IF(isDebug(), "%s: MDPComp failed to configure overlay for \
+                    layer %d with pipe index:%d",__FUNCTION__,
+                    index, cur_pipe.index);
+            return false;
+        }
     }
     return true;
 }
 
-void MDPComp::unsetMDPCompLayerFlags(hwc_context_t* ctx,
-                                     hwc_display_contents_1_t* list)
-{
-    LayerProp *layerProp = ctx->layerProp[HWC_DISPLAY_PRIMARY];
-
-    for (int index = 0 ;
-         index < ctx->listStats[HWC_DISPLAY_PRIMARY].numAppLayers; index++) {
-        if(layerProp[index].mFlags & HWC_MDPCOMP) {
-            layerProp[index].mFlags &= ~HWC_MDPCOMP;
-        }
-
-        if(list->hwLayers[index].compositionType == HWC_OVERLAY) {
-            list->hwLayers[index].compositionType = HWC_FRAMEBUFFER;
-        }
-    }
-}
-
-bool MDPComp::draw(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
+bool MDPCompLowRes::draw(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
 
     if(!isEnabled() || !isUsed()) {
         ALOGD_IF(isDebug(),"%s: MDP Comp not configured", __FUNCTION__);
         return true;
-     }
+    }
 
     if(!ctx || !list) {
         ALOGE("%s: invalid contxt or list",__FUNCTION__);
@@ -460,10 +554,11 @@
     if(idleInvalidator)
         idleInvalidator->markForSleep();
 
+    const int dpy = HWC_DISPLAY_PRIMARY;
     overlay::Overlay& ov = *ctx->mOverlay;
-    LayerProp *layerProp = ctx->layerProp[HWC_DISPLAY_PRIMARY];
+    LayerProp *layerProp = ctx->layerProp[dpy];
 
-    int numHwLayers = ctx->listStats[HWC_DISPLAY_PRIMARY].numAppLayers;
+    int numHwLayers = ctx->listStats[dpy].numAppLayers;
     for(int i = 0; i < numHwLayers; i++ )
     {
         hwc_layer_1_t *layer = &list->hwLayers[i];
@@ -473,7 +568,7 @@
         }
 
         MdpPipeInfo& pipe_info =
-                        sCurrentFrame.pipeLayer[i].pipeIndex;
+                mCurrentFrame.pipeLayer[i].pipeIndex;
         int index = pipe_info.index;
 
         if(index < 0) {
@@ -491,8 +586,8 @@
             }
 
             ALOGD_IF(isDebug(),"%s: MDP Comp: Drawing layer: %p hnd: %p \
-                                 using  pipe: %d", __FUNCTION__, layer,
-                                 hnd, index );
+                    using  pipe: %d", __FUNCTION__, layer,
+                    hnd, index );
 
             if (!ov.queueBuffer(hnd->fd, hnd->offset, dest)) {
                 ALOGE("%s: queueBuffer failed for external", __FUNCTION__);
@@ -505,103 +600,14 @@
     return true;
 }
 
-/*
- * Sets up BORDERFILL as default base pipe and detaches RGB0.
- * Framebuffer is always updated using PLAY ioctl.
- */
-
-bool MDPComp::setupBasePipe(hwc_context_t *ctx) {
-
-    int fb_stride = ctx->dpyAttr[HWC_DISPLAY_PRIMARY].stride;
-    int fb_width = ctx->dpyAttr[HWC_DISPLAY_PRIMARY].xres;
-    int fb_height = ctx->dpyAttr[HWC_DISPLAY_PRIMARY].yres;
-    int fb_fd = ctx->dpyAttr[HWC_DISPLAY_PRIMARY].fd;
-
-    mdp_overlay ovInfo;
-    msmfb_overlay_data ovData;
-    memset(&ovInfo, 0, sizeof(mdp_overlay));
-    memset(&ovData, 0, sizeof(msmfb_overlay_data));
-
-    ovInfo.src.format = MDP_RGB_BORDERFILL;
-    ovInfo.src.width  = fb_width;
-    ovInfo.src.height = fb_height;
-    ovInfo.src_rect.w = fb_width;
-    ovInfo.src_rect.h = fb_height;
-    ovInfo.dst_rect.w = fb_width;
-    ovInfo.dst_rect.h = fb_height;
-    ovInfo.id = MSMFB_NEW_REQUEST;
-
-    if (ioctl(fb_fd, MSMFB_OVERLAY_SET, &ovInfo) < 0) {
-        ALOGE("Failed to call ioctl MSMFB_OVERLAY_SET err=%s",
-                  strerror(errno));
-        return false;
-    }
-
-    ovData.id = ovInfo.id;
-    if (ioctl(fb_fd, MSMFB_OVERLAY_PLAY, &ovData) < 0) {
-        ALOGE("Failed to call ioctl MSMFB_OVERLAY_PLAY err=%s",
-                   strerror(errno));
-        return false;
-    }
-    return true;
-}
-
-bool MDPComp::init(hwc_context_t *ctx) {
-
-    if(!ctx) {
-        ALOGE("%s: Invalid hwc context!!",__FUNCTION__);
-        return false;
-    }
-
-    if(!setupBasePipe(ctx)) {
-        ALOGE("%s: Failed to setup primary base pipe", __FUNCTION__);
-        return false;
-    }
-
-    char property[PROPERTY_VALUE_MAX];
-
-    sEnabled = false;
-    if((property_get("persist.hwc.mdpcomp.enable", property, NULL) > 0) &&
-                      (!strncmp(property, "1", PROPERTY_VALUE_MAX ) ||
-                      (!strncasecmp(property,"true", PROPERTY_VALUE_MAX )))) {
-           sEnabled = true;
-    }
-
-    sDebugLogs = false;
-    if(property_get("debug.mdpcomp.logs", property, NULL) > 0) {
-        if(atoi(property) != 0)
-           sDebugLogs = true;
-    }
-
-    unsigned long idle_timeout = DEFAULT_IDLE_TIME;
-    if(property_get("debug.mdpcomp.idletime", property, NULL) > 0) {
-        if(atoi(property) != 0)
-           idle_timeout = atoi(property);
-    }
-
-    //create Idle Invalidator
-    idleInvalidator = IdleInvalidator::getInstance();
-
-    if(idleInvalidator == NULL) {
-       ALOGE("%s: failed to instantiate idleInvalidator  object", __FUNCTION__);
-    } else {
-       idleInvalidator->init(timeout_handler, ctx, idle_timeout);
-    }
-    return true;
-}
-
-bool MDPComp::configure(hwc_context_t *ctx,
-                        hwc_display_contents_1_t* list) {
-
+bool MDPCompLowRes::prepare(hwc_context_t *ctx,
+        hwc_display_contents_1_t* list) {
     if(!isEnabled()) {
         ALOGE_IF(isDebug(),"%s: MDP Comp. not enabled.", __FUNCTION__);
         return false;
     }
 
     overlay::Overlay& ov = *ctx->mOverlay;
-
-    sActiveMax = ov.availablePipes();
-
     bool isMDPCompUsed = true;
     bool doable = isDoable(ctx, list);
 
@@ -612,31 +618,21 @@
             ALOGD_IF(isDebug(),"%s: MDP Comp Failed",__FUNCTION__);
             isMDPCompUsed = false;
         }
-     } else {
+    } else {
         ALOGD_IF( isDebug(),"%s: MDP Comp not possible[%d]",__FUNCTION__,
-                   doable);
+                doable);
         isMDPCompUsed = false;
-     }
+    }
 
-     //Reset states
-     if(!isMDPCompUsed) {
+    //Reset states
+    if(!isMDPCompUsed) {
         //Reset current frame
-         reset(ctx, list);
-     }
+        reset(ctx, list);
+    }
 
-     sMDPCompState = isMDPCompUsed ? MDPCOMP_ON : MDPCOMP_OFF;
-
-     return isMDPCompUsed;
+    mState = isMDPCompUsed ? MDPCOMP_ON : MDPCOMP_OFF;
+    return isMDPCompUsed;
 }
 
-void MDPComp::dump(android::String8& buf)
-{
-    dumpsys_log(buf, "  MDP Composition: ");
-    dumpsys_log(buf, "MDPCompState=%d\n", sMDPCompState);
-    //XXX: Log more info
-
-}
-
-
 }; //namespace
 
diff --git a/libhwcomposer/hwc_mdpcomp.h b/libhwcomposer/hwc_mdpcomp.h
index 6ff6385..4dc5878 100644
--- a/libhwcomposer/hwc_mdpcomp.h
+++ b/libhwcomposer/hwc_mdpcomp.h
@@ -30,6 +30,22 @@
 namespace ovutils = overlay::utils;
 
 class MDPComp {
+public:
+    virtual ~MDPComp() {}
+    /*sets up mdp comp for the current frame */
+    virtual bool prepare(hwc_context_t *ctx,
+            hwc_display_contents_1_t* list) = 0;
+    /* draw */
+    virtual bool draw(hwc_context_t *ctx, hwc_display_contents_1_t *list) = 0;
+    void dump(android::String8& buf);
+    bool isUsed() { return (mState == MDPCOMP_ON); };
+
+    static MDPComp* getObject(const int& width);
+    /* Handler to invoke frame redraw on Idle Timer expiry */
+    static void timeout_handler(void *udata);
+    static bool init(hwc_context_t *ctx);
+
+protected:
     enum eState {
         MDPCOMP_ON = 0,
         MDPCOMP_OFF,
@@ -41,6 +57,39 @@
         MDPCOMP_OV_ANY,
     };
 
+    /* set/reset flags for MDPComp */
+    void setMDPCompLayerFlags(hwc_context_t *ctx,
+                                       hwc_display_contents_1_t* list);
+    void unsetMDPCompLayerFlags(hwc_context_t* ctx,
+                                       hwc_display_contents_1_t* list);
+    void printInfo(hwc_layer_1_t* layer);
+    /* get/set states */
+    eState getState() { return mState; };
+
+    /* set up Border fill as Base pipe */
+    static bool setupBasePipe(hwc_context_t*);
+    /* Is debug enabled */
+    static bool isDebug() { return sDebugLogs ? true : false; };
+    /* Is feature enabled */
+    static bool isEnabled() { return sEnabled; };
+
+    eState mState;
+
+    static bool sEnabled;
+    static bool sDebugLogs;
+    static bool sIdleFallBack;
+    static IdleInvalidator *idleInvalidator;
+
+};
+
+class MDPCompLowRes : public MDPComp {
+public:
+    virtual ~MDPCompLowRes() {}
+    virtual bool prepare(hwc_context_t *ctx,
+            hwc_display_contents_1_t* list);
+    virtual bool draw(hwc_context_t *ctx, hwc_display_contents_1_t *list);
+
+private:
     struct MdpPipeInfo {
         int index;
         int zOrder;
@@ -56,81 +105,35 @@
         struct PipeLayerPair* pipeLayer;
 
     };
-
-    static eState sMDPCompState;
-    static IdleInvalidator *idleInvalidator;
-    static struct FrameInfo sCurrentFrame;
-    static bool sEnabled;
-    static bool sDebugLogs;
-    static bool sIdleFallBack;
-    static int sActiveMax;
-    static bool sSecuredVid;
-
-public:
-    /* Handler to invoke frame redraw on Idle Timer expiry */
-    static void timeout_handler(void *udata);
-
-    /* configure/tear-down MDPComp params*/
-    static bool init(hwc_context_t *ctx);
-    static bool deinit();
-    static bool isUsed() { return (sMDPCompState == MDPCOMP_ON); };
-
-    /*sets up mdp comp for the current frame */
-    static bool configure(hwc_context_t *ctx,
-                            hwc_display_contents_1_t* list);
-
-    /* draw */
-    static bool draw(hwc_context_t *ctx, hwc_display_contents_1_t *list);
-
-    static void dump(android::String8& buf);
-
-private:
-    /* set/reset flags for MDPComp */
-    static void setMDPCompLayerFlags(hwc_context_t *ctx,
-                                       hwc_display_contents_1_t* list);
-    static void unsetMDPCompLayerFlags(hwc_context_t* ctx,
-                                       hwc_display_contents_1_t* list);
-
-    static void print_info(hwc_layer_1_t* layer);
-
     /* configure's overlay pipes for the frame */
-    static int  prepare(hwc_context_t *ctx, hwc_layer_1_t *layer,
+    int configure(hwc_context_t *ctx, hwc_layer_1_t *layer,
                         MdpPipeInfo& mdp_info);
-
     /* checks for conditions where mdpcomp is not possible */
-    static bool isDoable(hwc_context_t *ctx, hwc_display_contents_1_t* list);
-
-    static bool setup(hwc_context_t* ctx, hwc_display_contents_1_t* list);
-
+    bool isDoable(hwc_context_t *ctx, hwc_display_contents_1_t* list);
+    bool setup(hwc_context_t* ctx, hwc_display_contents_1_t* list);
     /* allocates pipes to selected candidates */
-    static bool allocLayerPipes(hwc_context_t *ctx,
+    bool allocLayerPipes(hwc_context_t *ctx,
             hwc_display_contents_1_t* list,
             FrameInfo& current_frame);
-
-    /* get/set states */
-    static eState getState() { return sMDPCompState; };
-
     /* reset state */
-    static void reset( hwc_context_t *ctx, hwc_display_contents_1_t* list );
-
-    /* Is feature enabled */
-    static bool isEnabled() { return sEnabled; };
-
-    /* Is debug enabled */
-    static bool isDebug() { return sDebugLogs ? true : false; };
-
-    /* check layer state */
-    static bool isSkipPresent (hwc_context_t *ctx);
-    static bool isYuvPresent (hwc_context_t *ctx);
-
+    void reset( hwc_context_t *ctx, hwc_display_contents_1_t* list );
     /* configure MDP flags for video buffers */
-    static void setVidInfo(hwc_layer_1_t *layer, ovutils::eMdpFlags &mdpFlags);
-
-    /* set up Border fill as Base pipe */
-    static bool setupBasePipe(hwc_context_t*);
-
+    void setVidInfo(hwc_layer_1_t *layer, ovutils::eMdpFlags &mdpFlags);
     /* allocate MDP pipes from overlay */
-    static int getMdpPipe(hwc_context_t *ctx, ePipeType type);
+    int getMdpPipe(hwc_context_t *ctx, ePipeType type);
+
+    struct FrameInfo mCurrentFrame;
 };
+
+class MDPCompHighRes : public MDPComp {
+public:
+    virtual ~MDPCompHighRes() {}
+    virtual bool prepare(hwc_context_t *ctx,
+            hwc_display_contents_1_t* list) { return false; }
+    virtual bool draw(hwc_context_t *ctx, hwc_display_contents_1_t *list) {
+        return true;
+    }
+};
+
 }; //namespace
 #endif
diff --git a/libhwcomposer/hwc_uevents.cpp b/libhwcomposer/hwc_uevents.cpp
index 78f6788..334df26 100644
--- a/libhwcomposer/hwc_uevents.cpp
+++ b/libhwcomposer/hwc_uevents.cpp
@@ -26,6 +26,7 @@
 #include <string.h>
 #include <stdlib.h>
 #include "hwc_utils.h"
+#include "hwc_fbupdate.h"
 #include "external.h"
 
 namespace qhwc {
@@ -38,8 +39,8 @@
     int64_t timestamp = 0;
     const char *str = udata;
 
-    if(!strcasestr(str, "change@/devices/virtual/switch/hdmi") &&
-       !strcasestr(str, "change@/devices/virtual/switch/wfd")) {
+    if(!strcasestr("change@/devices/virtual/switch/hdmi", str) &&
+       !strcasestr("change@/devices/virtual/switch/wfd", str)) {
         ALOGD_IF(UEVENT_DEBUG, "%s: Not Ext Disp Event ", __FUNCTION__);
         return;
     }
@@ -65,10 +66,19 @@
 
     if(connected != -1) { //either we got switch_state connected or disconnect
         ctx->dpyAttr[HWC_DISPLAY_EXTERNAL].connected = connected;
-        if(connected) {
+        if (connected) {
+            ctx->mExtDispConfiguring = true;
             ctx->mExtDisplay->processUEventOnline(udata);
-        }else {
+            ctx->mFBUpdate[HWC_DISPLAY_EXTERNAL] =
+                IFBUpdate::getObject(ctx->dpyAttr[HWC_DISPLAY_EXTERNAL].xres,
+                HWC_DISPLAY_EXTERNAL);
+        } else {
             ctx->mExtDisplay->processUEventOffline(udata);
+            if(ctx->mFBUpdate[HWC_DISPLAY_EXTERNAL]) {
+                Locker::Autolock _l(ctx->mExtSetLock);
+                delete ctx->mFBUpdate[HWC_DISPLAY_EXTERNAL];
+                ctx->mFBUpdate[HWC_DISPLAY_EXTERNAL] = NULL;
+            }
         }
         ALOGD("%s sending hotplug: connected = %d", __FUNCTION__, connected);
         Locker::Autolock _l(ctx->mExtSetLock); //hwc comp could be on
diff --git a/libhwcomposer/hwc_utils.cpp b/libhwcomposer/hwc_utils.cpp
index 2f35567..76635d5 100644
--- a/libhwcomposer/hwc_utils.cpp
+++ b/libhwcomposer/hwc_utils.cpp
@@ -23,6 +23,7 @@
 #include <overlay.h>
 #include "hwc_utils.h"
 #include "hwc_mdpcomp.h"
+#include "hwc_fbupdate.h"
 #include "mdp_version.h"
 #include "external.h"
 #include "QService.h"
@@ -59,15 +60,22 @@
     ctx->mMDP.version = qdutils::MDPVersion::getInstance().getMDPVersion();
     ctx->mMDP.hasOverlay = qdutils::MDPVersion::getInstance().hasOverlay();
     ctx->mMDP.panel = qdutils::MDPVersion::getInstance().getPanelType();
+    //Is created and destroyed only once for primary
+    //For external it could get created and destroyed multiple times depending
+    //on what external we connect to.
+    ctx->mFBUpdate[HWC_DISPLAY_PRIMARY] =
+        IFBUpdate::getObject(ctx->dpyAttr[HWC_DISPLAY_PRIMARY].xres,
+        HWC_DISPLAY_PRIMARY);
     ctx->mExtDisplay = new ExternalDisplay(ctx);
     for (uint32_t i = 0; i < HWC_NUM_DISPLAY_TYPES; i++)
         ctx->mLayerCache[i] = new LayerCache();
+    ctx->mMDPComp = MDPComp::getObject(ctx->dpyAttr[HWC_DISPLAY_PRIMARY].xres);
     MDPComp::init(ctx);
 
     pthread_mutex_init(&(ctx->vstate.lock), NULL);
     pthread_cond_init(&(ctx->vstate.cond), NULL);
     ctx->vstate.enable = false;
-
+    ctx->mExtDispConfiguring = false;
     ALOGI("Initializing Qualcomm Hardware Composer");
     ALOGI("MDP version: %d", ctx->mMDP.version);
 }
@@ -91,6 +99,18 @@
         ctx->mExtDisplay = NULL;
     }
 
+    for(int i = 0; i < HWC_NUM_DISPLAY_TYPES; i++) {
+        if(ctx->mFBUpdate[i]) {
+            delete ctx->mFBUpdate[i];
+            ctx->mFBUpdate[i] = NULL;
+        }
+    }
+
+    if(ctx->mMDPComp) {
+        delete ctx->mMDPComp;
+        ctx->mMDPComp = NULL;
+    }
+
     pthread_mutex_destroy(&(ctx->vstate.lock));
     pthread_cond_destroy(&(ctx->vstate.cond));
 }
@@ -238,15 +258,25 @@
     int count = 0;
     int releaseFd = -1;
     int fbFd = -1;
+    bool swapzero = false;
     data.flags = MDP_BUF_SYNC_FLAG_WAIT;
     data.acq_fen_fd = acquireFd;
     data.rel_fen_fd = &releaseFd;
+    char property[PROPERTY_VALUE_MAX];
+    if(property_get("debug.egl.swapinterval", property, "1") > 0) {
+        if(atoi(property) == 0)
+            swapzero = true;
+    }
+
     //Accumulate acquireFenceFds
     for(uint32_t i = 0; i < list->numHwLayers; i++) {
         if((list->hwLayers[i].compositionType == HWC_OVERLAY ||
             list->hwLayers[i].compositionType == HWC_FRAMEBUFFER_TARGET) &&
             list->hwLayers[i].acquireFenceFd != -1 ){
-            acquireFd[count++] = list->hwLayers[i].acquireFenceFd;
+            if(UNLIKELY(swapzero))
+                acquireFd[count++] = -1;
+            else
+                acquireFd[count++] = list->hwLayers[i].acquireFenceFd;
         }
     }
 
@@ -254,7 +284,8 @@
     fbFd = ctx->dpyAttr[dpy].fd;
 
     //Waits for acquire fences, returns a release fence
-    ret = ioctl(fbFd, MSMFB_BUFFER_SYNC, &data);
+    if(LIKELY(!swapzero))
+        ret = ioctl(fbFd, MSMFB_BUFFER_SYNC, &data);
     if(ret < 0) {
         ALOGE("ioctl MSMFB_BUFFER_SYNC failed, err=%s",
                 strerror(errno));
@@ -269,10 +300,18 @@
                 list->hwLayers[i].acquireFenceFd = -1;
             }
             //Populate releaseFenceFds.
-            list->hwLayers[i].releaseFenceFd = dup(releaseFd);
+            if(UNLIKELY(swapzero))
+                list->hwLayers[i].releaseFenceFd = -1;
+            else
+                list->hwLayers[i].releaseFenceFd = dup(releaseFd);
         }
     }
-    list->retireFenceFd = releaseFd;
+    if(UNLIKELY(swapzero)){
+        list->retireFenceFd = -1;
+        close(releaseFd);
+    } else {
+        list->retireFenceFd = releaseFd;
+    }
     return ret;
 }
 
diff --git a/libhwcomposer/hwc_utils.h b/libhwcomposer/hwc_utils.h
index d7200b0..9541404 100644
--- a/libhwcomposer/hwc_utils.h
+++ b/libhwcomposer/hwc_utils.h
@@ -31,6 +31,7 @@
 #define FINAL_TRANSFORM_MASK 0x000F
 #define MAX_NUM_DISPLAYS 4 //Yes, this is ambitious
 #define MAX_NUM_LAYERS 32
+#define MAX_DISPLAY_DIM 2048
 
 //Fwrd decls
 struct hwc_context_t;
@@ -48,6 +49,8 @@
 //fwrd decl
 class QueuedBufferStore;
 class ExternalDisplay;
+class IFBUpdate;
+class MDPComp;
 
 struct MDPInfo {
     int version;
@@ -215,6 +218,9 @@
     overlay::Overlay *mOverlay;
     //QService object
     qService::QService *mQService;
+
+    //Primary and external FB updater
+    qhwc::IFBUpdate *mFBUpdate[HWC_NUM_DISPLAY_TYPES];
     // External display related information
     qhwc::ExternalDisplay *mExtDisplay;
     qhwc::MDPInfo mMDP;
@@ -222,9 +228,12 @@
     qhwc::ListStats listStats[HWC_NUM_DISPLAY_TYPES];
     qhwc::LayerCache *mLayerCache[HWC_NUM_DISPLAY_TYPES];
     qhwc::LayerProp *layerProp[HWC_NUM_DISPLAY_TYPES];
+    qhwc::MDPComp *mMDPComp;
 
     //Securing in progress indicator
     bool mSecuring;
+    //External Display configuring progress indicator
+    bool mExtDispConfiguring;
     //Display in secure mode indicator
     bool mSecureMode;
     //Lock to prevent set from being called while blanking
@@ -235,4 +244,12 @@
     struct vsync_state vstate;
 };
 
+static inline bool isSkipPresent (hwc_context_t *ctx, int dpy) {
+    return  ctx->listStats[dpy].skipCount;
+}
+
+static inline bool isYuvPresent (hwc_context_t *ctx, int dpy) {
+    return  ctx->listStats[dpy].yuvCount;
+}
+
 #endif //HWC_UTILS_H
diff --git a/libhwcomposer/hwc_video.cpp b/libhwcomposer/hwc_video.cpp
index 48cb165..1784593 100644
--- a/libhwcomposer/hwc_video.cpp
+++ b/libhwcomposer/hwc_video.cpp
@@ -19,6 +19,7 @@
 #include <overlay.h>
 #include "hwc_video.h"
 #include "hwc_utils.h"
+#include "qdMetaData.h"
 
 namespace qhwc {
 
@@ -106,6 +107,11 @@
                 ovutils::OV_MDP_BLEND_FG_PREMULT);
     }
 
+    MetaData_t *metadata = (MetaData_t *)hnd->base_metadata;
+    if ((metadata->operation & PP_PARAM_INTERLACED) && metadata->interlaced) {
+        ovutils::setMdpFlags(mdpFlags, ovutils::OV_MDP_DEINTERLACE);
+    }
+
     ovutils::eIsFg isFgFlag = ovutils::IS_FG_OFF;
     if (ctx->listStats[dpy].numAppLayers == 1) {
         isFgFlag = ovutils::IS_FG_SET;
diff --git a/libhwcomposer/hwc_vsync.cpp b/libhwcomposer/hwc_vsync.cpp
index ee6af28..7f7bb1f 100644
--- a/libhwcomposer/hwc_vsync.cpp
+++ b/libhwcomposer/hwc_vsync.cpp
@@ -112,9 +112,11 @@
         if(!fakevsync) {
             for(int i = 0; i < MAX_RETRY_COUNT; i++) {
                 len = pread(fd_timestamp, vdata, MAX_DATA, 0);
-                if(len < 0 && (errno == EAGAIN || errno == EINTR)) {
-                    ALOGW("%s: vsync read: EAGAIN, retry (%d/%d).",
-                          __FUNCTION__, i, MAX_RETRY_COUNT);
+                if(len < 0 && (errno == EAGAIN ||
+                               errno == EINTR  ||
+                               errno == EBUSY)) {
+                    ALOGW("%s: vsync read: %s, retry (%d/%d).",
+                          __FUNCTION__, strerror(errno), i, MAX_RETRY_COUNT);
                     continue;
                 } else {
                     break;
diff --git a/liboverlay/overlay.h b/liboverlay/overlay.h
index 2378889..151cfb3 100644
--- a/liboverlay/overlay.h
+++ b/liboverlay/overlay.h
@@ -71,8 +71,8 @@
     static void initOverlay();
     /* Returns the singleton instance of overlay */
     static Overlay* getInstance();
-    /* Returns total of available ("unallocated") pipes */
-    static int availablePipes();
+    /* Returns available ("unallocated") pipes for a display */
+    int availablePipes(int dpy);
     /* set the framebuffer index for external display */
     void setExtFbNum(int fbNum);
     /* Returns framebuffer index of the current external display */
@@ -111,8 +111,6 @@
         static void resetAllocation(int index);
         static bool isAllocated(int index);
         static bool isNotAllocated(int index);
-        /* Returns total of available ("unallocated") pipes */
-        static int availablePipes();
 
         static int NUM_PIPES;
 
@@ -149,8 +147,15 @@
             utils::getDestStr((utils::eDest)index));
 }
 
-inline int Overlay::availablePipes() {
-    return PipeBook::availablePipes();
+inline int Overlay::availablePipes(int dpy) {
+     int avail = 0;
+     for(int i = 0; i < PipeBook::NUM_PIPES; i++) {
+       if((mPipeBook[i].mDisplay == PipeBook::DPY_UNUSED ||
+           mPipeBook[i].mDisplay == dpy) && PipeBook::isNotAllocated(i)) {
+                avail++;
+        }
+    }
+    return avail;
 }
 
 inline void Overlay::setExtFbNum(int fbNum) {
@@ -163,16 +168,6 @@
     return sExtFbIndex;
 }
 
-inline int Overlay::PipeBook::availablePipes() {
-    int used = 0;
-    int bmp = sAllocatedBitmap;
-    for(; bmp; used++) {
-        //clearing from lsb
-        bmp = bmp & (bmp - 1);
-    }
-    return NUM_PIPES - used;
-}
-
 inline bool Overlay::PipeBook::valid() {
     return (mPipe != NULL);
 }
diff --git a/liboverlay/overlayMdssRot.cpp b/liboverlay/overlayMdssRot.cpp
index cb3c48f..dedc396 100644
--- a/liboverlay/overlayMdssRot.cpp
+++ b/liboverlay/overlayMdssRot.cpp
@@ -30,6 +30,8 @@
 #define MDSS_MDP_ROT_ONLY 0x80
 #endif
 
+#define SIZE_1M 0x00100000
+
 namespace ovutils = overlay::utils;
 
 namespace overlay {
@@ -93,7 +95,10 @@
 }
 
 void MdssRot::setFlags(const utils::eMdpFlags& flags) {
-    // TODO
+    mRotInfo.flags &= ~utils::OV_MDP_SECURE_OVERLAY_SESSION;
+    if (flags & utils::OV_MDP_SECURE_OVERLAY_SESSION) {
+        mRotInfo.flags |= utils::OV_MDP_SECURE_OVERLAY_SESSION;
+    }
 }
 
 void MdssRot::setTransform(const utils::eTransform& rot, const bool& rotUsed)
@@ -119,6 +124,7 @@
 
 bool MdssRot::commit() {
     doTransform();
+    setBufSize(mRotInfo.src.format);
     mRotInfo.flags |= MDSS_MDP_ROT_ONLY;
     if(!overlay::mdp_wrapper::setOverlay(mFd.getFD(), mRotInfo)) {
         ALOGE("MdssRot commit failed!");
@@ -166,8 +172,9 @@
 {
     OvMem mem;
     OVASSERT(MAP_FAILED == mem.addr(), "MAP failed in open_i");
+    bool isSecure = mRotInfo.flags & utils::OV_MDP_SECURE_OVERLAY_SESSION;
 
-    if(!mem.open(numbufs, bufsz, false)){ // TODO: secure for badger
+    if(!mem.open(numbufs, bufsz, isSecure)){
         ALOGE("%s: Failed to open", __func__);
         mem.close();
         return false;
@@ -248,4 +255,12 @@
     ALOGE("== Dump MdssRot end ==");
 }
 
+void MdssRot::setBufSize(int format) {
+    if (format == MDP_Y_CBCR_H2V2_VENUS) {
+        mBufSize = VENUS_BUFFER_SIZE(COLOR_FMT_NV12, mRotInfo.dst_rect.w,
+                                     mRotInfo.dst_rect.h);
+    }
+    if (mRotInfo.flags & utils::OV_MDP_SECURE_OVERLAY_SESSION)
+        mBufSize = utils::align(mBufSize, SIZE_1M);
+}
 } // namespace overlay
diff --git a/liboverlay/overlayMem.h b/liboverlay/overlayMem.h
index 60ed8fe..e81c2dc 100644
--- a/liboverlay/overlayMem.h
+++ b/liboverlay/overlayMem.h
@@ -119,8 +119,9 @@
     alloc_data data;
     int allocFlags = GRALLOC_USAGE_PRIVATE_IOMMU_HEAP;
     if(isSecure) {
-        allocFlags |= GRALLOC_USAGE_PRIVATE_MM_HEAP;
+        allocFlags = GRALLOC_USAGE_PRIVATE_MM_HEAP;
         allocFlags |= GRALLOC_USAGE_PRIVATE_CP_BUFFER;
+        allocFlags |= GRALLOC_USAGE_PRIVATE_UNCACHED;
     }
 
     int err = 0;
diff --git a/liboverlay/overlayRotator.h b/liboverlay/overlayRotator.h
index 4ef33f3..ca71402 100644
--- a/liboverlay/overlayRotator.h
+++ b/liboverlay/overlayRotator.h
@@ -199,6 +199,7 @@
     void doTransform();
     /* reset underlying data, basically memset 0 */
     void reset();
+    void setBufSize(int format);
 
     /* MdssRot info structure */
     mdp_overlay   mRotInfo;
diff --git a/liboverlay/overlayUtils.cpp b/liboverlay/overlayUtils.cpp
index d0f9457..49a1eaf 100644
--- a/liboverlay/overlayUtils.cpp
+++ b/liboverlay/overlayUtils.cpp
@@ -231,7 +231,8 @@
             return MDP_Y_CBCR_H1V1;
         case HAL_PIXEL_FORMAT_YCrCb_444_SP:
             return MDP_Y_CRCB_H1V1;
-
+        case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS:
+            return MDP_Y_CBCR_H2V2_VENUS;
         default:
             //Unsupported by MDP
             //---graphics.h--------
diff --git a/liboverlay/overlayUtils.h b/liboverlay/overlayUtils.h
index f9fcca8..cbacf3e 100644
--- a/liboverlay/overlayUtils.h
+++ b/liboverlay/overlayUtils.h
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
+* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
@@ -44,6 +44,11 @@
 #include <utils/Log.h>
 #include "gralloc_priv.h" //for interlace
 
+// Older platforms do not support Venus.
+#ifndef VENUS_COLOR_FORMAT
+#define MDP_Y_CBCR_H2V2_VENUS (MDP_IMGTYPE_LIMIT2 + 1)
+#endif
+
 /*
 *
 * Collection of utilities functions/structs/enums etc...
@@ -63,6 +68,10 @@
 #define DEBUG_OVERLAY 0
 #define PROFILE_OVERLAY 0
 
+#ifndef MDSS_MDP_RIGHT_MIXER
+#define MDSS_MDP_RIGHT_MIXER 0x100
+#endif
+
 namespace overlay {
 
 // fwd
@@ -297,6 +306,7 @@
     OV_MDP_BLEND_FG_PREMULT = MDP_BLEND_FG_PREMULT,
     OV_MDP_FLIP_H = MDP_FLIP_LR,
     OV_MDP_FLIP_V = MDP_FLIP_UD,
+    OV_MDSS_MDP_RIGHT_MIXER = MDSS_MDP_RIGHT_MIXER,
 };
 
 enum eZorder {
@@ -487,6 +497,7 @@
         case MDP_Y_CBCR_H2V2_TILE:
         case MDP_Y_CR_CB_H2V2:
         case MDP_Y_CR_CB_GH2V2:
+        case MDP_Y_CBCR_H2V2_VENUS:
             return true;
         default:
             return false;
@@ -534,6 +545,8 @@
         "MDP_YCRCB_H1V1",
         "MDP_YCBCR_H1V1",
         "MDP_BGR_565",
+        "MDP_BGR_888",
+        "MDP_Y_CBCR_H2V2_VENUS",
         "MDP_IMGTYPE_LIMIT",
         "MDP_RGB_BORDERFILL",
         "MDP_FB_FORMAT",
diff --git a/libqdutils/Android.mk b/libqdutils/Android.mk
index ed8bed0..ecae273 100644
--- a/libqdutils/Android.mk
+++ b/libqdutils/Android.mk
@@ -12,3 +12,19 @@
                                  idle_invalidator.cpp
 
 include $(BUILD_SHARED_LIBRARY)
+
+include $(CLEAR_VARS)
+
+LOCAL_COPY_HEADERS_TO           := qcom/display
+LOCAL_COPY_HEADERS              := qdMetaData.h
+LOCAL_MODULE_PATH               := $(TARGET_OUT_SHARED_LIBRARIES)
+LOCAL_SHARED_LIBRARIES          := liblog libcutils
+LOCAL_C_INCLUDES                := $(common_includes)
+LOCAL_ADDITIONAL_DEPENDENCIES   := $(common_deps)
+LOCAL_SRC_FILES                 := qdMetaData.cpp
+LOCAL_CFLAGS                    := $(common_flags)
+LOCAL_CFLAGS                    += -DLOG_TAG=\"DisplayMetaData\"
+LOCAL_MODULE_TAGS               := optional
+LOCAL_MODULE                    := libqdMetaData
+include $(BUILD_SHARED_LIBRARY)
+
diff --git a/libqdutils/qdMetaData.cpp b/libqdutils/qdMetaData.cpp
new file mode 100644
index 0000000..a53ba07
--- /dev/null
+++ b/libqdutils/qdMetaData.cpp
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2012, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ *       copyright notice, this list of conditions and the following
+ *       disclaimer in the documentation and/or other materials provided
+ *       with the distribution.
+ *     * Neither the name of The Linux Foundation nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <string.h>
+#include <sys/mman.h>
+#include <cutils/log.h>
+#include <gralloc_priv.h>
+#include "qdMetaData.h"
+
+int setMetaData(private_handle_t *handle, DispParamType paramType,
+                                                    void *param) {
+    if (!handle) {
+        ALOGE("%s: Private handle is null!", __func__);
+        return -1;
+    }
+    if (handle->fd_metadata == -1) {
+        ALOGE("%s: Bad fd for extra data!", __func__);
+        return -1;
+    }
+    unsigned long size = ROUND_UP_PAGESIZE(sizeof(MetaData_t));
+    void *base = mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_SHARED,
+        handle->fd_metadata, 0);
+    if (!base) {
+        ALOGE("%s: mmap() failed: Base addr is NULL!", __func__);
+        return -1;
+    }
+    MetaData_t *data = reinterpret_cast <MetaData_t *>(base);
+    data->operation |= paramType;
+    switch (paramType) {
+        case PP_PARAM_HSIC:
+            memcpy((void *)&data->hsicData, param, sizeof(HSICData_t));
+            break;
+        case PP_PARAM_SHARPNESS:
+            data->sharpness = *((int32_t *)param);
+            break;
+        case PP_PARAM_VID_INTFC:
+            data->video_interface = *((int32_t *)param);
+            break;
+        case PP_PARAM_INTERLACED:
+            data->interlaced = *((int32_t *)param);
+            break;
+        default:
+            ALOGE("Unknown paramType %d", paramType);
+            break;
+    }
+    if(munmap(base, size))
+        ALOGE("%s: failed to unmap ptr 0x%x, err %d", __func__, (int)base,
+                                                                        errno);
+    return 0;
+}
diff --git a/libqdutils/qdMetaData.h b/libqdutils/qdMetaData.h
new file mode 100644
index 0000000..e60daed
--- /dev/null
+++ b/libqdutils/qdMetaData.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2012, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ *       copyright notice, this list of conditions and the following
+ *       disclaimer in the documentation and/or other materials provided
+ *       with the distribution.
+ *     * Neither the name of The Linux Foundation nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _QDMETADATA_H
+#define _QDMETADATA_H
+
+
+typedef struct {
+    int32_t hue;
+    float   saturation;
+    int32_t intensity;
+    float   contrast;
+} HSICData_t;
+
+typedef struct {
+    int32_t operation;
+    int32_t interlaced;
+    HSICData_t hsicData;
+    int32_t sharpness;
+    int32_t video_interface;
+} MetaData_t;
+
+typedef enum {
+    PP_PARAM_HSIC       = 0x0001,
+    PP_PARAM_SHARPNESS  = 0x0002,
+    PP_PARAM_INTERLACED = 0x0004,
+    PP_PARAM_VID_INTFC  = 0x0008
+} DispParamType;
+
+int setMetaData(private_handle_t *handle, DispParamType paramType, void *param);
+
+#endif /* _QDMETADATA_H */
+