am 0028b620: overlay: Call MSMFB_SECURE on alloc/free of secure rotator buffer

* commit '0028b620909a0ddc8edac301967bfa43fb33a421':
  overlay: Call MSMFB_SECURE on alloc/free of secure rotator buffer
diff --git a/msm8084/Android.mk b/msm8084/Android.mk
index 0959e7a..59a9751 100644
--- a/msm8084/Android.mk
+++ b/msm8084/Android.mk
@@ -1,6 +1,6 @@
 display-hals := libgralloc libcopybit liblight libvirtual
 display-hals += libhwcomposer liboverlay libqdutils libexternal libqservice
-display-hals += libmemtrack hdmi_cec
+display-hals += libmemtrack
 ifeq ($(call is-vendor-board-platform,QCOM),true)
     include $(call all-named-subdir-makefiles,$(display-hals))
 else
diff --git a/msm8084/hdmi_cec/Android.mk b/msm8084/hdmi_cec/Android.mk
deleted file mode 100644
index a605b6b..0000000
--- a/msm8084/hdmi_cec/Android.mk
+++ /dev/null
@@ -1,15 +0,0 @@
-LOCAL_PATH := $(call my-dir)
-include $(LOCAL_PATH)/../common.mk
-include $(CLEAR_VARS)
-
-LOCAL_MODULE                  := hdmi_cec.$(TARGET_BOARD_PLATFORM)
-LOCAL_MODULE_PATH             := $(TARGET_OUT_SHARED_LIBRARIES)/hw
-LOCAL_MODULE_TAGS             := optional
-LOCAL_C_INCLUDES              := $(common_includes)
-LOCAL_SHARED_LIBRARIES        := $(common_libs) libqservice libbinder libqdutils
-
-LOCAL_CFLAGS                  := $(common_flags) -DLOG_TAG=\"qdhdmi_cec\"
-LOCAL_ADDITIONAL_DEPENDENCIES := $(common_deps)
-LOCAL_SRC_FILES               := qhdmi_cec.cpp \
-                                 QHDMIClient.cpp
-include $(BUILD_SHARED_LIBRARY)
diff --git a/msm8084/hdmi_cec/QHDMIClient.cpp b/msm8084/hdmi_cec/QHDMIClient.cpp
deleted file mode 100644
index 176779a..0000000
--- a/msm8084/hdmi_cec/QHDMIClient.cpp
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
-* Copyright (c) 2014 The Linux Foundation. All rights reserved.
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted provided that the following conditions are
-* met:
-*    * Redistributions of source code must retain the above copyright
-*      notice, this list of conditions and the following disclaimer.
-*    * Redistributions in binary form must reproduce the above
-*      copyright notice, this list of conditions and the following
-*      disclaimer in the documentation and/or other materials provided
-*      with the distribution.
-*    * Neither the name of The Linux Foundation. nor the names of its
-*      contributors may be used to endorse or promote products derived
-*      from this software without specific prior written permission.
-*
-* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
-* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
-* ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
-* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
-* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
-* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
-* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
-
-#include <QServiceUtils.h>
-#include "QHDMIClient.h"
-
-using namespace android;
-using namespace qhdmicec;
-using namespace qService;
-
-namespace qClient {
-
-void QHDMIClient::binderDied(const wp<IBinder>& who __unused)
-{
-    ALOGW("%s: Display QService died", __FUNCTION__);
-}
-
-void QHDMIClient::onHdmiHotplug(int connected)
-{
-    ALOGD("%s: HDMI connected event connected: %d", __FUNCTION__, connected);
-    cec_hdmi_hotplug(mCtx, connected);
-}
-
-void QHDMIClient::onCECMessageRecieved(char *msg, ssize_t len)
-{
-    ALOGD("%s: CEC message received len: %zd", __FUNCTION__, len);
-    cec_receive_message(mCtx, msg, len);
-}
-
-void QHDMIClient::registerClient(sp<QHDMIClient>& client)
-{
-    sp<IServiceManager> sm = defaultServiceManager();
-    sp<IBinder> binder = sm->getService(String16("display.qservice"));
-    binder->linkToDeath(client);
-    mQService = interface_cast<IQService>(binder);
-    mQService->connect(interface_cast<IQHDMIClient>(client));
-}
-
-};
diff --git a/msm8084/hdmi_cec/QHDMIClient.h b/msm8084/hdmi_cec/QHDMIClient.h
deleted file mode 100644
index 9e54f2f..0000000
--- a/msm8084/hdmi_cec/QHDMIClient.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
-* Copyright (c) 2014 The Linux Foundation. All rights reserved.
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted provided that the following conditions are
-* met:
-*    * Redistributions of source code must retain the above copyright
-*      notice, this list of conditions and the following disclaimer.
-*    * Redistributions in binary form must reproduce the above
-*      copyright notice, this list of conditions and the following
-*      disclaimer in the documentation and/or other materials provided
-*      with the distribution.
-*    * Neither the name of The Linux Foundation. nor the names of its
-*      contributors may be used to endorse or promote products derived
-*      from this software without specific prior written permission.
-*
-* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
-* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
-* ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
-* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
-* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
-* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
-* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
-
-#include "IQHDMIClient.h"
-#include "qhdmi_cec.h"
-#include <IQService.h>
-
-namespace qClient {
-
-class QHDMIClient: public android::IBinder::DeathRecipient,
-    public BnQHDMIClient
-{
-public:
-    QHDMIClient() {}
-
-    virtual void binderDied(const android::wp<android::IBinder>& who);
-
-    virtual void onHdmiHotplug(int connected);
-
-    virtual void onCECMessageRecieved(char *msg, ssize_t len);
-
-    void setCECContext(qhdmicec::cec_context_t* ctx) { mCtx = ctx; }
-
-    void registerClient(android::sp<QHDMIClient>& client);
-
-private:
-    qhdmicec::cec_context_t* mCtx;
-    android::sp<qService::IQService> mQService;
-
-};
-};
diff --git a/msm8084/hdmi_cec/qhdmi_cec.cpp b/msm8084/hdmi_cec/qhdmi_cec.cpp
deleted file mode 100644
index d23fce6..0000000
--- a/msm8084/hdmi_cec/qhdmi_cec.cpp
+++ /dev/null
@@ -1,492 +0,0 @@
-/*
-* Copyright (c) 2014 The Linux Foundation. All rights reserved.
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted provided that the following conditions are
-* met:
-*    * Redistributions of source code must retain the above copyright
-*      notice, this list of conditions and the following disclaimer.
-*    * Redistributions in binary form must reproduce the above
-*      copyright notice, this list of conditions and the following
-*      disclaimer in the documentation and/or other materials provided
-*      with the distribution.
-*    * Neither the name of The Linux Foundation. nor the names of its
-*      contributors may be used to endorse or promote products derived
-*      from this software without specific prior written permission.
-*
-* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
-* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
-* ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
-* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
-* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
-* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
-* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
-
-#define DEBUG 1
-#define ATRACE_TAG (ATRACE_TAG_GRAPHICS | ATRACE_TAG_HAL)
-#include <cstdlib>
-#include <cutils/log.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <hardware/hdmi_cec.h>
-#include <utils/Trace.h>
-#include "qhdmi_cec.h"
-#include "QHDMIClient.h"
-
-namespace qhdmicec {
-
-const int NUM_HDMI_PORTS = 1;
-const int MAX_SYSFS_DATA = 128;
-const int MAX_CEC_FRAME_SIZE = 20;
-const int MAX_SEND_MESSAGE_RETRIES = 1;
-
-enum {
-    LOGICAL_ADDRESS_SET   =  1,
-    LOGICAL_ADDRESS_UNSET = -1,
-};
-
-// Offsets of members of struct hdmi_cec_msg
-// drivers/video/msm/mdss/mdss_hdmi_cec.c
-// XXX: Get this from a driver header
-enum {
-    CEC_OFFSET_SENDER_ID,
-    CEC_OFFSET_RECEIVER_ID,
-    CEC_OFFSET_OPCODE,
-    CEC_OFFSET_OPERAND,
-    CEC_OFFSET_FRAME_LENGTH = 18,
-    CEC_OFFSET_RETRANSMIT,
-};
-
-//Forward declarations
-static void cec_close_context(cec_context_t* ctx __unused);
-static int cec_enable(cec_context_t *ctx, int enable);
-
-static ssize_t read_node(const char *path, char *data)
-{
-    ssize_t err = 0;
-    FILE *fp = NULL;
-    err = access(path, R_OK);
-    if (!err) {
-        fp = fopen(path, "r");
-        err = fread(data, sizeof(char), MAX_SYSFS_DATA ,fp);
-        fclose(fp);
-    }
-    return err;
-}
-
-static ssize_t write_node(const char *path, const char *data, size_t len)
-{
-    ssize_t err = 0;
-    int fd = -1;
-    err = access(path, W_OK);
-    if (!err) {
-        fd = open(path, O_WRONLY);
-        errno = 0;
-        err = write(fd, data, len);
-        if (err < 0) {
-            err = -errno;
-        }
-        close(fd);
-    } else {
-        ALOGE("%s: Failed to access path: %s error: %s",
-                __FUNCTION__, path, strerror(errno));
-        err = -errno;
-    }
-    return err;
-}
-
-// Helper function to write integer values to the full sysfs path
-static ssize_t write_int_to_node(cec_context_t *ctx,
-        const char *path_postfix,
-        const int value)
-{
-    char sysfs_full_path[MAX_PATH_LENGTH];
-    char sysfs_data[MAX_SYSFS_DATA];
-    snprintf(sysfs_data, sizeof(sysfs_data), "%d",value);
-    snprintf(sysfs_full_path,sizeof(sysfs_full_path), "%s/%s",
-            ctx->fb_sysfs_path, path_postfix);
-    ssize_t err = write_node(sysfs_full_path, sysfs_data, strlen(sysfs_data));
-    return err;
-}
-
-static void hex_to_string(const char *msg, ssize_t len, char *str)
-{
-    //Functions assumes sufficient memory in str
-    char *ptr = str;
-    for(int i=0; i < len ; i++) {
-        ptr += snprintf(ptr, 3,  "%02X", msg[i]);
-        // Overwrite null termination of snprintf in all except the last byte
-        if (i < len - 1)
-            *ptr = ':';
-        ptr++;
-    }
-}
-
-static ssize_t cec_get_fb_node_number(cec_context_t *ctx)
-{
-    //XXX: Do this from a common utility library across the display HALs
-    const int MAX_FB_DEVICES = 2;
-    ssize_t len = 0;
-    char fb_type_path[MAX_PATH_LENGTH];
-    char fb_type[MAX_SYSFS_DATA];
-    const char *dtv_panel_str = "dtv panel";
-
-    for(int num = 0; num < MAX_FB_DEVICES; num++) {
-        snprintf(fb_type_path, sizeof(fb_type_path),"%s%d/msm_fb_type",
-                SYSFS_BASE,num);
-        ALOGD_IF(DEBUG, "%s: num: %d fb_type_path: %s", __FUNCTION__, num, fb_type_path);
-        len = read_node(fb_type_path, fb_type);
-        ALOGD_IF(DEBUG, "%s: fb_type:%s", __FUNCTION__, fb_type);
-        if(len > 0 && (strncmp(fb_type, dtv_panel_str, strlen(dtv_panel_str)) == 0)){
-            ALOGD_IF(DEBUG, "%s: Found DTV panel at fb%d", __FUNCTION__, num);
-            ctx->fb_num = num;
-            snprintf(ctx->fb_sysfs_path, sizeof(ctx->fb_sysfs_path),
-                    "%s%d", SYSFS_BASE, num);
-            break;
-        }
-    }
-    if (len < 0)
-        return len;
-    else
-        return 0;
-}
-
-static int cec_add_logical_address(const struct hdmi_cec_device* dev,
-        cec_logical_address_t addr)
-{
-    if (addr <  CEC_ADDR_TV || addr > CEC_ADDR_BROADCAST) {
-        ALOGE("%s: Received invalid address: %d ", __FUNCTION__, addr);
-        return -EINVAL;
-    }
-    cec_context_t* ctx = (cec_context_t*)(dev);
-    ctx->logical_address[addr] = LOGICAL_ADDRESS_SET;
-
-    //XXX: We can get multiple logical addresses here but we can only send one
-    //to the driver. Store locally for now
-    ssize_t err = write_int_to_node(ctx, "cec/logical_addr", addr);
-    ALOGD_IF(DEBUG, "%s: Allocated logical address: %d ", __FUNCTION__, addr);
-    return (int) err;
-}
-
-static void cec_clear_logical_address(const struct hdmi_cec_device* dev)
-{
-    cec_context_t* ctx = (cec_context_t*)(dev);
-    memset(ctx->logical_address, LOGICAL_ADDRESS_UNSET,
-            sizeof(ctx->logical_address));
-    //XXX: Find logical_addr that needs to be reset
-    write_int_to_node(ctx, "cec/logical_addr", -1);
-    ALOGD_IF(DEBUG, "%s: Cleared logical addresses", __FUNCTION__);
-}
-
-static int cec_get_physical_address(const struct hdmi_cec_device* dev,
-        uint16_t* addr)
-{
-    cec_context_t* ctx = (cec_context_t*)(dev);
-    //XXX: Not sure if this physical address is the same as the one in port info
-    *addr = ctx->port_info[0].physical_address;
-    ALOGD_IF(DEBUG, "%s: Physical Address: 0x%x", __FUNCTION__, *addr);
-    return 0;
-}
-
-static int cec_send_message(const struct hdmi_cec_device* dev,
-        const cec_message_t* msg)
-{
-    ATRACE_CALL();
-    cec_context_t* ctx = (cec_context_t*)(dev);
-    ALOGD_IF(DEBUG, "%s: initiator: %d destination: %d length: %u",
-            __FUNCTION__, msg->initiator, msg->destination,
-            (uint32_t) msg->length);
-
-    // Dump message received from framework
-    char dump[128];
-    if(msg->length > 0) {
-        hex_to_string((char*)msg->body, msg->length, dump);
-        ALOGD_IF(DEBUG, "%s: message from framework: %s", __FUNCTION__, dump);
-    }
-
-    char write_msg_path[MAX_PATH_LENGTH];
-    char write_msg[MAX_CEC_FRAME_SIZE];
-    memset(write_msg, 0, sizeof(write_msg));
-    // See definition of struct hdmi_cec_msg in driver code
-    // drivers/video/msm/mdss/mdss_hdmi_cec.c
-    // Write header block
-    // XXX: Include this from header in kernel
-    write_msg[CEC_OFFSET_SENDER_ID] = msg->initiator;
-    write_msg[CEC_OFFSET_RECEIVER_ID] = msg->destination;
-    //Kernel splits opcode/operand, but Android sends it in one byte array
-    write_msg[CEC_OFFSET_OPCODE] = msg->body[0];
-    if(msg->length > 1) {
-        memcpy(&write_msg[CEC_OFFSET_OPERAND], &msg->body[1],
-                sizeof(char)*(msg->length - 1));
-    }
-    //msg length + initiator + destination
-    write_msg[CEC_OFFSET_FRAME_LENGTH] = (unsigned char) (msg->length + 1);
-    hex_to_string(write_msg, sizeof(write_msg), dump);
-    ALOGD_IF(DEBUG, "%s: message to driver: %s", __FUNCTION__, dump);
-    snprintf(write_msg_path, sizeof(write_msg_path), "%s/cec/wr_msg",
-            ctx->fb_sysfs_path);
-    int retry_count = 0;
-    ssize_t err = 0;
-    //HAL spec requires us to retry at least once.
-    while (true) {
-        err = write_node(write_msg_path, write_msg, sizeof(write_msg));
-        retry_count++;
-        if (err == -EAGAIN && retry_count <= MAX_SEND_MESSAGE_RETRIES) {
-            ALOGE("%s: CEC line busy, retrying", __FUNCTION__);
-        } else {
-            break;
-        }
-    }
-
-    if (err < 0) {
-       if (err == -ENXIO) {
-           ALOGE("%s: No device exists with the destination address",
-                   __FUNCTION__);
-           return HDMI_RESULT_NACK;
-       } else if (err == -EAGAIN) {
-            ALOGE("%s: CEC line is busy, max retry count exceeded",
-                    __FUNCTION__);
-            return HDMI_RESULT_BUSY;
-        } else {
-            return HDMI_RESULT_FAIL;
-            ALOGE("%s: Failed to send CEC message err: %zd - %s",
-                    __FUNCTION__, err, strerror(-err));
-        }
-    } else {
-        ALOGD_IF(DEBUG, "%s: Sent CEC message - %zd bytes written",
-                __FUNCTION__, err);
-        return HDMI_RESULT_SUCCESS;
-    }
-}
-
-void cec_receive_message(cec_context_t *ctx, char *msg, ssize_t len)
-{
-    char dump[128];
-    if(len > 0) {
-        hex_to_string(msg, len, dump);
-        ALOGD_IF(DEBUG, "%s: Message from driver: %s", __FUNCTION__, dump);
-    }
-
-    hdmi_event_t event;
-    event.type = HDMI_EVENT_CEC_MESSAGE;
-    event.dev = (hdmi_cec_device *) ctx;
-    // Remove initiator/destination from this calculation
-    event.cec.length = msg[CEC_OFFSET_FRAME_LENGTH] - 1;
-    event.cec.initiator = (cec_logical_address_t) msg[CEC_OFFSET_SENDER_ID];
-    event.cec.destination = (cec_logical_address_t) msg[CEC_OFFSET_RECEIVER_ID];
-    //Copy opcode and operand
-    memcpy(event.cec.body, &msg[CEC_OFFSET_OPCODE], event.cec.length);
-    hex_to_string((char *) event.cec.body, event.cec.length, dump);
-    ALOGD_IF(DEBUG, "%s: Message to framework: %s", __FUNCTION__, dump);
-    ctx->callback.callback_func(&event, ctx->callback.callback_arg);
-}
-
-void cec_hdmi_hotplug(cec_context_t *ctx, int connected)
-{
-    hdmi_event_t event;
-    event.type = HDMI_EVENT_HOT_PLUG;
-    event.dev = (hdmi_cec_device *) ctx;
-    event.hotplug.connected = connected ? HDMI_CONNECTED : HDMI_NOT_CONNECTED;
-    ctx->callback.callback_func(&event, ctx->callback.callback_arg);
-}
-
-static void cec_register_event_callback(const struct hdmi_cec_device* dev,
-            event_callback_t callback, void* arg)
-{
-    ALOGD_IF(DEBUG, "%s: Registering callback", __FUNCTION__);
-    cec_context_t* ctx = (cec_context_t*)(dev);
-    ctx->callback.callback_func = callback;
-    ctx->callback.callback_arg = arg;
-}
-
-static void cec_get_version(const struct hdmi_cec_device* dev, int* version)
-{
-    cec_context_t* ctx = (cec_context_t*)(dev);
-    *version = ctx->version;
-    ALOGD_IF(DEBUG, "%s: version: %d", __FUNCTION__, *version);
-}
-
-static void cec_get_vendor_id(const struct hdmi_cec_device* dev,
-        uint32_t* vendor_id)
-{
-    cec_context_t* ctx = (cec_context_t*)(dev);
-    *vendor_id = ctx->vendor_id;
-    ALOGD_IF(DEBUG, "%s: vendor id: %u", __FUNCTION__, *vendor_id);
-}
-
-static void cec_get_port_info(const struct hdmi_cec_device* dev,
-            struct hdmi_port_info* list[], int* total)
-{
-    ALOGD_IF(DEBUG, "%s: Get port info", __FUNCTION__);
-    cec_context_t* ctx = (cec_context_t*)(dev);
-    *total = NUM_HDMI_PORTS;
-    *list = ctx->port_info;
-}
-
-static void cec_set_option(const struct hdmi_cec_device* dev, int flag,
-        int value)
-{
-    cec_context_t* ctx = (cec_context_t*)(dev);
-    ALOGD_IF(DEBUG, "%s: flag:%d value:%d", __FUNCTION__, flag, value);
-    switch (flag) {
-        case HDMI_OPTION_WAKEUP:
-            //XXX
-            break;
-        case HDMI_OPTION_ENABLE_CEC:
-            cec_enable(ctx, value? 1 : 0);
-            break;
-        case HDMI_OPTION_SYSTEM_CEC_CONTROL:
-            //XXX
-            break;
-    }
-}
-
-static void cec_set_audio_return_channel(const struct hdmi_cec_device* dev,
-        int flag)
-{
-    cec_context_t* ctx = (cec_context_t*)(dev);
-    ctx->arc_enabled = flag ? true : false;
-    ALOGD_IF(DEBUG, "%s: ARC flag: %d", __FUNCTION__, flag);
-}
-
-static int cec_is_connected(const struct hdmi_cec_device* dev, int port_id)
-{
-    // Ignore port_id since we have only one port
-    int connected = 0;
-    cec_context_t* ctx = (cec_context_t*)(dev);
-    char connected_path[MAX_PATH_LENGTH];
-    char connected_data[MAX_SYSFS_DATA];
-    snprintf (connected_path, sizeof(connected_path),"%s/connected",
-            ctx->fb_sysfs_path);
-    ssize_t err = read_node(connected_path, connected_data);
-    connected = atoi(connected_data);
-
-    ALOGD_IF(DEBUG, "%s: HDMI at port %d is - %s", __FUNCTION__, port_id,
-            connected ? "connected":"disconnected");
-    if (err)
-        return (int) err;
-    else
-        return connected;
-}
-
-static int cec_device_close(struct hw_device_t *dev)
-{
-    ALOGD_IF(DEBUG, "%s: Close CEC HAL ", __FUNCTION__);
-    if (!dev) {
-        ALOGE("%s: NULL device pointer", __FUNCTION__);
-        return -EINVAL;
-    }
-    cec_context_t* ctx = (cec_context_t*)(dev);
-    cec_close_context(ctx);
-    free(dev);
-    return 0;
-}
-
-static int cec_enable(cec_context_t *ctx, int enable)
-{
-    ssize_t err;
-    err = write_int_to_node(ctx, "cec/enable", !!enable);
-    if(err < 0) {
-        ALOGE("%s: Failed to toggle CEC: enable: %d",
-                __FUNCTION__, enable);
-        return (int) err;
-    }
-    ctx->enabled = enable;
-    return 0;
-}
-
-static void cec_init_context(cec_context_t *ctx)
-{
-    ALOGD_IF(DEBUG, "%s: Initializing context", __FUNCTION__);
-    cec_get_fb_node_number(ctx);
-
-    //Initialize ports - We support only one output port
-    ctx->port_info = new hdmi_port_info[NUM_HDMI_PORTS];
-    ctx->port_info[0].type = HDMI_OUTPUT;
-    //XXX: Updated l-dev has port_id field
-    ctx->port_info[0].port_id = 1;
-    ctx->port_info[0].cec_supported = 1;
-    //XXX: Enable ARC if supported
-    ctx->port_info[0].arc_supported = 0;
-    //XXX: Get physical address from driver
-    ctx->port_info[0].physical_address = 0x1000;
-
-    ctx->version = 0x4;
-    //XXX: Get vendor ID from driver - this is currently a placeholder value
-    ctx->vendor_id = 0x4571;
-    cec_clear_logical_address((hdmi_cec_device_t*)ctx);
-
-    //Set up listener for HDMI events
-    ctx->disp_client = new qClient::QHDMIClient();
-    ctx->disp_client->setCECContext(ctx);
-    ctx->disp_client->registerClient(ctx->disp_client);
-
-    //Enable CEC - framework expects it to be enabled by default
-    cec_enable(ctx, true);
-
-    ALOGD("%s: CEC enabled", __FUNCTION__);
-}
-
-static void cec_close_context(cec_context_t* ctx __unused)
-{
-    ALOGD("%s: Closing context", __FUNCTION__);
-}
-
-static int cec_device_open(const struct hw_module_t* module,
-        const char* name,
-        struct hw_device_t** device)
-{
-    ALOGD_IF(DEBUG, "%s: name: %s", __FUNCTION__, name);
-    int status = -EINVAL;
-    if (!strcmp(name, HDMI_CEC_HARDWARE_INTERFACE )) {
-        struct cec_context_t *dev;
-        dev = (cec_context_t *) calloc (1, sizeof(*dev));
-        cec_init_context(dev);
-
-        //Setup CEC methods
-        dev->device.common.tag       = HARDWARE_DEVICE_TAG;
-        dev->device.common.version   = HDMI_CEC_DEVICE_API_VERSION_1_0;
-        dev->device.common.module    = const_cast<hw_module_t* >(module);
-        dev->device.common.close     = cec_device_close;
-        dev->device.add_logical_address = cec_add_logical_address;
-        dev->device.clear_logical_address = cec_clear_logical_address;
-        dev->device.get_physical_address = cec_get_physical_address;
-        dev->device.send_message = cec_send_message;
-        dev->device.register_event_callback = cec_register_event_callback;
-        dev->device.get_version = cec_get_version;
-        dev->device.get_vendor_id = cec_get_vendor_id;
-        dev->device.get_port_info = cec_get_port_info;
-        dev->device.set_option = cec_set_option;
-        dev->device.set_audio_return_channel = cec_set_audio_return_channel;
-        dev->device.is_connected = cec_is_connected;
-
-        *device = &dev->device.common;
-        status = 0;
-    }
-    return status;
-}
-}; //namespace qhdmicec
-
-// Standard HAL module, should be outside qhdmicec namespace
-static struct hw_module_methods_t cec_module_methods = {
-        .open = qhdmicec::cec_device_open
-};
-
-hdmi_module_t HAL_MODULE_INFO_SYM = {
-    .common = {
-        .tag = HARDWARE_MODULE_TAG,
-        .version_major = 1,
-        .version_minor = 0,
-        .id = HDMI_CEC_HARDWARE_MODULE_ID,
-        .name = "QTI HDMI CEC module",
-        .author = "The Linux Foundation",
-        .methods = &cec_module_methods,
-    }
-};
-
-
diff --git a/msm8084/hdmi_cec/qhdmi_cec.h b/msm8084/hdmi_cec/qhdmi_cec.h
deleted file mode 100644
index 4afd07f..0000000
--- a/msm8084/hdmi_cec/qhdmi_cec.h
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
-* Copyright (c) 2014 The Linux Foundation. All rights reserved.
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted provided that the following conditions are
-* met:
-*    * Redistributions of source code must retain the above copyright
-*      notice, this list of conditions and the following disclaimer.
-*    * Redistributions in binary form must reproduce the above
-*      copyright notice, this list of conditions and the following
-*      disclaimer in the documentation and/or other materials provided
-*      with the distribution.
-*    * Neither the name of The Linux Foundation. nor the names of its
-*      contributors may be used to endorse or promote products derived
-*      from this software without specific prior written permission.
-*
-* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
-* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
-* ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
-* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
-* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
-* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
-* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
-#ifndef QHDMI_CEC_H
-#define QHDMI_CEC_H
-
-#include <hardware/hdmi_cec.h>
-#include <utils/RefBase.h>
-
-namespace qClient {
-    class QHDMIClient;
-};
-
-namespace qhdmicec {
-
-#define SYSFS_BASE  "/sys/class/graphics/fb"
-#define MAX_PATH_LENGTH  128
-
-struct cec_callback_t {
-    // Function in HDMI service to call back on CEC messages
-    event_callback_t callback_func;
-    // This stores the object to pass back to the framework
-    void* callback_arg;
-
-};
-
-struct cec_context_t {
-    hdmi_cec_device_t device;    // Device for HW module
-    cec_callback_t callback;     // Struct storing callback object
-    bool enabled;
-    bool arc_enabled;
-    int fb_num;                  // Framebuffer node for HDMI
-    char fb_sysfs_path[MAX_PATH_LENGTH];
-    hdmi_port_info *port_info;   // HDMI port info
-
-    // Logical address is stored in an array, the index of the array is the
-    // logical address and the value in the index shows whether it is set or not
-    int logical_address[CEC_ADDR_BROADCAST];
-    int version;
-    uint32_t vendor_id;
-    android::sp<qClient::QHDMIClient> disp_client;
-};
-
-void cec_receive_message(cec_context_t *ctx, char *msg, ssize_t len);
-void cec_hdmi_hotplug(cec_context_t *ctx, int connected);
-
-}; //namespace
-#endif /* end of include guard: QHDMI_CEC_H */
diff --git a/msm8084/libgralloc/alloc_controller.cpp b/msm8084/libgralloc/alloc_controller.cpp
index 775ef44..4dae3e6 100644
--- a/msm8084/libgralloc/alloc_controller.cpp
+++ b/msm8084/libgralloc/alloc_controller.cpp
@@ -596,7 +596,7 @@
         //Planar
         case HAL_PIXEL_FORMAT_YV12:
             ystride = hnd->width;
-            cstride = hnd->width/2;
+            cstride = ALIGN(hnd->width/2, 16);
             ycbcr->y  = (void*)hnd->base;
             ycbcr->cr = (void*)(hnd->base + ystride * hnd->height);
             ycbcr->cb = (void*)(hnd->base + ystride * hnd->height +
diff --git a/msm8084/libgralloc/gpu.cpp b/msm8084/libgralloc/gpu.cpp
index 226e259..0782c96 100644
--- a/msm8084/libgralloc/gpu.cpp
+++ b/msm8084/libgralloc/gpu.cpp
@@ -30,6 +30,7 @@
 using namespace gralloc;
 
 #define SZ_1M 0x100000
+#define SZ_2M 0x200000
 
 gpu_context_t::gpu_context_t(const private_module_t* module,
                              IAllocController* alloc_ctrl ) :
@@ -71,7 +72,7 @@
 #ifdef MDSS_TARGET
     if ((usage & GRALLOC_USAGE_PROTECTED) &&
         (usage & GRALLOC_USAGE_PRIVATE_MM_HEAP)) {
-        data.align = ALIGN((int) data.align, SZ_1M);
+        data.align = ALIGN((int) data.align, SZ_2M);
         size = ALIGN(size, data.align);
     }
 #endif
diff --git a/msm8084/libhwcomposer/hwc_mdpcomp.cpp b/msm8084/libhwcomposer/hwc_mdpcomp.cpp
index 08aa4f2..603b8ef 100644
--- a/msm8084/libhwcomposer/hwc_mdpcomp.cpp
+++ b/msm8084/libhwcomposer/hwc_mdpcomp.cpp
@@ -347,7 +347,8 @@
      * There also is a HW limilation in MDP, minimum block size is 2x2
      * Fallback to GPU if height is less than 2.
      */
-    if((crop_w < 5)||(crop_h < 5))
+    if(qdutils::MDPVersion::getInstance().hasMinCropWidthLimitation() and
+            (crop_w < 5 or crop_h < 5))
         return false;
 
     if((w_scale > 1.0f) || (h_scale > 1.0f)) {
@@ -2049,7 +2050,8 @@
             qdutils::MDPVersion::getInstance().isSrcSplitAlways();
     int lSplit = getLeftSplit(ctx, mDpy);
     int dstWidth = dst.right - dst.left;
-    int cropWidth = crop.right - crop.left;
+    int cropWidth = has90Transform(layer) ? crop.bottom - crop.top :
+            crop.right - crop.left;
 
     if(dstWidth > qdutils::MAX_DISPLAY_DIM or
             cropWidth > qdutils::MAX_DISPLAY_DIM or
diff --git a/msm8084/libhwcomposer/hwc_virtual.cpp b/msm8084/libhwcomposer/hwc_virtual.cpp
index 97b19ea..5d3f593 100644
--- a/msm8084/libhwcomposer/hwc_virtual.cpp
+++ b/msm8084/libhwcomposer/hwc_virtual.cpp
@@ -112,9 +112,9 @@
             ctx->dpyAttr[dpy].vsync_period
                               = ctx->dpyAttr[HWC_DISPLAY_PRIMARY].vsync_period;
             init(ctx);
-            // XXX: for architectures with limited resources we would normally
-            // allow one padding round to free up resources but this breaks
-            // certain use cases.
+            // Do a padding round so that primary can free up a pipe for virtual
+            // The virtual composition falls back to GPU for this frame
+            ctx->isPaddingRound = true;
         }
         if(!ctx->dpyAttr[dpy].isPause) {
             ctx->dpyAttr[dpy].isConfiguring = false;
diff --git a/msm8084/liboverlay/overlayMem.h b/msm8084/liboverlay/overlayMem.h
index e8338fb..b2e7dd1 100644
--- a/msm8084/liboverlay/overlayMem.h
+++ b/msm8084/liboverlay/overlayMem.h
@@ -41,6 +41,7 @@
 #include "mdpWrapper.h"
 
 #define SIZE_1M 0x00100000
+#define SIZE_2M 0x00200000
 
 namespace overlay {
 
@@ -138,8 +139,8 @@
     if(isSecure) {
         allocFlags = GRALLOC_USAGE_PRIVATE_MM_HEAP;
         allocFlags |= GRALLOC_USAGE_PROTECTED;
-        mBufSzAligned = utils::align(bufSz, SIZE_1M);
-        data.align = SIZE_1M;
+        mBufSzAligned = utils::align(bufSz, SIZE_2M);
+        data.align = SIZE_2M;
     } else {
         mBufSzAligned = bufSz;
         data.align = getpagesize();
diff --git a/msm8084/libqdutils/mdp_version.cpp b/msm8084/libqdutils/mdp_version.cpp
index a2ecf8a..dcf8af7 100644
--- a/msm8084/libqdutils/mdp_version.cpp
+++ b/msm8084/libqdutils/mdp_version.cpp
@@ -364,6 +364,10 @@
 }
 
 
+bool MDPVersion::hasMinCropWidthLimitation() const {
+    return mMdpRev <= MDSS_MDP_HW_REV_102;
+}
+
 bool MDPVersion::supportsDecimation() {
     return mFeatures & MDP_DECIMATION_EN;
 }
diff --git a/msm8084/libqdutils/mdp_version.h b/msm8084/libqdutils/mdp_version.h
index 7246ad6..94d21f3 100644
--- a/msm8084/libqdutils/mdp_version.h
+++ b/msm8084/libqdutils/mdp_version.h
@@ -139,6 +139,7 @@
     bool needsROIMerge() { return mPanelInfo.mNeedsROIMerge; }
     unsigned long getLowBw() { return mLowBw; }
     unsigned long getHighBw() { return mHighBw; }
+    bool hasMinCropWidthLimitation() const;
     bool isSrcSplit() const;
     bool isSrcSplitAlways() const;
     bool isRGBScalarSupported() const;
diff --git a/msm8226/Android.mk b/msm8226/Android.mk
index 6f4b865..59a9751 100644
--- a/msm8226/Android.mk
+++ b/msm8226/Android.mk
@@ -4,8 +4,7 @@
 ifeq ($(call is-vendor-board-platform,QCOM),true)
     include $(call all-named-subdir-makefiles,$(display-hals))
 else
-ifneq ($(filter msm8226 msm8x26,$(TARGET_BOARD_PLATFORM)),)
-    #This is for mako since it doesn't have the QCOM make functions
+ifneq ($(filter msm% apq%,$(TARGET_BOARD_PLATFORM)),)
     include $(call all-named-subdir-makefiles,$(display-hals))
 endif
 endif
diff --git a/msm8226/common.mk b/msm8226/common.mk
index 83407fb..0bcb288 100644
--- a/msm8226/common.mk
+++ b/msm8226/common.mk
@@ -1,12 +1,12 @@
 #Common headers
-common_includes := hardware/qcom/display/msm8226/libgralloc
-common_includes += hardware/qcom/display/msm8226/liboverlay
-common_includes += hardware/qcom/display/msm8226/libcopybit
-common_includes += hardware/qcom/display/msm8226/libqdutils
-common_includes += hardware/qcom/display/msm8226/libhwcomposer
-common_includes += hardware/qcom/display/msm8226/libexternal
-common_includes += hardware/qcom/display/msm8226/libqservice
-common_includes += hardware/qcom/display/msm8226/libvirtual
+common_includes := $(LOCAL_PATH)/../libgralloc
+common_includes += $(LOCAL_PATH)/../liboverlay
+common_includes += $(LOCAL_PATH)/../libcopybit
+common_includes += $(LOCAL_PATH)/../libqdutils
+common_includes += $(LOCAL_PATH)/../libhwcomposer
+common_includes += $(LOCAL_PATH)/../libexternal
+common_includes += $(LOCAL_PATH)/../libqservice
+common_includes += $(LOCAL_PATH)/../libvirtual
 
 ifeq ($(TARGET_USES_POST_PROCESSING),true)
     common_flags     += -DUSES_POST_PROCESSING
@@ -27,8 +27,8 @@
     common_flags += -D__ARM_HAVE_NEON
 endif
 
-ifeq ($(call is-board-platform-in-list, msm8226 msm8610 apq8084 \
-        mpq8092 msm_bronze msm8916), true)
+ifeq ($(call is-board-platform-in-list, msm8974 msm8226 msm8610 apq8084 \
+        mpq8092 msm_bronze msm8916 msm8994), true)
     common_flags += -DVENUS_COLOR_FORMAT
     common_flags += -DMDSS_TARGET
 endif
diff --git a/msm8226/libcopybit/Android.mk b/msm8226/libcopybit/Android.mk
index 2ac7d15..c239c3a 100644
--- a/msm8226/libcopybit/Android.mk
+++ b/msm8226/libcopybit/Android.mk
@@ -22,7 +22,7 @@
 include $(BUILD_COPY_HEADERS)
 
 LOCAL_MODULE                  := copybit.$(TARGET_BOARD_PLATFORM)
-LOCAL_MODULE_PATH             := $(TARGET_OUT_SHARED_LIBRARIES)/hw
+LOCAL_MODULE_RELATIVE_PATH    := hw
 LOCAL_MODULE_TAGS             := optional
 LOCAL_C_INCLUDES              := $(common_includes) $(kernel_includes)
 LOCAL_SHARED_LIBRARIES        := $(common_libs) libdl libmemalloc
diff --git a/msm8226/libcopybit/copybit.cpp b/msm8226/libcopybit/copybit.cpp
index c0246e3..84d7620 100644
--- a/msm8226/libcopybit/copybit.cpp
+++ b/msm8226/libcopybit/copybit.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.
@@ -154,7 +154,7 @@
     img->width      = rhs->w;
     img->height     = rhs->h;
     img->format     = get_format(rhs->format);
-    img->offset     = hnd->offset;
+    img->offset     = (uint32_t)hnd->offset;
     img->memory_id  = hnd->fd;
 }
 /** setup rectangles */
@@ -162,9 +162,7 @@
                       struct mdp_blit_req *e,
                       const struct copybit_rect_t *dst,
                       const struct copybit_rect_t *src,
-                      const struct copybit_rect_t *scissor,
-                      uint32_t horiz_padding,
-                      uint32_t vert_padding) {
+                      const struct copybit_rect_t *scissor) {
     struct copybit_rect_t clip;
     intersect(&clip, scissor, dst);
 
@@ -312,7 +310,7 @@
             case COPYBIT_PLANE_ALPHA:
                 if (value < 0)      value = MDP_ALPHA_NOP;
                 if (value >= 256)   value = 255;
-                ctx->mAlpha = value;
+                ctx->mAlpha = (uint8_t)value;
                 break;
             case COPYBIT_DITHER:
                 if (value == COPYBIT_ENABLE) {
@@ -491,7 +489,8 @@
                 return -EINVAL;
             }
         }
-        const uint32_t maxCount = sizeof(list->req)/sizeof(list->req[0]);
+        const uint32_t maxCount =
+                (uint32_t)(sizeof(list->req)/sizeof(list->req[0]));
         const struct copybit_rect_t bounds = { 0, 0, (int)dst->w, (int)dst->h };
         struct copybit_rect_t clip;
         status = 0;
@@ -508,7 +507,7 @@
             set_infos(ctx, req, flags);
             set_image(&req->dst, dst);
             set_image(&req->src, src);
-            set_rects(ctx, req, dst_rect, src_rect, &clip, src->horiz_padding, src->vert_padding);
+            set_rects(ctx, req, dst_rect, src_rect, &clip);
 
             if (req->src_rect.w<=0 || req->src_rect.h<=0)
                 continue;
@@ -553,6 +552,9 @@
 static int finish_copybit(struct copybit_device_t *dev)
 {
     // NOP for MDP copybit
+    if(!dev)
+       return -EINVAL;
+
     return 0;
 }
 static int clear_copybit(struct copybit_device_t *dev,
@@ -702,6 +704,10 @@
                         struct hw_device_t** device)
 {
     int status = -EINVAL;
+
+    if (strcmp(name, COPYBIT_HARDWARE_COPYBIT0)) {
+        return COPYBIT_FAILURE;
+    }
     copybit_context_t *ctx;
     ctx = (copybit_context_t *)malloc(sizeof(copybit_context_t));
     memset(ctx, 0, sizeof(*ctx));
diff --git a/msm8226/libcopybit/copybit_c2d.cpp b/msm8226/libcopybit/copybit_c2d.cpp
index 7aad58c..d2b00dd 100644
--- a/msm8226/libcopybit/copybit_c2d.cpp
+++ b/msm8226/libcopybit/copybit_c2d.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.
@@ -78,8 +78,8 @@
 
 C2D_STATUS (*LINK_c2dDestroySurface)( uint32 surface_id );
 
-C2D_STATUS (*LINK_c2dMapAddr) ( int mem_fd, void * hostptr, uint32 len,
-                                uint32 offset, uint32 flags, void ** gpuaddr);
+C2D_STATUS (*LINK_c2dMapAddr) ( int mem_fd, void * hostptr, size_t len,
+                                size_t offset, uint32 flags, void ** gpuaddr);
 
 C2D_STATUS (*LINK_c2dUnMapAddr) ( void * gpuaddr);
 
@@ -145,7 +145,7 @@
     alloc_data temp_src_buffer;
     alloc_data temp_dst_buffer;
     unsigned int dst[NUM_SURFACE_TYPES]; // dst surfaces
-    unsigned int mapped_gpu_addr[MAX_SURFACES]; // GPU addresses mapped inside copybit
+    uintptr_t mapped_gpu_addr[MAX_SURFACES]; // GPU addresses mapped inside copybit
     int blit_rgb_count;         // Total RGB surfaces being blit
     int blit_yuv_2_plane_count; // Total 2 plane YUV surfaces being
     int blit_yuv_3_plane_count; // Total 3 plane YUV  surfaces being blit
@@ -180,8 +180,8 @@
     int yStride;       //luma stride
     int plane1_stride;
     int plane2_stride;
-    int plane1_offset;
-    int plane2_offset;
+    size_t plane1_offset;
+    size_t plane2_offset;
 };
 
 /**
@@ -257,6 +257,8 @@
 static int get_format(int format) {
     switch (format) {
         case HAL_PIXEL_FORMAT_RGB_565:        return C2D_COLOR_FORMAT_565_RGB;
+        case HAL_PIXEL_FORMAT_RGB_888:        return C2D_COLOR_FORMAT_888_RGB |
+                                              C2D_FORMAT_SWAP_RB;
         case HAL_PIXEL_FORMAT_RGBX_8888:      return C2D_COLOR_FORMAT_8888_ARGB |
                                               C2D_FORMAT_SWAP_RB |
                                                   C2D_FORMAT_DISABLE_ALPHA;
@@ -315,6 +317,9 @@
         case C2D_COLOR_FORMAT_8888_ARGB:
             c2dBpp = 32;
             break;
+        case C2D_COLOR_FORMAT_888_RGB:
+            c2dBpp = 24;
+            break;
         case C2D_COLOR_FORMAT_8_L:
         case C2D_COLOR_FORMAT_8_A:
             c2dBpp = 8;
@@ -332,10 +337,11 @@
     return c2dBpp;
 }
 
-static uint32 c2d_get_gpuaddr(copybit_context_t* ctx,
+static size_t c2d_get_gpuaddr(copybit_context_t* ctx,
                               struct private_handle_t *handle, int &mapped_idx)
 {
-    uint32 memtype, *gpuaddr = 0;
+    uint32 memtype;
+    size_t *gpuaddr = 0;
     C2D_STATUS rc;
     int freeindex = 0;
     bool mapaddr = false;
@@ -372,11 +378,11 @@
         if (rc == C2D_STATUS_OK) {
             // We have mapped the GPU address inside copybit. We need to unmap
             // this address after the blit. Store this address
-            ctx->mapped_gpu_addr[freeindex] = (uint32) gpuaddr;
+            ctx->mapped_gpu_addr[freeindex] = (size_t)gpuaddr;
             mapped_idx = freeindex;
         }
     }
-    return (uint32) gpuaddr;
+    return (size_t)gpuaddr;
 }
 
 static void unmap_gpuaddr(copybit_context_t* ctx, int mapped_idx)
@@ -395,6 +401,7 @@
     switch(format) {
         case HAL_PIXEL_FORMAT_RGBA_8888:
         case HAL_PIXEL_FORMAT_RGBX_8888:
+        case HAL_PIXEL_FORMAT_RGB_888:
         case HAL_PIXEL_FORMAT_RGB_565:
         case HAL_PIXEL_FORMAT_BGRA_8888: {
             return COPYBIT_SUCCESS;
@@ -496,7 +503,7 @@
     struct private_handle_t* handle = (struct private_handle_t*)rhs->handle;
     C2D_SURFACE_TYPE surfaceType;
     int status = COPYBIT_SUCCESS;
-    uint32 gpuaddr = 0;
+    uintptr_t gpuaddr = 0;
     int c2d_format;
     mapped_idx = -1;
 
@@ -540,7 +547,7 @@
             ((flags & FLAGS_PREMULTIPLIED_ALPHA) ? C2D_FORMAT_PREMULTIPLIED : 0);
         surfaceDef.width = rhs->w;
         surfaceDef.height = rhs->h;
-        int aligned_width = ALIGN(surfaceDef.width,32);
+        int aligned_width = ALIGN((int)surfaceDef.width,32);
         surfaceDef.stride = (aligned_width * c2diGetBpp(surfaceDef.format))>>3;
 
         if(LINK_c2dUpdateSurface( surfaceId,C2D_TARGET | C2D_SOURCE, surfaceType,
@@ -728,7 +735,8 @@
        (ctx->trg_transform & C2D_TARGET_ROTATE_180)) {
         /* target rotation is 270 */
         c2dObject->target_rect.x        = (dst->t)<<16;
-        c2dObject->target_rect.y        = ctx->fb_width?(ALIGN(ctx->fb_width,32)- dst->r):dst->r;
+        c2dObject->target_rect.y        = ctx->fb_width?
+                (ALIGN(ctx->fb_width,32)- dst->r):dst->r;
         c2dObject->target_rect.y        = c2dObject->target_rect.y<<16;
         c2dObject->target_rect.height   = ((dst->r) - (dst->l))<<16;
         c2dObject->target_rect.width    = ((dst->b) - (dst->t))<<16;
@@ -741,7 +749,8 @@
     } else if(ctx->trg_transform & C2D_TARGET_ROTATE_180) {
         c2dObject->target_rect.y        = ctx->fb_height?(ctx->fb_height - dst->b):dst->b;
         c2dObject->target_rect.y        = c2dObject->target_rect.y<<16;
-        c2dObject->target_rect.x        = ctx->fb_width?(ALIGN(ctx->fb_width,32) - dst->r):dst->r;
+        c2dObject->target_rect.x        = ctx->fb_width?
+                (ALIGN(ctx->fb_width,32) - dst->r):dst->r;
         c2dObject->target_rect.x        = c2dObject->target_rect.x<<16;
         c2dObject->target_rect.height   = ((dst->b) - (dst->t))<<16;
         c2dObject->target_rect.width    = ((dst->r) - (dst->l))<<16;
@@ -953,9 +962,9 @@
 /* Function to get the required size for a particular format, inorder for C2D to perform
  * the blit operation.
  */
-static size_t get_size(const bufferInfo& info)
+static int get_size(const bufferInfo& info)
 {
-    size_t size = 0;
+    int size = 0;
     int w = info.width;
     int h = info.height;
     int aligned_w = ALIGN(w, 32);
@@ -1065,8 +1074,7 @@
     }
 }
 
-static bool need_to_execute_draw(struct copybit_context_t* ctx,
-                                          eC2DFlags flags)
+static bool need_to_execute_draw(eC2DFlags flags)
 {
     if (flags & FLAGS_TEMP_SRC_DST) {
         return true;
@@ -1183,7 +1191,7 @@
         dst_hnd->fd = ctx->temp_dst_buffer.fd;
         dst_hnd->size = ctx->temp_dst_buffer.size;
         dst_hnd->flags = ctx->temp_dst_buffer.allocType;
-        dst_hnd->base = (int)(ctx->temp_dst_buffer.base);
+        dst_hnd->base = (uintptr_t)(ctx->temp_dst_buffer.base);
         dst_hnd->offset = ctx->temp_dst_buffer.offset;
         dst_hnd->gpuaddr = 0;
         dst_image.handle = dst_hnd;
@@ -1268,7 +1276,7 @@
         src_hnd->fd = ctx->temp_src_buffer.fd;
         src_hnd->size = ctx->temp_src_buffer.size;
         src_hnd->flags = ctx->temp_src_buffer.allocType;
-        src_hnd->base = (int)(ctx->temp_src_buffer.base);
+        src_hnd->base = (uintptr_t)(ctx->temp_src_buffer.base);
         src_hnd->offset = ctx->temp_src_buffer.offset;
         src_hnd->gpuaddr = 0;
         src_image.handle = src_hnd;
@@ -1352,7 +1360,7 @@
 
     // Check if we need to perform an early draw-finish.
     flags |= (need_temp_dst || need_temp_src) ? FLAGS_TEMP_SRC_DST : 0;
-    if (need_to_execute_draw(ctx, (eC2DFlags)flags))
+    if (need_to_execute_draw((eC2DFlags)flags))
     {
         finish_copybit(dev);
     }
@@ -1386,8 +1394,11 @@
 }
 
 static int set_sync_copybit(struct copybit_device_t *dev,
-    int acquireFenceFd)
+    int /*acquireFenceFd*/)
 {
+    if(!dev)
+        return -EINVAL;
+
     return 0;
 }
 
@@ -1430,9 +1441,12 @@
 static int fill_color(struct copybit_device_t *dev,
                       struct copybit_image_t const *dst,
                       struct copybit_rect_t const *rect,
-                      uint32_t color)
+                      uint32_t /*color*/)
 {
     // TODO: Implement once c2d driver supports color fill
+    if(!dev || !dst || !rect)
+       return -EINVAL;
+
     return -EINVAL;
 }
 
@@ -1500,10 +1514,13 @@
                         struct hw_device_t** device)
 {
     int status = COPYBIT_SUCCESS;
+    if (strcmp(name, COPYBIT_HARDWARE_COPYBIT0)) {
+        return COPYBIT_FAILURE;
+    }
+
     C2D_RGB_SURFACE_DEF surfDefinition = {0};
     C2D_YUV_SURFACE_DEF yuvSurfaceDef = {0} ;
     struct copybit_context_t *ctx;
-    char fbName[64];
 
     ctx = (struct copybit_context_t *)malloc(sizeof(struct copybit_context_t));
     if(!ctx) {
diff --git a/msm8226/libcopybit/software_converter.cpp b/msm8226/libcopybit/software_converter.cpp
index e26b795..5adacea 100644
--- a/msm8226/libcopybit/software_converter.cpp
+++ b/msm8226/libcopybit/software_converter.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 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
@@ -52,7 +52,7 @@
     unsigned int   width   = src->w - src->horiz_padding;
     unsigned int   height  = src->h;
     unsigned int   y_size  = stride * src->h;
-    unsigned int   c_width = ALIGN(stride/2, 16);
+    unsigned int   c_width = ALIGN(stride/2, (unsigned int)16);
     unsigned int   c_size  = c_width * src->h/2;
     unsigned int   chromaPadding = c_width - width/2;
     unsigned int   chromaSize = c_size * 2;
@@ -128,19 +128,20 @@
     int height;
     int src_stride;
     int dst_stride;
-    int src_plane1_offset;
-    int src_plane2_offset;
-    int dst_plane1_offset;
-    int dst_plane2_offset;
+    size_t src_plane1_offset;
+    size_t src_plane2_offset;
+    size_t dst_plane1_offset;
+    size_t dst_plane2_offset;
 };
 
 /* Internal function to do the actual copy of source to destination */
-static int copy_source_to_destination(const int src_base, const int dst_base,
+static int copy_source_to_destination(const uintptr_t src_base,
+                                      const uintptr_t dst_base,
                                       copyInfo& info)
 {
     if (!src_base || !dst_base) {
-        ALOGE("%s: invalid memory src_base = 0x%x dst_base=0x%x",
-             __FUNCTION__, src_base, dst_base);
+        ALOGE("%s: invalid memory src_base = 0x%p dst_base=0x%p",
+             __FUNCTION__, (void*)src_base, (void*)dst_base);
          return COPYBIT_FAILURE;
     }
 
diff --git a/msm8226/libexternal/Android.mk b/msm8226/libexternal/Android.mk
index 3df6984..05e42d4 100644
--- a/msm8226/libexternal/Android.mk
+++ b/msm8226/libexternal/Android.mk
@@ -3,7 +3,6 @@
 include $(CLEAR_VARS)
 
 LOCAL_MODULE                  := libexternal
-LOCAL_MODULE_PATH             := $(TARGET_OUT_SHARED_LIBRARIES)
 LOCAL_MODULE_TAGS             := optional
 LOCAL_C_INCLUDES              := $(common_includes) $(kernel_includes)
 LOCAL_SHARED_LIBRARIES        := $(common_libs) liboverlay libqdutils
diff --git a/msm8226/libexternal/external.cpp b/msm8226/libexternal/external.cpp
index b08c0c1..982146e 100644
--- a/msm8226/libexternal/external.cpp
+++ b/msm8226/libexternal/external.cpp
@@ -34,7 +34,6 @@
 #include "external.h"
 #include "overlayUtils.h"
 #include "overlay.h"
-#include "mdp_version.h"
 #include "qd_utils.h"
 
 using namespace android;
@@ -192,7 +191,7 @@
         return;
     } else {
         len = read(hdmiScanInfoFile, scanInfo, sizeof(scanInfo)-1);
-        ALOGD("%s: Scan Info string: %s length = %zu",
+        ALOGD("%s: Scan Info string: %s length = %zd",
                  __FUNCTION__, scanInfo, len);
         if (len <= 0) {
             close(hdmiScanInfoFile);
@@ -314,7 +313,7 @@
         return false;
     } else {
         len = read(hdmiEDIDFile, edidStr, sizeof(edidStr)-1);
-        ALOGD_IF(DEBUG, "%s: EDID string: %s length = %zu",
+        ALOGD_IF(DEBUG, "%s: EDID string: %s length = %zd",
                  __FUNCTION__, edidStr, len);
         if ( len <= 0) {
             ALOGE("%s: edid_modes file empty '%s'",
@@ -586,7 +585,7 @@
         mHwcContext->dpyAttr[HWC_DISPLAY_EXTERNAL].xres = width;
         mHwcContext->dpyAttr[HWC_DISPLAY_EXTERNAL].yres = height;
         mHwcContext->dpyAttr[HWC_DISPLAY_EXTERNAL].mDownScaleMode = false;
-        if(!qdutils::MDPVersion::getInstance().is8x26()
+        if(mHwcContext->mOverlay->isUIScalingOnExternalSupported()
                 && mHwcContext->mMDPDownscaleEnabled) {
             int priW = mHwcContext->dpyAttr[HWC_DISPLAY_PRIMARY].xres;
             int priH = mHwcContext->dpyAttr[HWC_DISPLAY_PRIMARY].yres;
@@ -621,6 +620,13 @@
                 mHwcContext->dpyAttr[HWC_DISPLAY_EXTERNAL].mDownScaleMode =true;
             }
         }
+        //Initialize the display viewFrame info
+        mHwcContext->mViewFrame[HWC_DISPLAY_EXTERNAL].left = 0;
+        mHwcContext->mViewFrame[HWC_DISPLAY_EXTERNAL].top = 0;
+        mHwcContext->mViewFrame[HWC_DISPLAY_EXTERNAL].right =
+            (int)mHwcContext->dpyAttr[HWC_DISPLAY_EXTERNAL].xres;
+        mHwcContext->mViewFrame[HWC_DISPLAY_EXTERNAL].bottom =
+            (int)mHwcContext->dpyAttr[HWC_DISPLAY_EXTERNAL].yres;
         mHwcContext->dpyAttr[HWC_DISPLAY_EXTERNAL].vsync_period =
                 (int) 1000000000l / fps;
     }
diff --git a/msm8226/libgralloc/Android.mk b/msm8226/libgralloc/Android.mk
index ef10f54..412f1be 100644
--- a/msm8226/libgralloc/Android.mk
+++ b/msm8226/libgralloc/Android.mk
@@ -18,10 +18,10 @@
 include $(CLEAR_VARS)
 
 LOCAL_MODULE                  := gralloc.$(TARGET_BOARD_PLATFORM)
-LOCAL_MODULE_PATH             := $(TARGET_OUT_SHARED_LIBRARIES)/hw
+LOCAL_MODULE_RELATIVE_PATH    := hw
 LOCAL_MODULE_TAGS             := optional
 LOCAL_C_INCLUDES              := $(common_includes) $(kernel_includes)
-LOCAL_SHARED_LIBRARIES        := $(common_libs) libmemalloc
+LOCAL_SHARED_LIBRARIES        := $(common_libs) libmemalloc libqdMetaData
 LOCAL_SHARED_LIBRARIES        += libqdutils libGLESv1_CM
 LOCAL_CFLAGS                  := $(common_flags) -DLOG_TAG=\"qdgralloc\"
 LOCAL_ADDITIONAL_DEPENDENCIES := $(common_deps) $(kernel_deps)
diff --git a/msm8226/libgralloc/alloc_controller.cpp b/msm8226/libgralloc/alloc_controller.cpp
index 878f17c..b26f4ea 100644
--- a/msm8226/libgralloc/alloc_controller.cpp
+++ b/msm8226/libgralloc/alloc_controller.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011-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
@@ -181,6 +181,7 @@
     } else {
         switch (format)
         {
+            case HAL_PIXEL_FORMAT_YCrCb_420_SP:
             case HAL_PIXEL_FORMAT_YCrCb_420_SP_ADRENO:
             case HAL_PIXEL_FORMAT_RAW_SENSOR:
                 aligned_w = ALIGN(width, 32);
@@ -189,7 +190,6 @@
                 aligned_w = ALIGN(width, 128);
                 break;
             case HAL_PIXEL_FORMAT_YCbCr_420_SP:
-            case HAL_PIXEL_FORMAT_YCrCb_420_SP:
             case HAL_PIXEL_FORMAT_YV12:
             case HAL_PIXEL_FORMAT_YCbCr_422_SP:
             case HAL_PIXEL_FORMAT_YCrCb_422_SP:
@@ -271,7 +271,12 @@
 //-------------- IonController-----------------------//
 IonController::IonController()
 {
-    mIonAlloc = new IonAlloc();
+    allocateIonMem();
+}
+
+void IonController::allocateIonMem()
+{
+   mIonAlloc = new IonAlloc();
 }
 
 int IonController::allocate(alloc_data& data, int usage)
@@ -389,9 +394,9 @@
 }
 
 // helper function
-size_t getSize(int format, int width, int height, const int alignedw,
+unsigned int getSize(int format, int width, int height, const int alignedw,
         const int alignedh) {
-    size_t size = 0;
+    unsigned int size = 0;
 
     switch (format) {
         case HAL_PIXEL_FORMAT_RGBA_8888:
@@ -428,7 +433,7 @@
             }
             size = alignedw*alignedh +
                     (ALIGN(alignedw/2, 16) * (alignedh/2))*2;
-            size = ALIGN(size, 4096);
+            size = ALIGN(size, (unsigned int)4096);
             break;
         case HAL_PIXEL_FORMAT_YCbCr_420_SP:
         case HAL_PIXEL_FORMAT_YCrCb_420_SP:
@@ -496,10 +501,10 @@
     return size;
 }
 
-size_t getBufferSizeAndDimensions(int width, int height, int format,
+unsigned int getBufferSizeAndDimensions(int width, int height, int format,
         int& alignedw, int &alignedh)
 {
-    size_t size;
+    unsigned int size;
 
     AdrenoMemInfo::getInstance().getAlignedWidthAndHeight(width,
             height,
@@ -514,10 +519,10 @@
 }
 
 
-size_t getBufferSizeAndDimensions(int width, int height, int format, int usage,
-        int& alignedw, int &alignedh)
+unsigned int getBufferSizeAndDimensions(int width, int height, int format,
+        int usage, int& alignedw, int &alignedh)
 {
-    size_t size;
+    unsigned int size;
     int tileEnabled = isMacroTileEnabled(format, usage);
 
     AdrenoMemInfo::getInstance().getAlignedWidthAndHeight(width,
@@ -534,7 +539,7 @@
 
 
 void getBufferAttributes(int width, int height, int format, int usage,
-        int& alignedw, int &alignedh, int& tileEnabled, size_t& size)
+        int& alignedw, int &alignedh, int& tileEnabled, unsigned int& size)
 {
     tileEnabled = isMacroTileEnabled(format, usage);
 
@@ -547,6 +552,69 @@
     size = getSize(format, width, height, alignedw, alignedh);
 }
 
+int getYUVPlaneInfo(private_handle_t* hnd, struct android_ycbcr* ycbcr)
+{
+    int err = 0;
+    unsigned int ystride, cstride;
+    memset(ycbcr->reserved, 0, sizeof(ycbcr->reserved));
+
+    // Get the chroma offsets from the handle width/height. We take advantage
+    // of the fact the width _is_ the stride
+    switch (hnd->format) {
+        //Semiplanar
+        case HAL_PIXEL_FORMAT_YCbCr_420_SP:
+        case HAL_PIXEL_FORMAT_YCbCr_422_SP:
+        case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS:
+        case HAL_PIXEL_FORMAT_NV12_ENCODEABLE: //Same as YCbCr_420_SP_VENUS
+            ystride = cstride = hnd->width;
+            ycbcr->y  = (void*)hnd->base;
+            ycbcr->cb = (void*)(hnd->base + ystride * hnd->height);
+            ycbcr->cr = (void*)(hnd->base + ystride * hnd->height + 1);
+            ycbcr->ystride = ystride;
+            ycbcr->cstride = cstride;
+            ycbcr->chroma_step = 2;
+        break;
+
+        case HAL_PIXEL_FORMAT_YCrCb_420_SP:
+        case HAL_PIXEL_FORMAT_YCrCb_422_SP:
+        case HAL_PIXEL_FORMAT_YCrCb_420_SP_ADRENO:
+        case HAL_PIXEL_FORMAT_NV21_ZSL:
+        case HAL_PIXEL_FORMAT_RAW_SENSOR:
+            ystride = cstride = hnd->width;
+            ycbcr->y  = (void*)hnd->base;
+            ycbcr->cr = (void*)(hnd->base + ystride * hnd->height);
+            ycbcr->cb = (void*)(hnd->base + ystride * hnd->height + 1);
+            ycbcr->ystride = ystride;
+            ycbcr->cstride = cstride;
+            ycbcr->chroma_step = 2;
+        break;
+
+        //Planar
+        case HAL_PIXEL_FORMAT_YV12:
+            ystride = hnd->width;
+            cstride = ALIGN(hnd->width/2, 16);
+            ycbcr->y  = (void*)hnd->base;
+            ycbcr->cr = (void*)(hnd->base + ystride * hnd->height);
+            ycbcr->cb = (void*)(hnd->base + ystride * hnd->height +
+                    cstride * hnd->height/2);
+            ycbcr->ystride = ystride;
+            ycbcr->cstride = cstride;
+            ycbcr->chroma_step = 1;
+
+        break;
+        //Unsupported formats
+        case HAL_PIXEL_FORMAT_YCbCr_422_I:
+        case HAL_PIXEL_FORMAT_YCrCb_422_I:
+        case HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED:
+        default:
+        ALOGD("%s: Invalid format passed: 0x%x", __FUNCTION__,
+                hnd->format);
+        err = -EINVAL;
+    }
+    return err;
+
+}
+
 
 
 // Allocate buffer from width, height and format into a
@@ -577,7 +645,7 @@
     private_handle_t* hnd = new private_handle_t(data.fd, data.size,
                                                  data.allocType, 0, format,
                                                  alignedw, alignedh);
-    hnd->base = (int) data.base;
+    hnd->base = (uint64_t) data.base;
     hnd->offset = data.offset;
     hnd->gpuaddr = 0;
     *pHnd = hnd;
diff --git a/msm8226/libgralloc/alloc_controller.h b/msm8226/libgralloc/alloc_controller.h
index 5fe81fa..f0b8ed9 100644
--- a/msm8226/libgralloc/alloc_controller.h
+++ b/msm8226/libgralloc/alloc_controller.h
@@ -65,6 +65,7 @@
 
     private:
     IonAlloc* mIonAlloc;
+    void allocateIonMem();
 
 };
 } //end namespace gralloc
diff --git a/msm8226/libgralloc/fb_priv.h b/msm8226/libgralloc/fb_priv.h
index 01af2e1..7ff1f3a 100644
--- a/msm8226/libgralloc/fb_priv.h
+++ b/msm8226/libgralloc/fb_priv.h
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2008 The Android Open Source Project
- * Copyright (c) 2012, 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.
@@ -51,7 +51,6 @@
     float ydpi;
     float fps;
     uint32_t swapInterval;
-    uint32_t currentOffset;
 };
 
 
diff --git a/msm8226/libgralloc/framebuffer.cpp b/msm8226/libgralloc/framebuffer.cpp
index a7a58dc..2ce5dc6 100644
--- a/msm8226/libgralloc/framebuffer.cpp
+++ b/msm8226/libgralloc/framebuffer.cpp
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2008 The Android Open Source Project
- * Copyright (c) 2010-2012 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2010-2012,2014 The Linux Foundation. All rights reserved.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -72,7 +72,6 @@
     if (property_interval >= 0)
         interval = property_interval;
 
-    fb_context_t* ctx = (fb_context_t*)dev;
     private_module_t* m = reinterpret_cast<private_module_t*>(
         dev->common.module);
     if (interval < dev->minSwapInterval || interval > dev->maxSwapInterval)
@@ -88,9 +87,10 @@
         reinterpret_cast<private_module_t*>(dev->common.module);
     private_handle_t *hnd = static_cast<private_handle_t*>
         (const_cast<native_handle_t*>(buffer));
-    const size_t offset = hnd->base - m->framebuffer->base;
+    const unsigned int offset = (unsigned int) (hnd->base -
+            m->framebuffer->base);
     m->info.activate = FB_ACTIVATE_VBL;
-    m->info.yoffset = offset / m->finfo.line_length;
+    m->info.yoffset = (int)(offset / m->finfo.line_length);
     if (ioctl(m->framebuffer->fd, FBIOPUT_VSCREENINFO, &m->info) == -1) {
         ALOGE("%s: FBIOPUT_VSCREENINFO for primary failed, str: %s",
                 __FUNCTION__, strerror(errno));
@@ -102,6 +102,9 @@
 static int fb_compositionComplete(struct framebuffer_device_t* dev)
 {
     // TODO: Properly implement composition complete callback
+    if(!dev) {
+        return -1;
+    }
     glFinish();
 
     return 0;
@@ -202,8 +205,8 @@
     }
 
     //adreno needs 4k aligned offsets. Max hole size is 4096-1
-    int  size = roundUpToPageSize(info.yres * info.xres *
-                                                       (info.bits_per_pixel/8));
+    unsigned int size = roundUpToPageSize(info.yres * info.xres *
+                                               (info.bits_per_pixel/8));
 
     /*
      * Request NUM_BUFFERS screens (at least 2 for page flipping)
@@ -224,13 +227,13 @@
 
     //consider the included hole by 4k alignment
     uint32_t line_length = (info.xres * info.bits_per_pixel / 8);
-    info.yres_virtual = (size * numberOfBuffers) / line_length;
+    info.yres_virtual = (uint32_t) ((size * numberOfBuffers) / line_length);
 
     uint32_t flags = PAGE_FLIP;
 
     if (info.yres_virtual < ((size * 2) / line_length) ) {
         // we need at least 2 for page-flipping
-        info.yres_virtual = size / line_length;
+        info.yres_virtual = (int)(size / line_length);
         flags &= ~PAGE_FLIP;
         ALOGW("page flipping not supported (yres_virtual=%d, requested=%d)",
               info.yres_virtual, info.yres*2);
@@ -244,12 +247,13 @@
     if (int(info.width) <= 0 || int(info.height) <= 0) {
         // the driver doesn't return that information
         // default to 160 dpi
-        info.width  = ((info.xres * 25.4f)/160.0f + 0.5f);
-        info.height = ((info.yres * 25.4f)/160.0f + 0.5f);
+        info.width  = (uint32_t)(((float)(info.xres) * 25.4f)/160.0f + 0.5f);
+        info.height = (uint32_t)(((float)(info.yres) * 25.4f)/160.0f + 0.5f);
     }
 
-    float xdpi = (info.xres * 25.4f) / info.width;
-    float ydpi = (info.yres * 25.4f) / info.height;
+    float xdpi = ((float)(info.xres) * 25.4f) / (float)info.width;
+    float ydpi = ((float)(info.yres) * 25.4f) / (float)info.height;
+
 #ifdef MSMFB_METADATA_GET
     struct msmfb_metadata metadata;
     memset(&metadata, 0 , sizeof(metadata));
@@ -259,7 +263,7 @@
         close(fd);
         return -errno;
     }
-    float fps  = metadata.data.panel_frame_rate;
+    float fps = (float)metadata.data.panel_frame_rate;
 #else
     //XXX: Remove reserved field usage on all baselines
     //The reserved[3] field is used to store FPS by the driver.
@@ -320,11 +324,10 @@
      * map the framebuffer
      */
 
-    int err;
     module->numBuffers = info.yres_virtual / info.yres;
     module->bufferMask = 0;
     //adreno needs page aligned offsets. Align the fbsize to pagesize.
-    size_t fbSize = roundUpToPageSize(finfo.line_length * info.yres)*
+    unsigned int fbSize = roundUpToPageSize(finfo.line_length * info.yres)*
                     module->numBuffers;
     module->framebuffer = new private_handle_t(fd, fbSize,
                                         private_handle_t::PRIV_FLAGS_USES_ION,
@@ -336,9 +339,8 @@
         close(fd);
         return -errno;
     }
-    module->framebuffer->base = intptr_t(vaddr);
+    module->framebuffer->base = uint64_t(vaddr);
     memset(vaddr, 0, fbSize);
-    module->currentOffset = 0;
     //Enable vsync
     int enable = 1;
     ioctl(module->framebuffer->fd, MSMFB_OVERLAY_VSYNC_CTRL,
diff --git a/msm8226/libgralloc/gpu.cpp b/msm8226/libgralloc/gpu.cpp
index b6253cd..8739f34 100644
--- a/msm8226/libgralloc/gpu.cpp
+++ b/msm8226/libgralloc/gpu.cpp
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2010 The Android Open Source Project
- * Copyright (c) 2011-2013 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011-2014 The Linux Foundation. All rights reserved.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -51,7 +51,7 @@
 
 }
 
-int gpu_context_t::gralloc_alloc_buffer(size_t size, int usage,
+int gpu_context_t::gralloc_alloc_buffer(unsigned int size, int usage,
                                         buffer_handle_t* pHandle, int bufferType,
                                         int format, int width, int height)
 {
@@ -69,14 +69,15 @@
 
     /* force 1MB alignment selectively for secure buffers, MDP5 onwards */
 #ifdef MDSS_TARGET
-    if (usage & GRALLOC_USAGE_PROTECTED) {
-        data.align = ALIGN(data.align, SZ_1M);
+    if ((usage & GRALLOC_USAGE_PROTECTED) &&
+        (usage & GRALLOC_USAGE_PRIVATE_MM_HEAP)) {
+        data.align = ALIGN((int) data.align, SZ_1M);
         size = ALIGN(size, data.align);
     }
 #endif
 
     data.size = size;
-    data.pHandle = (unsigned int) pHandle;
+    data.pHandle = (uintptr_t) pHandle;
     err = mAllocCtrl->allocate(data, usage);
 
     if (!err) {
@@ -97,9 +98,12 @@
             flags |= private_handle_t::PRIV_FLAGS_EXTERNAL_ONLY;
         }
 
+        ColorSpace_t colorSpace = ITU_R_601;
+        flags |= private_handle_t::PRIV_FLAGS_ITU_R_601;
         if (bufferType == BUFFER_TYPE_VIDEO) {
             if (usage & GRALLOC_USAGE_HW_CAMERA_WRITE) {
 #ifndef MDSS_TARGET
+                colorSpace = ITU_R_601_FR;
                 flags |= private_handle_t::PRIV_FLAGS_ITU_R_601_FR;
 #else
                 // Per the camera spec ITU 709 format should be set only for
@@ -108,14 +112,15 @@
                 // camera buffer
                 //
                 if (usage & GRALLOC_USAGE_HW_CAMERA_MASK) {
-                    if (usage & GRALLOC_USAGE_HW_VIDEO_ENCODER)
+                    if (usage & GRALLOC_USAGE_HW_VIDEO_ENCODER) {
                         flags |= private_handle_t::PRIV_FLAGS_ITU_R_709;
-                    else
+                        colorSpace = ITU_R_709;
+                    } else {
                         flags |= private_handle_t::PRIV_FLAGS_ITU_R_601_FR;
+                        colorSpace = ITU_R_601_FR;
+                    }
                 }
 #endif
-            } else {
-                flags |= private_handle_t::PRIV_FLAGS_ITU_R_601;
             }
         }
 
@@ -147,15 +152,20 @@
             flags |= private_handle_t::PRIV_FLAGS_TILE_RENDERED;
         }
 
+        if(usage & (GRALLOC_USAGE_SW_READ_MASK | GRALLOC_USAGE_SW_WRITE_MASK)) {
+            flags |= private_handle_t::PRIV_FLAGS_CPU_RENDERED;
+        }
+
         flags |= data.allocType;
-        int eBaseAddr = int(eData.base) + eData.offset;
+        uint64_t eBaseAddr = (uint64_t)(eData.base) + eData.offset;
         private_handle_t *hnd = new private_handle_t(data.fd, size, flags,
                 bufferType, format, width, height, eData.fd, eData.offset,
                 eBaseAddr);
 
         hnd->offset = data.offset;
-        hnd->base = int(data.base) + data.offset;
+        hnd->base = (uint64_t)(data.base) + data.offset;
         hnd->gpuaddr = 0;
+        setMetaData(hnd, UPDATE_COLOR_SPACE, (void*) &colorSpace);
 
         *pHandle = hnd;
     }
@@ -170,9 +180,6 @@
 {
     *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;
@@ -182,7 +189,7 @@
     }
 }
 
-int gpu_context_t::gralloc_alloc_framebuffer_locked(size_t size, int usage,
+int gpu_context_t::gralloc_alloc_framebuffer_locked(int usage,
                                                     buffer_handle_t* pHandle)
 {
     private_module_t* m = reinterpret_cast<private_module_t*>(common.module);
@@ -197,9 +204,9 @@
         return -EINVAL;
     }
 
-    const uint32_t bufferMask = m->bufferMask;
+    const unsigned int bufferMask = m->bufferMask;
     const uint32_t numBuffers = m->numBuffers;
-    size_t bufferSize = m->finfo.line_length * m->info.yres;
+    unsigned int bufferSize = m->finfo.line_length * m->info.yres;
 
     //adreno needs FB size to be page aligned
     bufferSize = roundUpToPageSize(bufferSize);
@@ -219,7 +226,7 @@
     }
 
     // create a "fake" handle for it
-    intptr_t vaddr = intptr_t(m->framebuffer->base);
+    uint64_t vaddr = uint64_t(m->framebuffer->base);
     private_handle_t* hnd = new private_handle_t(
         dup(m->framebuffer->fd), bufferSize,
         private_handle_t::PRIV_FLAGS_USES_PMEM |
@@ -230,42 +237,43 @@
     // find a free slot
     for (uint32_t i=0 ; i<numBuffers ; i++) {
         if ((bufferMask & (1LU<<i)) == 0) {
-            m->bufferMask |= (1LU<<i);
+            m->bufferMask |= (uint32_t)(1LU<<i);
             break;
         }
         vaddr += bufferSize;
     }
     hnd->base = vaddr;
-    hnd->offset = vaddr - intptr_t(m->framebuffer->base);
+    hnd->offset = (unsigned int)(vaddr - m->framebuffer->base);
     *pHandle = hnd;
     return 0;
 }
 
 
-int gpu_context_t::gralloc_alloc_framebuffer(size_t size, int usage,
+int gpu_context_t::gralloc_alloc_framebuffer(int usage,
                                              buffer_handle_t* pHandle)
 {
     private_module_t* m = reinterpret_cast<private_module_t*>(common.module);
     pthread_mutex_lock(&m->lock);
-    int err = gralloc_alloc_framebuffer_locked(size, usage, pHandle);
+    int err = gralloc_alloc_framebuffer_locked(usage, pHandle);
     pthread_mutex_unlock(&m->lock);
     return err;
 }
 
 int gpu_context_t::alloc_impl(int w, int h, int format, int usage,
                               buffer_handle_t* pHandle, int* pStride,
-                              size_t bufferSize) {
+                              unsigned int bufferSize) {
     if (!pHandle || !pStride)
         return -EINVAL;
 
-    size_t size;
+    unsigned int size;
     int alignedw, alignedh;
     int grallocFormat = format;
     int bufferType;
 
     //If input format is HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED then based on
     //the usage bits, gralloc assigns a format.
-    if(format == HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED) {
+    if(format == HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED ||
+       format == HAL_PIXEL_FORMAT_YCbCr_420_888) {
         if(usage & GRALLOC_USAGE_HW_VIDEO_ENCODER)
             grallocFormat = HAL_PIXEL_FORMAT_NV12_ENCODEABLE; //NV12
         else if((usage & GRALLOC_USAGE_HW_CAMERA_MASK)
@@ -284,7 +292,7 @@
     size = getBufferSizeAndDimensions(w, h, grallocFormat, usage, alignedw,
                    alignedh);
 
-    if ((ssize_t)size <= 0)
+    if ((unsigned int)size <= 0)
         return -EINVAL;
     size = (bufferSize >= size)? bufferSize : size;
 
@@ -299,7 +307,7 @@
 
     int err = 0;
     if(useFbMem) {
-        err = gralloc_alloc_framebuffer(size, usage, pHandle);
+        err = gralloc_alloc_framebuffer(usage, pHandle);
     } else {
         err = gralloc_alloc_buffer(size, usage, pHandle, bufferType,
                                    grallocFormat, alignedw, alignedh);
@@ -316,21 +324,22 @@
 int gpu_context_t::free_impl(private_handle_t const* hnd) {
     private_module_t* m = reinterpret_cast<private_module_t*>(common.module);
     if (hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER) {
-        const size_t bufferSize = m->finfo.line_length * m->info.yres;
-        int index = (hnd->base - m->framebuffer->base) / bufferSize;
-        m->bufferMask &= ~(1<<index);
+        const unsigned int bufferSize = m->finfo.line_length * m->info.yres;
+        unsigned int index = (unsigned int) ((hnd->base - m->framebuffer->base)
+                / bufferSize);
+        m->bufferMask &= (uint32_t)~(1LU<<index);
     } else {
 
         terminateBuffer(&m->base, const_cast<private_handle_t*>(hnd));
         IMemAlloc* memalloc = mAllocCtrl->getAllocator(hnd->flags);
-        int err = memalloc->free_buffer((void*)hnd->base, (size_t) hnd->size,
+        int err = memalloc->free_buffer((void*)hnd->base, hnd->size,
                                         hnd->offset, hnd->fd);
         if(err)
             return err;
         // free the metadata space
-        unsigned long size = ROUND_UP_PAGESIZE(sizeof(MetaData_t));
+        unsigned int size = ROUND_UP_PAGESIZE(sizeof(MetaData_t));
         err = memalloc->free_buffer((void*)hnd->base_metadata,
-                                    (size_t) size, hnd->offset_metadata,
+                                    size, hnd->offset_metadata,
                                     hnd->fd_metadata);
         if (err)
             return err;
diff --git a/msm8226/libgralloc/gpu.h b/msm8226/libgralloc/gpu.h
index 5515759..262aed5 100644
--- a/msm8226/libgralloc/gpu.h
+++ b/msm8226/libgralloc/gpu.h
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2008 The Android Open Source Project
- * Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011-2012,2014, The Linux Foundation. All rights reserved.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -35,7 +35,7 @@
     gpu_context_t(const private_module_t* module,
                   IAllocController* alloc_ctrl);
 
-    int gralloc_alloc_buffer(size_t size, int usage,
+    int gralloc_alloc_buffer(unsigned int size, int usage,
                              buffer_handle_t* pHandle,
                              int bufferType, int format,
                              int width, int height);
@@ -44,16 +44,16 @@
 
     int alloc_impl(int w, int h, int format, int usage,
                    buffer_handle_t* pHandle, int* pStride,
-                   size_t bufferSize = 0);
+                   unsigned int bufferSize = 0);
 
     static int gralloc_alloc(alloc_device_t* dev, int w, int h,
                              int format, int usage,
                              buffer_handle_t* pHandle,
                              int* pStride);
-    int gralloc_alloc_framebuffer_locked(size_t size, int usage,
+    int gralloc_alloc_framebuffer_locked(int usage,
                                          buffer_handle_t* pHandle);
 
-    int gralloc_alloc_framebuffer(size_t size, int usage,
+    int gralloc_alloc_framebuffer(int usage,
                                   buffer_handle_t* pHandle);
 
     static int gralloc_free(alloc_device_t* dev, buffer_handle_t handle);
diff --git a/msm8226/libgralloc/gr.h b/msm8226/libgralloc/gr.h
index 73b176b..797d57e 100644
--- a/msm8226/libgralloc/gr.h
+++ b/msm8226/libgralloc/gr.h
@@ -33,11 +33,12 @@
 struct private_module_t;
 struct private_handle_t;
 
-inline size_t roundUpToPageSize(size_t x) {
+inline unsigned int roundUpToPageSize(unsigned int x) {
     return (x + (PAGE_SIZE-1)) & ~(PAGE_SIZE-1);
 }
 
-inline size_t ALIGN(size_t x, size_t align) {
+template <class Type>
+inline Type ALIGN(Type x, Type align) {
     return (x + align-1) & ~(align-1);
 }
 
@@ -46,16 +47,16 @@
 
 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);
+unsigned int getBufferSizeAndDimensions(int width, int height, int format,
+        int usage, int& alignedw, int &alignedh);
+unsigned int getBufferSizeAndDimensions(int width, int height, int format,
+        int& alignedw, int &alignedh);
 
 
 // Attributes include aligned width, aligned height, tileEnabled and size of the buffer
 void getBufferAttributes(int width, int height, int format, int usage,
                            int& alignedw, int &alignedh,
-                           int& tileEnabled, size_t &size);
+                           int& tileEnabled, unsigned int &size);
 
 
 bool isMacroTileEnabled(int format, int usage);
@@ -68,11 +69,13 @@
 // It is the responsibility of the caller to free the buffer
 int alloc_buffer(private_handle_t **pHnd, int w, int h, int format, int usage);
 void free_buffer(private_handle_t *hnd);
+int getYUVPlaneInfo(private_handle_t* pHnd, struct android_ycbcr* ycbcr);
 
 /*****************************************************************************/
 
 class Locker {
     pthread_mutex_t mutex;
+    pthread_cond_t cond;
     public:
     class Autolock {
         Locker& locker;
@@ -80,10 +83,18 @@
         inline Autolock(Locker& locker) : locker(locker) {  locker.lock(); }
         inline ~Autolock() { locker.unlock(); }
     };
-    inline Locker()        { pthread_mutex_init(&mutex, 0); }
-    inline ~Locker()       { pthread_mutex_destroy(&mutex); }
+    inline Locker()        {
+        pthread_mutex_init(&mutex, 0);
+        pthread_cond_init(&cond, 0);
+    }
+    inline ~Locker()       {
+        pthread_mutex_destroy(&mutex);
+        pthread_cond_destroy(&cond);
+    }
     inline void lock()     { pthread_mutex_lock(&mutex); }
+    inline void wait()     { pthread_cond_wait(&cond, &mutex); }
     inline void unlock()   { pthread_mutex_unlock(&mutex); }
+    inline void signal()   { pthread_cond_signal(&cond); }
 };
 
 
diff --git a/msm8226/libgralloc/gralloc.cpp b/msm8226/libgralloc/gralloc.cpp
index b21ce75..c1c61aa 100644
--- a/msm8226/libgralloc/gralloc.cpp
+++ b/msm8226/libgralloc/gralloc.cpp
@@ -42,6 +42,11 @@
                         int l, int t, int w, int h,
                         void** vaddr);
 
+extern int gralloc_lock_ycbcr(gralloc_module_t const* module,
+                        buffer_handle_t handle, int usage,
+                        int l, int t, int w, int h,
+                        struct android_ycbcr *ycbcr);
+
 extern int gralloc_unlock(gralloc_module_t const* module,
                           buffer_handle_t handle);
 
@@ -56,36 +61,37 @@
 
 // HAL module methods
 static struct hw_module_methods_t gralloc_module_methods = {
-open: gralloc_device_open
+    open: gralloc_device_open
 };
 
 // HAL module initialize
 struct private_module_t HAL_MODULE_INFO_SYM = {
-base: {
-    common: {
-        tag: HARDWARE_MODULE_TAG,
-             version_major: 1,
-             version_minor: 0,
-             id: GRALLOC_HARDWARE_MODULE_ID,
-             name: "Graphics Memory Allocator Module",
-             author: "The Android Open Source Project",
-             methods: &gralloc_module_methods,
-             dso: 0,
-             reserved: {0},
-            },
-    registerBuffer: gralloc_register_buffer,
-    unregisterBuffer: gralloc_unregister_buffer,
-    lock: gralloc_lock,
-    unlock: gralloc_unlock,
-    perform: gralloc_perform,
-      },
-framebuffer: 0,
-fbFormat: 0,
-flags: 0,
-numBuffers: 0,
-bufferMask: 0,
-lock: PTHREAD_MUTEX_INITIALIZER,
-currentBuffer: 0,
+    base: {
+        common: {
+            tag: HARDWARE_MODULE_TAG,
+            version_major: 1,
+            version_minor: 0,
+            id: GRALLOC_HARDWARE_MODULE_ID,
+            name: "Graphics Memory Allocator Module",
+            author: "The Android Open Source Project",
+            methods: &gralloc_module_methods,
+            dso: 0,
+            reserved: {0},
+        },
+        registerBuffer: gralloc_register_buffer,
+        unregisterBuffer: gralloc_unregister_buffer,
+        lock: gralloc_lock,
+        unlock: gralloc_unlock,
+        perform: gralloc_perform,
+        lock_ycbcr: gralloc_lock_ycbcr,
+    },
+    framebuffer: 0,
+    fbFormat: 0,
+    flags: 0,
+    numBuffers: 0,
+    bufferMask: 0,
+    lock: PTHREAD_MUTEX_INITIALIZER,
+    currentBuffer: 0,
 };
 
 // Open Gralloc device
@@ -99,6 +105,9 @@
         gpu_context_t *dev;
         IAllocController* alloc_ctrl = IAllocController::getInstance();
         dev = new gpu_context_t(m, alloc_ctrl);
+        if(!dev)
+            return status;
+
         *device = &dev->common;
         status = 0;
     } else {
diff --git a/msm8226/libgralloc/gralloc_priv.h b/msm8226/libgralloc/gralloc_priv.h
index 89f1a88..f029b80 100644
--- a/msm8226/libgralloc/gralloc_priv.h
+++ b/msm8226/libgralloc/gralloc_priv.h
@@ -79,8 +79,10 @@
     // libraries
     GRALLOC_MODULE_PERFORM_GET_STRIDE,
     GRALLOC_MODULE_PERFORM_GET_CUSTOM_STRIDE_FROM_HANDLE,
+    GRALLOC_MODULE_PERFORM_GET_CUSTOM_STRIDE_AND_HEIGHT_FROM_HANDLE,
     GRALLOC_MODULE_PERFORM_GET_ATTRIBUTES,
     GRALLOC_MODULE_PERFORM_GET_COLOR_SPACE_FROM_HANDLE,
+    GRALLOC_MODULE_PERFORM_GET_YUV_PLANE_INFO,
 };
 
 #define GRALLOC_HEAP_MASK   (GRALLOC_USAGE_PRIVATE_UI_CONTIG_HEAP |\
@@ -200,7 +202,9 @@
             PRIV_FLAGS_ITU_R_709          = 0x00800000,
             PRIV_FLAGS_SECURE_DISPLAY     = 0x01000000,
             // Buffer is rendered in Tile Format
-            PRIV_FLAGS_TILE_RENDERED      = 0x02000000
+            PRIV_FLAGS_TILE_RENDERED      = 0x02000000,
+            // Buffer rendered using CPU/SW renderer
+            PRIV_FLAGS_CPU_RENDERED       = 0x04000000
         };
 
         // file-descriptors
@@ -209,34 +213,37 @@
         // ints
         int     magic;
         int     flags;
-        int     size;
-        int     offset;
+        unsigned int  size;
+        unsigned int  offset;
         int     bufferType;
-        int     base;
-        int     offset_metadata;
+        uint64_t base __attribute__((aligned(8)));
+        unsigned int  offset_metadata;
         // The gpu address mapped into the mmu.
-        int     gpuaddr;
+        uint64_t gpuaddr __attribute__((aligned(8)));
         int     format;
         int     width;
         int     height;
-        int     base_metadata;
+        uint64_t base_metadata __attribute__((aligned(8)));
 
 #ifdef __cplusplus
-        static const int sNumInts = 12;
         static const int sNumFds = 2;
+        static inline int sNumInts() {
+            return ((sizeof(private_handle_t) - sizeof(native_handle_t)) /
+                    sizeof(int)) - sNumFds;
+        }
         static const int sMagic = 'gmsm';
 
-        private_handle_t(int fd, int size, int flags, int bufferType,
-                         int format,int width, int height, int eFd = -1,
-                         int eOffset = 0, int eBase = 0) :
+        private_handle_t(int fd, unsigned int size, int flags, int bufferType,
+                         int format, int width, int height, int eFd = -1,
+                         unsigned int eOffset = 0, uint64_t eBase = 0) :
             fd(fd), fd_metadata(eFd), magic(sMagic),
             flags(flags), size(size), offset(0), bufferType(bufferType),
             base(0), offset_metadata(eOffset), gpuaddr(0),
             format(format), width(width), height(height),
             base_metadata(eBase)
         {
-            version = sizeof(native_handle);
-            numInts = sNumInts;
+            version = (int) sizeof(native_handle);
+            numInts = sNumInts();
             numFds = sNumFds;
         }
         ~private_handle_t() {
@@ -250,14 +257,15 @@
         static int validate(const native_handle* h) {
             const private_handle_t* hnd = (const private_handle_t*)h;
             if (!h || h->version != sizeof(native_handle) ||
-                h->numInts != sNumInts || h->numFds != sNumFds ||
+                h->numInts != sNumInts() || h->numFds != sNumFds ||
                 hnd->magic != sMagic)
             {
                 ALOGD("Invalid gralloc handle (at %p): "
-                      "ver(%d/%d) ints(%d/%d) fds(%d/%d) magic(%c%c%c%c/%c%c%c%c)",
+                      "ver(%d/%zu) ints(%d/%d) fds(%d/%d)"
+                      "magic(%c%c%c%c/%c%c%c%c)",
                       h,
                       h ? h->version : -1, sizeof(native_handle),
-                      h ? h->numInts : -1, sNumInts,
+                      h ? h->numInts : -1, sNumInts(),
                       h ? h->numFds : -1, sNumFds,
                       hnd ? (((hnd->magic >> 24) & 0xFF)?
                              ((hnd->magic >> 24) & 0xFF) : '-') : '?',
diff --git a/msm8226/libgralloc/ionalloc.cpp b/msm8226/libgralloc/ionalloc.cpp
index bb6c2c8..10a662d 100644
--- a/msm8226/libgralloc/ionalloc.cpp
+++ b/msm8226/libgralloc/ionalloc.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011-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
@@ -73,7 +73,7 @@
 
     ionAllocData.len = data.size;
     ionAllocData.align = data.align;
-    ionAllocData.heap_mask = data.flags & ~ION_SECURE;
+    ionAllocData.heap_id_mask = data.flags & ~ION_SECURE;
     ionAllocData.flags = data.uncached ? 0 : ION_FLAG_CACHED;
     // ToDo: replace usage of alloc data structure with
     //  ionallocdata structure.
@@ -114,16 +114,17 @@
     data.base = base;
     data.fd = fd_data.fd;
     ioctl(mIonFd, ION_IOC_FREE, &handle_data);
-    ALOGD_IF(DEBUG, "ion: Allocated buffer base:%p size:%d fd:%d",
+    ALOGD_IF(DEBUG, "ion: Allocated buffer base:%p size:%zu fd:%d",
           data.base, ionAllocData.len, data.fd);
     return 0;
 }
 
 
-int IonAlloc::free_buffer(void* base, size_t size, int offset, int fd)
+int IonAlloc::free_buffer(void* base, unsigned int size, unsigned int offset,
+        int fd)
 {
     Locker::Autolock _l(mLock);
-    ALOGD_IF(DEBUG, "ion: Freeing buffer base:%p size:%d fd:%d",
+    ALOGD_IF(DEBUG, "ion: Freeing buffer base:%p size:%u fd:%d",
           base, size, fd);
     int err = 0;
     err = open_device();
@@ -136,7 +137,8 @@
     return err;
 }
 
-int IonAlloc::map_buffer(void **pBase, size_t size, int offset, int fd)
+int IonAlloc::map_buffer(void **pBase, unsigned int size, unsigned int offset,
+        int fd)
 {
     int err = 0;
     void *base = 0;
@@ -154,15 +156,16 @@
         ALOGE("ion: Failed to map memory in the client: %s",
               strerror(errno));
     } else {
-        ALOGD_IF(DEBUG, "ion: Mapped buffer base:%p size:%d offset:%d fd:%d",
+        ALOGD_IF(DEBUG, "ion: Mapped buffer base:%p size:%u offset:%u fd:%d",
               base, size, offset, fd);
     }
     return err;
 }
 
-int IonAlloc::unmap_buffer(void *base, size_t size, int offset)
+int IonAlloc::unmap_buffer(void *base, unsigned int size,
+        unsigned int /*offset*/)
 {
-    ALOGD_IF(DEBUG, "ion: Unmapping buffer  base:%p size:%d", base, size);
+    ALOGD_IF(DEBUG, "ion: Unmapping buffer  base:%p size:%u", base, size);
     int err = 0;
     if(munmap(base, size)) {
         err = -errno;
@@ -172,12 +175,12 @@
     return err;
 
 }
-int IonAlloc::clean_buffer(void *base, size_t size, int offset, int fd, int op)
+int IonAlloc::clean_buffer(void *base, unsigned int size, unsigned int offset,
+        int fd, int op)
 {
     struct ion_flush_data flush_data;
     struct ion_fd_data fd_data;
     struct ion_handle_data handle_data;
-    ion_user_handle_t handle;
     int err = 0;
 
     err = open_device();
@@ -195,6 +198,7 @@
     handle_data.handle = fd_data.handle;
     flush_data.handle  = fd_data.handle;
     flush_data.vaddr   = base;
+    // offset and length are unsigned int
     flush_data.offset  = offset;
     flush_data.length  = size;
 
diff --git a/msm8226/libgralloc/ionalloc.h b/msm8226/libgralloc/ionalloc.h
index 174f44b..635bda5 100644
--- a/msm8226/libgralloc/ionalloc.h
+++ b/msm8226/libgralloc/ionalloc.h
@@ -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
@@ -41,17 +41,17 @@
     public:
     virtual int alloc_buffer(alloc_data& data);
 
-    virtual int free_buffer(void *base, size_t size,
-                            int offset, int fd);
+    virtual int free_buffer(void *base, unsigned int size,
+                            unsigned int offset, int fd);
 
-    virtual int map_buffer(void **pBase, size_t size,
-                           int offset, int fd);
+    virtual int map_buffer(void **pBase, unsigned int size,
+                           unsigned int offset, int fd);
 
-    virtual int unmap_buffer(void *base, size_t size,
-                             int offset);
+    virtual int unmap_buffer(void *base, unsigned int size,
+                             unsigned int offset);
 
-    virtual int clean_buffer(void*base, size_t size,
-                             int offset, int fd, int op);
+    virtual int clean_buffer(void*base, unsigned int size,
+                             unsigned int offset, int fd, int op);
 
     IonAlloc() { mIonFd = FD_INIT; }
 
diff --git a/msm8226/libgralloc/mapper.cpp b/msm8226/libgralloc/mapper.cpp
index 59e7d60..0ee69c8 100644
--- a/msm8226/libgralloc/mapper.cpp
+++ b/msm8226/libgralloc/mapper.cpp
@@ -53,14 +53,16 @@
 }
 
 static int gralloc_map(gralloc_module_t const* module,
-                       buffer_handle_t handle,
-                       void** vaddr)
+                       buffer_handle_t handle)
 {
+    if(!module)
+        return -EINVAL;
+
     private_handle_t* hnd = (private_handle_t*)handle;
     void *mappedAddress;
     if (!(hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER) &&
         !(hnd->flags & private_handle_t::PRIV_FLAGS_SECURE_BUFFER)) {
-        size_t size = hnd->size;
+        unsigned int size = hnd->size;
         IMemAlloc* memalloc = getAllocator(hnd->flags) ;
         int err = memalloc->map_buffer(&mappedAddress, size,
                                        hnd->offset, hnd->fd);
@@ -71,9 +73,7 @@
             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);
+        hnd->base = uint64_t(mappedAddress) + hnd->offset;
         mappedAddress = MAP_FAILED;
         size = ROUND_UP_PAGESIZE(sizeof(MetaData_t));
         err = memalloc->map_buffer(&mappedAddress, size,
@@ -84,20 +84,22 @@
             hnd->base_metadata = 0;
             return -errno;
         }
-        hnd->base_metadata = intptr_t(mappedAddress) + hnd->offset_metadata;
+        hnd->base_metadata = uint64_t(mappedAddress) + hnd->offset_metadata;
     }
-    *vaddr = (void*)hnd->base;
     return 0;
 }
 
 static int gralloc_unmap(gralloc_module_t const* module,
                          buffer_handle_t handle)
 {
+    if(!module)
+        return -EINVAL;
+
     private_handle_t* hnd = (private_handle_t*)handle;
     if (!(hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER)) {
         int err = -EINVAL;
         void* base = (void*)hnd->base;
-        size_t size = hnd->size;
+        unsigned int size = hnd->size;
         IMemAlloc* memalloc = getAllocator(hnd->flags) ;
         if(memalloc != NULL) {
             err = memalloc->unmap_buffer(base, size, hnd->offset);
@@ -128,7 +130,7 @@
 int gralloc_register_buffer(gralloc_module_t const* module,
                             buffer_handle_t handle)
 {
-    if (private_handle_t::validate(handle) < 0)
+    if (!module || private_handle_t::validate(handle) < 0)
         return -EINVAL;
 
     // In this implementation, we don't need to do anything here
@@ -143,8 +145,7 @@
     private_handle_t* hnd = (private_handle_t*)handle;
     hnd->base = 0;
     hnd->base_metadata = 0;
-    void *vaddr;
-    int err = gralloc_map(module, handle, &vaddr);
+    int err = gralloc_map(module, handle);
     if (err) {
         ALOGE("%s: gralloc_map failed", __FUNCTION__);
         return err;
@@ -156,7 +157,7 @@
 int gralloc_unregister_buffer(gralloc_module_t const* module,
                               buffer_handle_t handle)
 {
-    if (private_handle_t::validate(handle) < 0)
+    if (!module || private_handle_t::validate(handle) < 0)
         return -EINVAL;
 
     /*
@@ -178,6 +179,9 @@
 int terminateBuffer(gralloc_module_t const* module,
                     private_handle_t* hnd)
 {
+    if(!module)
+        return -EINVAL;
+
     /*
      * If the buffer has been mapped during a lock operation, it's time
      * to un-map it. It's an error to be here with a locked buffer.
@@ -200,12 +204,10 @@
     return 0;
 }
 
-int gralloc_lock(gralloc_module_t const* module,
-                 buffer_handle_t handle, int usage,
-                 int l, int t, int w, int h,
-                 void** vaddr)
+static int gralloc_map_and_invalidate (gralloc_module_t const* module,
+                                       buffer_handle_t handle, int usage)
 {
-    if (private_handle_t::validate(handle) < 0)
+    if (!module || private_handle_t::validate(handle) < 0)
         return -EINVAL;
 
     int err = 0;
@@ -215,10 +217,9 @@
             // we need to map for real
             pthread_mutex_t* const lock = &sMapLock;
             pthread_mutex_lock(lock);
-            err = gralloc_map(module, handle, vaddr);
+            err = gralloc_map(module, handle);
             pthread_mutex_unlock(lock);
         }
-        *vaddr = (void*)hnd->base;
         if (hnd->flags & private_handle_t::PRIV_FLAGS_USES_ION) {
             //Invalidate if reading in software. No need to do this for the
             //metadata buffer as it is only read/written in software.
@@ -237,11 +238,36 @@
     return err;
 }
 
+int gralloc_lock(gralloc_module_t const* module,
+                 buffer_handle_t handle, int usage,
+                 int /*l*/, int /*t*/, int /*w*/, int /*h*/,
+                 void** vaddr)
+{
+    private_handle_t* hnd = (private_handle_t*)handle;
+    int err = gralloc_map_and_invalidate(module, handle, usage);
+    if(!err)
+        *vaddr = (void*)hnd->base;
+    return err;
+}
+
+int gralloc_lock_ycbcr(gralloc_module_t const* module,
+                 buffer_handle_t handle, int usage,
+                 int /*l*/, int /*t*/, int /*w*/, int /*h*/,
+                 struct android_ycbcr *ycbcr)
+{
+    private_handle_t* hnd = (private_handle_t*)handle;
+    int err = gralloc_map_and_invalidate(module, handle, usage);
+    if(!err)
+        err = getYUVPlaneInfo(hnd, ycbcr);
+    return err;
+}
+
 int gralloc_unlock(gralloc_module_t const* module,
                    buffer_handle_t handle)
 {
-    if (private_handle_t::validate(handle) < 0)
+    if (!module || private_handle_t::validate(handle) < 0)
         return -EINVAL;
+
     int err = 0;
     private_handle_t* hnd = (private_handle_t*)handle;
 
@@ -273,28 +299,30 @@
 {
     int res = -EINVAL;
     va_list args;
+    if(!module)
+        return res;
+
     va_start(args, operation);
     switch (operation) {
         case GRALLOC_MODULE_PERFORM_CREATE_HANDLE_FROM_BUFFER:
             {
                 int fd = va_arg(args, int);
-                size_t size = va_arg(args, size_t);
-                size_t offset = va_arg(args, size_t);
+                unsigned int size = va_arg(args, unsigned int);
+                unsigned int offset = va_arg(args, unsigned int);
                 void* base = va_arg(args, void*);
                 int width = va_arg(args, int);
                 int height = va_arg(args, int);
                 int format = va_arg(args, int);
 
                 native_handle_t** handle = va_arg(args, native_handle_t**);
-                int memoryFlags = va_arg(args, int);
                 private_handle_t* hnd = (private_handle_t*)native_handle_create(
-                    private_handle_t::sNumFds, private_handle_t::sNumInts);
+                    private_handle_t::sNumFds, private_handle_t::sNumInts());
                 hnd->magic = private_handle_t::sMagic;
                 hnd->fd = fd;
                 hnd->flags =  private_handle_t::PRIV_FLAGS_USES_ION;
                 hnd->size = size;
                 hnd->offset = offset;
-                hnd->base = intptr_t(base) + offset;
+                hnd->base = uint64_t(base) + offset;
                 hnd->gpuaddr = 0;
                 hnd->width = width;
                 hnd->height = height;
@@ -349,6 +377,25 @@
                 res = 0;
             } break;
 
+        case GRALLOC_MODULE_PERFORM_GET_CUSTOM_STRIDE_AND_HEIGHT_FROM_HANDLE:
+            {
+                private_handle_t* hnd =  va_arg(args, private_handle_t*);
+                int *stride = va_arg(args, int *);
+                int *height = va_arg(args, int *);
+                if (private_handle_t::validate(hnd)) {
+                    return res;
+                }
+                MetaData_t *metadata = (MetaData_t *)hnd->base_metadata;
+                if(metadata && metadata->operation & UPDATE_BUFFER_GEOMETRY) {
+                    *stride = metadata->bufferDim.sliceWidth;
+                    *height = metadata->bufferDim.sliceHeight;
+                } else {
+                    *stride = hnd->width;
+                    *height = hnd->height;
+                }
+                res = 0;
+            } break;
+
         case GRALLOC_MODULE_PERFORM_GET_ATTRIBUTES:
             {
                 int width   = va_arg(args, int);
@@ -378,6 +425,15 @@
                     res = 0;
                 }
             } break;
+        case GRALLOC_MODULE_PERFORM_GET_YUV_PLANE_INFO:
+            {
+                private_handle_t* hnd =  va_arg(args, private_handle_t*);
+                android_ycbcr* ycbcr = va_arg(args, struct android_ycbcr *);
+                if (!private_handle_t::validate(hnd)) {
+                    res = getYUVPlaneInfo(hnd, ycbcr);
+                }
+            } break;
+
         default:
             break;
     }
diff --git a/msm8226/libgralloc/memalloc.h b/msm8226/libgralloc/memalloc.h
index 664bfa2..2bc1ddf 100644
--- a/msm8226/libgralloc/memalloc.h
+++ b/msm8226/libgralloc/memalloc.h
@@ -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
@@ -43,10 +43,10 @@
 struct alloc_data {
     void           *base;
     int            fd;
-    int            offset;
-    size_t         size;
-    size_t         align;
-    unsigned int   pHandle;
+    unsigned int   offset;
+    unsigned int   size;
+    unsigned int   align;
+    uintptr_t      pHandle;
     bool           uncached;
     unsigned int   flags;
     int            allocType;
@@ -61,20 +61,20 @@
     virtual int alloc_buffer(alloc_data& data) = 0;
 
     // Free buffer
-    virtual int free_buffer(void *base, size_t size,
-                            int offset, int fd) = 0;
+    virtual int free_buffer(void *base, unsigned int size,
+                            unsigned int offset, int fd) = 0;
 
     // Map buffer
-    virtual int map_buffer(void **pBase, size_t size,
-                           int offset, int fd) = 0;
+    virtual int map_buffer(void **pBase, unsigned int size,
+                           unsigned int offset, int fd) = 0;
 
     // Unmap buffer
-    virtual int unmap_buffer(void *base, size_t size,
-                             int offset) = 0;
+    virtual int unmap_buffer(void *base, unsigned int size,
+                             unsigned int offset) = 0;
 
     // Clean and invalidate
-    virtual int clean_buffer(void *base, size_t size,
-                             int offset, int fd, int op) = 0;
+    virtual int clean_buffer(void *base, unsigned int size,
+                             unsigned int offset, int fd, int op) = 0;
 
     // Destructor
     virtual ~IMemAlloc() {};
diff --git a/msm8226/libhwcomposer/Android.mk b/msm8226/libhwcomposer/Android.mk
index 561ba2c..ef7778b 100644
--- a/msm8226/libhwcomposer/Android.mk
+++ b/msm8226/libhwcomposer/Android.mk
@@ -3,7 +3,7 @@
 include $(CLEAR_VARS)
 
 LOCAL_MODULE                  := hwcomposer.$(TARGET_BOARD_PLATFORM)
-LOCAL_MODULE_PATH             := $(TARGET_OUT_SHARED_LIBRARIES)/hw
+LOCAL_MODULE_RELATIVE_PATH    := hw
 LOCAL_MODULE_TAGS             := optional
 LOCAL_C_INCLUDES              := $(common_includes) $(kernel_includes) \
                                  $(TOP)/external/skia/include/core \
@@ -12,6 +12,11 @@
                                  libexternal libqdutils libhardware_legacy \
                                  libdl libmemalloc libqservice libsync \
                                  libbinder libmedia libvirtual
+
+ifeq ($(TARGET_USES_QCOM_BSP),true)
+LOCAL_SHARED_LIBRARIES += libskia
+endif #TARGET_USES_QCOM_BSP
+
 LOCAL_CFLAGS                  := $(common_flags) -DLOG_TAG=\"qdhwcomposer\"
 LOCAL_ADDITIONAL_DEPENDENCIES := $(common_deps)
 LOCAL_SRC_FILES               := hwc.cpp          \
diff --git a/msm8226/libhwcomposer/hwc.cpp b/msm8226/libhwcomposer/hwc.cpp
index fe418ad..8a64d67 100644
--- a/msm8226/libhwcomposer/hwc.cpp
+++ b/msm8226/libhwcomposer/hwc.cpp
@@ -44,7 +44,7 @@
 using namespace overlay;
 
 #define VSYNC_DEBUG 0
-#define BLANK_DEBUG 1
+#define POWER_MODE_DEBUG 1
 
 static int hwc_device_open(const struct hw_module_t* module,
                            const char* name,
@@ -101,12 +101,104 @@
     init_vsync_thread(ctx);
 }
 
-//Helper
+static void setPaddingRound(hwc_context_t *ctx, int numDisplays,
+                            hwc_display_contents_1_t** displays) {
+    ctx->isPaddingRound = false;
+    for(int i = 0; i < numDisplays; i++) {
+        hwc_display_contents_1_t *list = displays[i];
+        if (LIKELY(list && list->numHwLayers > 0)) {
+            if((ctx->mPrevHwLayerCount[i] == 1 or
+                ctx->mPrevHwLayerCount[i] == 0) and
+               (list->numHwLayers > 1)) {
+                /* If the previous cycle for dpy 'i' has 0 AppLayers and the
+                 * current cycle has atleast 1 AppLayer, padding round needs
+                 * to be invoked in current cycle on all the active displays
+                 * to free up the resources.
+                 */
+                ctx->isPaddingRound = true;
+            }
+            ctx->mPrevHwLayerCount[i] = (int)list->numHwLayers;
+        } else {
+            ctx->mPrevHwLayerCount[i] = 0;
+        }
+    }
+}
+
+/* Based on certain conditions, isPaddingRound will be set
+ * to make this function self-contained */
+static void setDMAState(hwc_context_t *ctx, int numDisplays,
+                        hwc_display_contents_1_t** displays) {
+
+    if(ctx->mRotMgr->getNumActiveSessions() == 0)
+        Overlay::setDMAMode(Overlay::DMA_LINE_MODE);
+
+    for(int dpy = 0; dpy < numDisplays; dpy++) {
+        hwc_display_contents_1_t *list = displays[dpy];
+        if (LIKELY(list && list->numHwLayers > 0)) {
+            for(size_t layerIndex = 0; layerIndex < list->numHwLayers;
+                                                  layerIndex++) {
+                if(list->hwLayers[layerIndex].compositionType !=
+                                            HWC_FRAMEBUFFER_TARGET)
+                {
+                    hwc_layer_1_t const* layer = &list->hwLayers[layerIndex];
+                    private_handle_t *hnd = (private_handle_t *)layer->handle;
+
+                    /* If a layer requires rotation, set the DMA state
+                     * to BLOCK_MODE */
+
+                    if (canUseRotator(ctx, dpy) &&
+                        has90Transform(layer) && isRotationDoable(ctx, hnd)) {
+                        if(not ctx->mOverlay->isDMAMultiplexingSupported()) {
+                            if(ctx->mOverlay->isPipeTypeAttached(
+                                             overlay::utils::OV_MDP_PIPE_DMA))
+                                ctx->isPaddingRound = true;
+                        }
+                        Overlay::setDMAMode(Overlay::DMA_BLOCK_MODE);
+                    }
+                }
+            }
+            if(dpy) {
+                /* Uncomment the below code for testing purpose.
+                   Assuming the orientation value is in terms of HAL_TRANSFORM,
+                   this needs mapping to HAL, if its in different convention */
+
+                /* char value[PROPERTY_VALUE_MAX];
+                   property_get("sys.ext_orientation", value, "0");
+                   ctx->mExtOrientation = atoi(value);*/
+
+                if(ctx->mExtOrientation || ctx->mBufferMirrorMode) {
+                    if(ctx->mOverlay->isPipeTypeAttached(
+                                         overlay::utils::OV_MDP_PIPE_DMA)) {
+                        ctx->isPaddingRound = true;
+                    }
+                    Overlay::setDMAMode(Overlay::DMA_BLOCK_MODE);
+                }
+            }
+        }
+    }
+}
+
+static void setNumActiveDisplays(hwc_context_t *ctx, int numDisplays,
+                            hwc_display_contents_1_t** displays) {
+
+    ctx->numActiveDisplays = 0;
+    for(int i = 0; i < numDisplays; i++) {
+        hwc_display_contents_1_t *list = displays[i];
+        if (LIKELY(list && list->numHwLayers > 0)) {
+            /* For display devices like SSD and screenrecord, we cannot
+             * rely on isActive and connected attributes of dpyAttr to
+             * determine if the displaydevice is active. Hence in case if
+             * the layer-list is non-null and numHwLayers > 0, we assume
+             * the display device to be active.
+             */
+            ctx->numActiveDisplays += 1;
+        }
+    }
+}
+
 static void reset(hwc_context_t *ctx, int numDisplays,
                   hwc_display_contents_1_t** displays) {
 
-    ctx->numActiveDisplays = 0;
-    ctx->isPaddingRound = false;
 
     for(int i = 0; i < numDisplays; i++) {
         hwc_display_contents_1_t *list = displays[i];
@@ -115,31 +207,15 @@
         // cache we need to reset it.
         // We can probably rethink that later on
         if (LIKELY(list && list->numHwLayers > 0)) {
-            for(uint32_t j = 0; j < list->numHwLayers; j++) {
+            for(size_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->mPrevHwLayerCount[i] == 1) and (list->numHwLayers > 1)) {
-                /* If the previous cycle for dpy 'i' has 0 AppLayers and the
-                 * current cycle has atleast 1 AppLayer, padding round needs
-                 * to be invoked on current cycle to free up the resources.
-                 */
-                ctx->isPaddingRound = true;
-            }
-            ctx->mPrevHwLayerCount[i] = list->numHwLayers;
-        } else {
-            ctx->mPrevHwLayerCount[i] = 0;
         }
 
+        if(ctx->mMDPComp[i])
+            ctx->mMDPComp[i]->reset();
         if(ctx->mFBUpdate[i])
             ctx->mFBUpdate[i]->reset();
         if(ctx->mCopyBit[i])
@@ -149,40 +225,30 @@
     }
 
     ctx->mAD->reset();
-    MDPComp::reset();
     if(ctx->mHWCVirtual)
         ctx->mHWCVirtual->destroy(ctx, numDisplays, displays);
 }
 
-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;
+    uint32_t origXres = ctx->dpyAttr[dpy].xres;
+    uint32_t origYres = ctx->dpyAttr[dpy].yres;
+    uint32_t newXres = ctx->dpyAttr[dpy].xres_new;
+    uint32_t newYres = ctx->dpyAttr[dpy].yres_new;
+    float xresRatio = (float)origXres / (float)newXres;
+    float yresRatio = (float)origYres / (float)newYres;
     for (size_t i = 0; i < list->numHwLayers; i++) {
         hwc_layer_1_t *layer = &list->hwLayers[i];
         hwc_rect_t& displayFrame = layer->displayFrame;
         hwc_rect_t sourceCrop = integerizeSourceCrop(layer->sourceCropf);
-        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;
+        uint32_t layerWidth = displayFrame.right - displayFrame.left;
+        uint32_t layerHeight = displayFrame.bottom - displayFrame.top;
+        displayFrame.left = (int)(xresRatio * (float)displayFrame.left);
+        displayFrame.top = (int)(yresRatio * (float)displayFrame.top);
+        displayFrame.right = (int)((float)displayFrame.left +
+                                   (float)layerWidth * xresRatio);
+        displayFrame.bottom = (int)((float)displayFrame.top +
+                                    (float)layerHeight * yresRatio);
     }
 }
 
@@ -195,17 +261,21 @@
     if (LIKELY(list && list->numHwLayers > 1) &&
             ctx->dpyAttr[dpy].isActive) {
 
-        if (ctx->dpyAttr[dpy].customFBSize)
+        if (ctx->dpyAttr[dpy].customFBSize &&
+                list->flags & HWC_GEOMETRY_CHANGED)
             scaleDisplayFrame(ctx, dpy, list);
 
-        reset_layer_prop(ctx, dpy, list->numHwLayers - 1);
+        reset_layer_prop(ctx, dpy, (int)list->numHwLayers - 1);
         setListStats(ctx, list, dpy);
 
         fbComp = (ctx->mMDPComp[dpy]->prepare(ctx, list) < 0);
 
         if (fbComp) {
             const int fbZ = 0;
-            ctx->mFBUpdate[dpy]->prepareAndValidate(ctx, list, fbZ);
+            if(not ctx->mFBUpdate[dpy]->prepareAndValidate(ctx, list, fbZ)) {
+                ctx->mOverlay->clear(dpy);
+                ctx->mLayerRotMap[dpy]->clear();
+            }
         }
 
         if (ctx->mMDP.version < qdutils::MDP_V4_0) {
@@ -226,13 +296,17 @@
     if (LIKELY(list && list->numHwLayers > 1) &&
             ctx->dpyAttr[dpy].isActive &&
             ctx->dpyAttr[dpy].connected) {
-        reset_layer_prop(ctx, dpy, list->numHwLayers - 1);
+        reset_layer_prop(ctx, dpy, (int)list->numHwLayers - 1);
         if(!ctx->dpyAttr[dpy].isPause) {
             ctx->dpyAttr[dpy].isConfiguring = false;
             setListStats(ctx, list, dpy);
             if(ctx->mMDPComp[dpy]->prepare(ctx, list) < 0) {
                 const int fbZ = 0;
-                ctx->mFBUpdate[dpy]->prepareAndValidate(ctx, list, fbZ);
+                if(not ctx->mFBUpdate[dpy]->prepareAndValidate(ctx, list, fbZ))
+                {
+                    ctx->mOverlay->clear(dpy);
+                    ctx->mLayerRotMap[dpy]->clear();
+                }
             }
         } else {
             /* External Display is in Pause state.
@@ -261,13 +335,16 @@
 
     //Will be unlocked at the end of set
     ctx->mDrawLock.lock();
-    reset(ctx, numDisplays, displays);
+    setPaddingRound(ctx, (int)numDisplays, displays);
+    setDMAState(ctx, (int)numDisplays, displays);
+    setNumActiveDisplays(ctx, (int)numDisplays, displays);
+    reset(ctx, (int)numDisplays, displays);
 
     ctx->mOverlay->configBegin();
     ctx->mRotMgr->configBegin();
     overlay::Writeback::configBegin();
 
-    for (int32_t i = (numDisplays-1); i >= 0; i--) {
+    for (int32_t i = ((int32_t)numDisplays-1); i >=0 ; i--) {
         hwc_display_contents_1_t *list = displays[i];
         int dpy = getDpyforExternalDisplay(ctx, i);
         switch(dpy) {
@@ -324,106 +401,86 @@
     return ret;
 }
 
-static int hwc_blank(struct hwc_composer_device_1* dev, int dpy, int blank)
+static int hwc_setPowerMode(struct hwc_composer_device_1* dev, int dpy,
+        int mode)
 {
     ATRACE_CALL();
     hwc_context_t* ctx = (hwc_context_t*)(dev);
-
-    Locker::Autolock _l(ctx->mDrawLock);
     int ret = 0, value = 0;
 
-    /* In case of non-hybrid WFD session, we are fooling SF by
-     * piggybacking on HDMI display ID for virtual.
-     * TODO: Not needed once we have WFD client working on top
-     * of Google API's.
-     */
-    dpy = getDpyforExternalDisplay(ctx,dpy);
+    Locker::Autolock _l(ctx->mDrawLock);
+    ALOGD_IF(POWER_MODE_DEBUG, "%s: Setting mode %d on display: %d",
+            __FUNCTION__, mode, dpy);
 
-    ALOGD_IF(BLANK_DEBUG, "%s: %s display: %d", __FUNCTION__,
-          blank==1 ? "Blanking":"Unblanking", dpy);
-    if(blank) {
-        // free up all the overlay pipes in use
-        // when we get a blank for either display
-        // makes sure that all pipes are freed
-        ctx->mOverlay->configBegin();
-        ctx->mOverlay->configDone();
-        ctx->mRotMgr->clear();
-        // If VDS is connected, do not clear WB object as it
-        // will end up detaching IOMMU. This is required
-        // to send black frame to WFD sink on power suspend.
-        // Note: With this change, we keep the WriteBack object
-        // alive on power suspend for AD use case.
+    switch(mode) {
+        case HWC_POWER_MODE_OFF:
+            // free up all the overlay pipes in use
+            // when we get a blank for either display
+            // makes sure that all pipes are freed
+            ctx->mOverlay->configBegin();
+            ctx->mOverlay->configDone();
+            ctx->mRotMgr->clear();
+            // If VDS is connected, do not clear WB object as it
+            // will end up detaching IOMMU. This is required
+            // to send black frame to WFD sink on power suspend.
+            // Note: With this change, we keep the WriteBack object
+            // alive on power suspend for AD use case.
+            value = FB_BLANK_POWERDOWN;
+            break;
+        case HWC_POWER_MODE_DOZE:
+        case HWC_POWER_MODE_DOZE_SUSPEND:
+            value = FB_BLANK_VSYNC_SUSPEND;
+            break;
+        case HWC_POWER_MODE_NORMAL:
+            value = FB_BLANK_UNBLANK;
+            break;
     }
+
     switch(dpy) {
     case HWC_DISPLAY_PRIMARY:
-        value = blank ? FB_BLANK_POWERDOWN : FB_BLANK_UNBLANK;
         if(ioctl(ctx->dpyAttr[dpy].fd, FBIOBLANK, value) < 0 ) {
-            ALOGE("%s: Failed to handle blank event(%d) for Primary!!",
-                  __FUNCTION__, blank );
-            return -1;
+            ALOGE("%s: ioctl FBIOBLANK failed for Primary with error %s"
+                    " value %d", __FUNCTION__, strerror(errno), value);
+            return -errno;
         }
 
-        if(!blank) {
-            // Enable HPD here, as during bootup unblank is called
+        if(mode == HWC_POWER_MODE_NORMAL) {
+            // Enable HPD here, as during bootup POWER_MODE_NORMAL is set
             // when SF is completely initialized
             ctx->mExtDisplay->setHPD(1);
         }
 
-        ctx->dpyAttr[dpy].isActive = !blank;
-
-        if(ctx->mVirtualonExtActive) {
-            /* if mVirtualonExtActive is true, display hal will
-             * receive unblank calls for non-hybrid WFD solution
-             * since we piggyback on HDMI.
-             * TODO: Not needed once we have WFD client working on top
-             of Google API's */
-            break;
-        }
+        ctx->dpyAttr[dpy].isActive = not(mode == HWC_POWER_MODE_OFF);
+        //Deliberate fall through since there is no explicit power mode for
+        //virtual displays.
     case HWC_DISPLAY_VIRTUAL:
-        /* There are two ways to reach this block of code.
-
-         * Display hal has received unblank call on HWC_DISPLAY_EXTERNAL
-         and ctx->mVirtualonExtActive is true. In this case, non-hybrid
-         WFD is active. If so, getDpyforExternalDisplay will return dpy
-         as HWC_DISPLAY_VIRTUAL.
-
-         * Display hal has received unblank call on HWC_DISPLAY_PRIMARY
-         and since SF is not aware of VIRTUAL DISPLAY being handle by HWC,
-         it wont send blank / unblank events for it. We piggyback on
-         PRIMARY DISPLAY events to release mdp pipes and
-         activate/deactivate VIRTUAL DISPLAY.
-
-         * TODO: This separate case statement is not needed once we have
-         WFD client working on top of Google API's.
-
-         */
-
         if(ctx->dpyAttr[HWC_DISPLAY_VIRTUAL].connected) {
-            if(blank and (!ctx->dpyAttr[HWC_DISPLAY_VIRTUAL].isPause)) {
-                int dpy = HWC_DISPLAY_VIRTUAL;
+            const int dpy = HWC_DISPLAY_VIRTUAL;
+            if(mode == HWC_POWER_MODE_OFF and
+                    (not ctx->dpyAttr[dpy].isPause)) {
                 if(!Overlay::displayCommit(ctx->dpyAttr[dpy].fd)) {
-                    ALOGE("%s: display commit fail for virtual!", __FUNCTION__);
+                    ALOGE("%s: displayCommit failed for virtual", __FUNCTION__);
                     ret = -1;
                 }
             }
-            ctx->dpyAttr[HWC_DISPLAY_VIRTUAL].isActive = !blank;
+            ctx->dpyAttr[dpy].isActive = not(mode == HWC_POWER_MODE_OFF);
         }
         break;
     case HWC_DISPLAY_EXTERNAL:
-        if(blank) {
+        if(mode == HWC_POWER_MODE_OFF) {
             if(!Overlay::displayCommit(ctx->dpyAttr[dpy].fd)) {
-                ALOGE("%s: display commit fail for external!", __FUNCTION__);
+                ALOGE("%s: displayCommit failed for external", __FUNCTION__);
                 ret = -1;
             }
         }
-        ctx->dpyAttr[dpy].isActive = !blank;
+        ctx->dpyAttr[dpy].isActive = not(mode == HWC_POWER_MODE_OFF);
         break;
     default:
         return -EINVAL;
     }
 
-    ALOGD_IF(BLANK_DEBUG, "%s: Done %s display: %d", __FUNCTION__,
-          blank ? "blanking":"unblanking", dpy);
+    ALOGD_IF(POWER_MODE_DEBUG, "%s: Done setting mode %d on display %d",
+            __FUNCTION__, mode, dpy);
     return ret;
 }
 
@@ -438,18 +495,18 @@
         return;
     }
 
-    ALOGD("%s: calling BLANK DISPLAY", __FUNCTION__);
-    ret = hwc_blank(dev, HWC_DISPLAY_PRIMARY, 1);
+    ALOGD("%s: setting power mode off", __FUNCTION__);
+    ret = hwc_setPowerMode(dev, HWC_DISPLAY_PRIMARY, HWC_POWER_MODE_OFF);
     if (ret < 0) {
         ALOGE("%s: FBIOBLANK failed to BLANK:  %s", __FUNCTION__,
-                                                            strerror(errno));
+                strerror(errno));
     }
 
-    ALOGD("%s: calling UNBLANK DISPLAY and enabling vsync", __FUNCTION__);
-    ret = hwc_blank(dev, HWC_DISPLAY_PRIMARY, 0);
+    ALOGD("%s: setting power mode normal and enabling vsync", __FUNCTION__);
+    ret = hwc_setPowerMode(dev, HWC_DISPLAY_PRIMARY, HWC_POWER_MODE_NORMAL);
     if (ret < 0) {
         ALOGE("%s: FBIOBLANK failed to UNBLANK : %s", __FUNCTION__,
-                                                            strerror(errno));
+                strerror(errno));
     }
     hwc_vsync_control(ctx, HWC_DISPLAY_PRIMARY, 1);
 
@@ -472,7 +529,8 @@
         if(ctx->mMDP.hasOverlay) {
             supported |= HWC_DISPLAY_VIRTUAL_BIT;
             if(!(qdutils::MDPVersion::getInstance().is8x26() ||
-                        qdutils::MDPVersion::getInstance().is8x16()))
+                        qdutils::MDPVersion::getInstance().is8x16() ||
+                        qdutils::MDPVersion::getInstance().is8x39()))
                 supported |= HWC_DISPLAY_EXTERNAL_BIT;
         }
         value[0] = supported;
@@ -496,12 +554,18 @@
     int ret = 0;
     const int dpy = HWC_DISPLAY_PRIMARY;
     if (LIKELY(list) && ctx->dpyAttr[dpy].isActive) {
-        uint32_t last = list->numHwLayers - 1;
+        size_t last = list->numHwLayers - 1;
         hwc_layer_1_t *fbLayer = &list->hwLayers[last];
         int fd = -1; //FenceFD from the Copybit(valid in async mode)
         bool copybitDone = false;
-        if(ctx->mCopyBit[dpy])
-            copybitDone = ctx->mCopyBit[dpy]->draw(ctx, list, dpy, &fd);
+
+        if (ctx->mCopyBit[dpy]) {
+            if (ctx->mMDP.version < qdutils::MDP_V4_0)
+                copybitDone = ctx->mCopyBit[dpy]->draw(ctx, list, dpy, &fd);
+            else
+                fd = ctx->mMDPComp[dpy]->drawOverlap(ctx, list);
+        }
+
         if(list->numHwLayers > 1)
             hwc_sync(ctx, list, dpy, fd);
 
@@ -521,6 +585,12 @@
             hnd = ctx->mCopyBit[dpy]->getCurrentRenderBuffer();
         }
 
+        if(isAbcInUse(ctx) == true) {
+            int index = ctx->listStats[dpy].renderBufIndexforABC;
+            hwc_layer_1_t *tempLayer = &list->hwLayers[index];
+            hnd = (private_handle_t *)tempLayer->handle;
+        }
+
         if(hnd) {
             if (!ctx->mFBUpdate[dpy]->draw(ctx, hnd)) {
                 ALOGE("%s: FBUpdate draw failed", __FUNCTION__);
@@ -528,8 +598,20 @@
             }
         }
 
-        if(!Overlay::displayCommit(ctx->dpyAttr[dpy].fd,
-                                            ctx->listStats[dpy].roi)) {
+        int lSplit = getLeftSplit(ctx, dpy);
+        qhwc::ovutils::Dim lRoi = qhwc::ovutils::Dim(
+            ctx->listStats[dpy].lRoi.left,
+            ctx->listStats[dpy].lRoi.top,
+            ctx->listStats[dpy].lRoi.right - ctx->listStats[dpy].lRoi.left,
+            ctx->listStats[dpy].lRoi.bottom - ctx->listStats[dpy].lRoi.top);
+
+        qhwc::ovutils::Dim rRoi = qhwc::ovutils::Dim(
+            ctx->listStats[dpy].rRoi.left - lSplit,
+            ctx->listStats[dpy].rRoi.top,
+            ctx->listStats[dpy].rRoi.right - ctx->listStats[dpy].rRoi.left,
+            ctx->listStats[dpy].rRoi.bottom - ctx->listStats[dpy].rRoi.top);
+
+        if(!Overlay::displayCommit(ctx->dpyAttr[dpy].fd, lRoi, rRoi)) {
             ALOGE("%s: display commit fail for %d dpy!", __FUNCTION__, dpy);
             ret = -1;
         }
@@ -552,7 +634,7 @@
     if (LIKELY(list) && ctx->dpyAttr[dpy].isActive &&
         ctx->dpyAttr[dpy].connected &&
         !ctx->dpyAttr[dpy].isPause) {
-        uint32_t last = list->numHwLayers - 1;
+        size_t last = list->numHwLayers - 1;
         hwc_layer_1_t *fbLayer = &list->hwLayers[last];
         int fd = -1; //FenceFD from the Copybit(valid in async mode)
         bool copybitDone = false;
@@ -605,7 +687,7 @@
 {
     int ret = 0;
     hwc_context_t* ctx = (hwc_context_t*)(dev);
-    for (uint32_t i = 0; i < numDisplays; i++) {
+    for (int i = 0; i < (int)numDisplays; i++) {
         hwc_display_contents_1_t* list = displays[i];
         int dpy = getDpyforExternalDisplay(ctx, i);
         switch(dpy) {
@@ -628,8 +710,6 @@
     CALC_FPS();
     MDPComp::resetIdleFallBack();
     ctx->mVideoTransFlag = false;
-    if(ctx->mRotMgr->getNumActiveSessions() == 0)
-        Overlay::setDMAMode(Overlay::DMA_LINE_MODE);
     //Was locked at the beginning of prepare
     ctx->mDrawLock.unlock();
     return ret;
@@ -640,8 +720,8 @@
     int ret = 0;
     hwc_context_t* ctx = (hwc_context_t*)(dev);
     disp = getDpyforExternalDisplay(ctx, disp);
-    //in 1.1 there is no way to choose a config, report as config id # 0
-    //This config is passed to getDisplayAttributes. Ignore for now.
+    //Currently we allow only 1 config, reported as config id # 0
+    //This config is passed in to getDisplayAttributes. Ignored for now.
     switch(disp) {
         case HWC_DISPLAY_PRIMARY:
             if(*numConfigs > 0) {
@@ -685,7 +765,7 @@
         HWC_DISPLAY_NO_ATTRIBUTE,
     };
 
-    const int NUM_DISPLAY_ATTRIBUTES = (sizeof(DISPLAY_ATTRIBUTES) /
+    const size_t NUM_DISPLAY_ATTRIBUTES = (sizeof(DISPLAY_ATTRIBUTES) /
             sizeof(DISPLAY_ATTRIBUTES)[0]);
 
     for (size_t i = 0; i < NUM_DISPLAY_ATTRIBUTES - 1; i++) {
@@ -694,14 +774,21 @@
             values[i] = ctx->dpyAttr[disp].vsync_period;
             break;
         case HWC_DISPLAY_WIDTH:
-            values[i] = ctx->dpyAttr[disp].xres;
+            if (ctx->dpyAttr[disp].customFBSize)
+                values[i] = ctx->dpyAttr[disp].xres_new;
+            else
+                values[i] = ctx->dpyAttr[disp].xres;
+
             ALOGD("%s disp = %d, width = %d",__FUNCTION__, disp,
-                    ctx->dpyAttr[disp].xres);
+                    values[i]);
             break;
         case HWC_DISPLAY_HEIGHT:
-            values[i] = ctx->dpyAttr[disp].yres;
+            if (ctx->dpyAttr[disp].customFBSize)
+                values[i] = ctx->dpyAttr[disp].yres_new;
+            else
+                values[i] = ctx->dpyAttr[disp].yres;
             ALOGD("%s disp = %d, height = %d",__FUNCTION__, disp,
-                    ctx->dpyAttr[disp].yres);
+                    values[i]);
             break;
         case HWC_DISPLAY_DPI_X:
             values[i] = (int32_t) (ctx->dpyAttr[disp].xdpi*1000.0);
@@ -730,7 +817,7 @@
         dumpsys_log(aBuf, "  Vsync is being faked!!\n");
     for(int dpy = 0; dpy < HWC_NUM_DISPLAY_TYPES; dpy++) {
         if(ctx->mMDPComp[dpy])
-            ctx->mMDPComp[dpy]->dump(aBuf);
+            ctx->mMDPComp[dpy]->dump(aBuf, ctx);
     }
     char ovDump[2048] = {'\0'};
     ctx->mOverlay->getDump(ovDump, 2048);
@@ -746,6 +833,17 @@
     strlcpy(buff, aBuf.string(), buff_len);
 }
 
+int hwc_getActiveConfig(struct hwc_composer_device_1* /*dev*/, int /*disp*/) {
+    //Supports only the default config (0th index) for now
+    return 0;
+}
+
+int hwc_setActiveConfig(struct hwc_composer_device_1* /*dev*/, int /*disp*/,
+        int index) {
+    //Supports only the default config (0th index) for now
+    return (index == 0) ? index : -EINVAL;
+}
+
 static int hwc_device_close(struct hw_device_t *dev)
 {
     if(!dev) {
@@ -775,18 +873,20 @@
 
         //Setup HWC methods
         dev->device.common.tag          = HARDWARE_DEVICE_TAG;
-        dev->device.common.version      = HWC_DEVICE_API_VERSION_1_3;
+        dev->device.common.version      = HWC_DEVICE_API_VERSION_1_4;
         dev->device.common.module       = const_cast<hw_module_t*>(module);
         dev->device.common.close        = hwc_device_close;
         dev->device.prepare             = hwc_prepare;
         dev->device.set                 = hwc_set;
         dev->device.eventControl        = hwc_eventControl;
-        dev->device.blank               = hwc_blank;
+        dev->device.setPowerMode        = hwc_setPowerMode;
         dev->device.query               = hwc_query;
         dev->device.registerProcs       = hwc_registerProcs;
         dev->device.dump                = hwc_dump;
         dev->device.getDisplayConfigs   = hwc_getDisplayConfigs;
         dev->device.getDisplayAttributes = hwc_getDisplayAttributes;
+        dev->device.getActiveConfig     = hwc_getActiveConfig;
+        dev->device.setActiveConfig     = hwc_setActiveConfig;
         *device = &dev->device.common;
         status = 0;
     }
diff --git a/msm8226/libhwcomposer/hwc_ad.cpp b/msm8226/libhwcomposer/hwc_ad.cpp
index 236093b..49e7e2a 100644
--- a/msm8226/libhwcomposer/hwc_ad.cpp
+++ b/msm8226/libhwcomposer/hwc_ad.cpp
@@ -41,37 +41,6 @@
 using namespace overlay::utils;
 namespace qhwc {
 
-//Opens writeback framebuffer and returns fd.
-static int openWbFb() {
-    int wbFd = -1;
-    //Check opening which FB would connect LM to WB
-    const int wbFbNum = Overlay::getFbForDpy(Overlay::DPY_WRITEBACK);
-    if(wbFbNum >= 0) {
-        char wbFbPath[256];
-        snprintf (wbFbPath, sizeof(wbFbPath),
-                "/sys/class/graphics/fb%d", wbFbNum);
-        //Opening writeback fb first time would create ad node if the device
-        //supports adaptive display
-        wbFd = open(wbFbPath, O_RDONLY);
-        if(wbFd < 0) {
-            ALOGE("%s: Failed to open /sys/class/graphics/fb%d with error %s",
-                    __func__, wbFbNum, strerror(errno));
-        }
-    } else {
-        ALOGD_IF(DEBUG, "%s: No writeback available", __func__);
-    }
-    return wbFd;
-}
-
-static inline void closeWbFb(int& fd) {
-    if(fd >= 0) {
-        close(fd);
-        fd = -1;
-    } else {
-        ALOGE("%s: Invalid fd %d", __func__, fd);
-    }
-}
-
 //Helper to write data to ad node
 static void adWrite(const int& value) {
     const int wbFbNum = Overlay::getFbForDpy(Overlay::DPY_WRITEBACK);
@@ -82,7 +51,7 @@
     if(adFd >= 0) {
         char opStr[4] = "";
         snprintf(opStr, sizeof(opStr), "%d", value);
-        int ret = write(adFd, opStr, strlen(opStr));
+        ssize_t ret = write(adFd, opStr, strlen(opStr));
         if(ret < 0) {
             ALOGE("%s: Failed to write %d with error %s",
                     __func__, value, strerror(errno));
@@ -124,32 +93,31 @@
     return ret;
 }
 
-AssertiveDisplay::AssertiveDisplay(hwc_context_t *ctx) : mWbFd(-1),
-        mDoable(false), mFeatureEnabled(false),
-        mDest(overlay::utils::OV_INVALID) {
-    int fd = openWbFb();
-    if(fd >= 0) {
-        //Values in ad node:
-        //-1 means feature is disabled on device
-        // 0 means feature exists but turned off, will be turned on by hwc
-        // 1 means feature is turned on by hwc
-        // Plus, we do this feature only on split primary displays.
-        // Plus, we do this feature only if ro.qcom.ad=2
+AssertiveDisplay::AssertiveDisplay(hwc_context_t *ctx) :
+     mTurnedOff(true), mFeatureEnabled(false),
+     mDest(overlay::utils::OV_INVALID)
+{
+    //Values in ad node:
+    //-1 means feature is disabled on device
+    // 0 means feature exists but turned off, will be turned on by hwc
+    // 1 means feature is turned on by hwc
+    // Plus, we do this feature only on split primary displays.
+    // Plus, we do this feature only if ro.qcom.ad=2
 
-        char property[PROPERTY_VALUE_MAX];
-        const int ENABLED = 2;
-        int val = 0;
+    char property[PROPERTY_VALUE_MAX];
+    const int ENABLED = 2;
+    int val = 0;
 
-        if(property_get("ro.qcom.ad", property, "0") > 0) {
-            val = atoi(property);
-        }
+    if(property_get("ro.qcom.ad", property, "0") > 0) {
+        val = atoi(property);
+    }
 
-        if(adRead() >= 0 && isDisplaySplit(ctx, HWC_DISPLAY_PRIMARY) &&
-                val == ENABLED) {
-            ALOGD_IF(DEBUG, "Assertive display feature supported");
-            mFeatureEnabled = true;
-        }
-        closeWbFb(fd);
+    if(adRead() >= 0 && isDisplaySplit(ctx, HWC_DISPLAY_PRIMARY) &&
+            val == ENABLED) {
+        ALOGD_IF(DEBUG, "Assertive display feature supported");
+        mFeatureEnabled = true;
+        // If feature exists but is turned off, set mTurnedOff to true
+        mTurnedOff = adRead() > 0 ? false : true;
     }
 }
 
@@ -168,22 +136,33 @@
     }
 }
 
+void AssertiveDisplay::turnOffAD() {
+    if(mFeatureEnabled) {
+        if(!mTurnedOff) {
+            const int off = 0;
+            adWrite(off);
+            mTurnedOff = true;
+        }
+    }
+    mDoable = false;
+}
+
 bool AssertiveDisplay::prepare(hwc_context_t *ctx,
         const hwc_rect_t& crop,
         const Whf& whf,
         const private_handle_t *hnd) {
     if(!isDoable()) {
-        if(isModeOn()) {
-            //Cleanup one time during this switch
-            const int off = 0;
-            adWrite(off);
-            closeWbFb(mWbFd);
-        }
+        //Cleanup one time during this switch
+        turnOffAD();
         return false;
     }
 
-    ovutils::eDest dest = ctx->mOverlay->nextPipe(ovutils::OV_MDP_PIPE_VG,
-            overlay::Overlay::DPY_WRITEBACK, Overlay::MIXER_DEFAULT);
+    Overlay::PipeSpecs pipeSpecs;
+    pipeSpecs.formatClass = Overlay::FORMAT_YUV;
+    pipeSpecs.dpy = overlay::Overlay::DPY_WRITEBACK;
+    pipeSpecs.fb = false;
+
+    ovutils::eDest dest = ctx->mOverlay->getPipe(pipeSpecs);
     if(dest == OV_INVALID) {
         ALOGE("%s failed: No VG pipe available", __func__);
         mDoable = false;
@@ -206,7 +185,8 @@
         return false;
     }
 
-    int tmpW, tmpH, size;
+    int tmpW, tmpH;
+    size_t size;
     int format = ovutils::getHALFormat(wb->getOutputFormat());
     if(format < 0) {
         ALOGE("%s invalid format %d", __func__, format);
@@ -217,7 +197,7 @@
     size = getBufferSizeAndDimensions(hnd->width, hnd->height,
                 format, tmpW, tmpH);
 
-    if(!wb->configureMemory(size)) {
+    if(!wb->configureMemory((uint32_t)size)) {
         ALOGE("%s: config memory failed", __func__);
         mDoable = false;
         return false;
@@ -241,27 +221,30 @@
     }
 
     mDest = dest;
-    if(!isModeOn()) {
-        mWbFd = openWbFb();
-        if(mWbFd >= 0) {
-            //write to sysfs, one time during this switch
-            const int on = 1;
-            adWrite(on);
-        }
-    }
-
-    if(!ctx->mOverlay->validateAndSet(overlay::Overlay::DPY_WRITEBACK,
-            mWbFd)) {
+    int wbFd = wb->getFbFd();
+    if(mFeatureEnabled && wbFd >= 0 &&
+        !ctx->mOverlay->validateAndSet(overlay::Overlay::DPY_WRITEBACK, wbFd))
+    {
         ALOGE("%s: Failed to validate and set overlay for dpy %d"
                 ,__FUNCTION__, overlay::Overlay::DPY_WRITEBACK);
+        turnOffAD();
         return false;
     }
 
+    // Only turn on AD if there are no errors during configuration stage
+    // and if it was previously in OFF state.
+    if(mFeatureEnabled && mTurnedOff) {
+        //write to sysfs, one time during this switch
+        const int on = 1;
+        adWrite(on);
+        mTurnedOff = false;
+    }
+
     return true;
 }
 
 bool AssertiveDisplay::draw(hwc_context_t *ctx, int fd, uint32_t offset) {
-    if(!isDoable() || !isModeOn()) {
+    if(!isDoable()) {
         return false;
     }
 
diff --git a/msm8226/libhwcomposer/hwc_ad.h b/msm8226/libhwcomposer/hwc_ad.h
index 3bfde17..0be5f5d 100644
--- a/msm8226/libhwcomposer/hwc_ad.h
+++ b/msm8226/libhwcomposer/hwc_ad.h
@@ -50,17 +50,16 @@
             mDest = overlay::utils::OV_INVALID;
     }
     bool isDoable() const { return mDoable; }
-    bool isModeOn() const { return (mWbFd >= 0); }
     int getDstFd() const;
     uint32_t getDstOffset() const;
 
 private:
-    //State of feature turned on and off
-    int mWbFd;
     bool mDoable;
+    bool mTurnedOff;
     //State of feature existence on certain devices and configs.
     bool mFeatureEnabled;
     overlay::utils::eDest mDest;
+    void turnOffAD();
 };
 
 }
diff --git a/msm8226/libhwcomposer/hwc_copybit.cpp b/msm8226/libhwcomposer/hwc_copybit.cpp
index 38b0ff6..4652b3d 100644
--- a/msm8226/libhwcomposer/hwc_copybit.cpp
+++ b/msm8226/libhwcomposer/hwc_copybit.cpp
@@ -40,7 +40,7 @@
 
     region_iterator(hwc_region_t region) {
         mRegion = region;
-        r.end = region.numRects;
+        r.end = (int)region.numRects;
         r.current = 0;
         this->next = iterate;
     }
@@ -131,6 +131,144 @@
     return renderArea;
 }
 
+int CopyBit::getLayersChanging(hwc_context_t *ctx,
+                      hwc_display_contents_1_t *list,
+                      int dpy){
+
+   int changingLayerIndex = -1;
+   if(mLayerCache.layerCount != ctx->listStats[dpy].numAppLayers) {
+        mLayerCache.reset();
+        mFbCache.reset();
+        mLayerCache.updateCounts(ctx,list,dpy);
+        return -1;
+    }
+
+    int updatingLayerCount = 0;
+    for (int k = ctx->listStats[dpy].numAppLayers-1; k >= 0 ; k--){
+       //swap rect will kick in only for single updating layer
+       if(mLayerCache.hnd[k] != list->hwLayers[k].handle){
+           updatingLayerCount ++;
+           if(updatingLayerCount == 1)
+             changingLayerIndex = k;
+       }
+    }
+    //since we are using more than one framebuffers,we have to
+    //kick in swap rect only if we are getting continuous same
+    //dirty rect for same layer at least equal of number of
+    //framebuffers
+
+    if ( updatingLayerCount ==  1 ) {
+       hwc_rect_t dirtyRect = list->hwLayers[changingLayerIndex].displayFrame;
+#ifdef QCOM_BSP
+       dirtyRect = list->hwLayers[changingLayerIndex].dirtyRect;
+#endif
+
+       for (int k = ctx->listStats[dpy].numAppLayers-1; k >= 0 ; k--){
+            //disable swap rect for overlapping visible layer(s)
+            hwc_rect_t displayFrame = list->hwLayers[k].displayFrame;
+            hwc_rect_t result = getIntersection(displayFrame,dirtyRect);
+            if((k != changingLayerIndex) && isValidRect(result)){
+              return -1;
+           }
+       }
+       mFbCache.insertAndUpdateFbCache(dirtyRect);
+       if(mFbCache.getUnchangedFbDRCount(dirtyRect) <
+                                             NUM_RENDER_BUFFERS)
+              changingLayerIndex =  -1;
+    }else {
+       mFbCache.reset();
+       changingLayerIndex =  -1;
+    }
+    mLayerCache.updateCounts(ctx,list,dpy);
+    return changingLayerIndex;
+}
+
+int CopyBit::checkDirtyRect(hwc_context_t *ctx,
+                           hwc_display_contents_1_t *list,
+                           int dpy) {
+
+   //dirty rect will enable only if
+   //1.Only single layer is updating.
+   //2.No overlapping
+   //3.No scaling
+   //4.No video layer
+   if(mSwapRectEnable == false)
+      return -1;
+   int changingLayerIndex =  getLayersChanging(ctx, list, dpy);
+   //swap rect will kick in only for single updating layer
+   if(changingLayerIndex == -1){
+      return -1;
+   }
+   if(!needsScaling(&list->hwLayers[changingLayerIndex])){
+     private_handle_t *hnd =
+         (private_handle_t *)list->hwLayers[changingLayerIndex].handle;
+      if( hnd && !isYuvBuffer(hnd))
+           return  changingLayerIndex;
+   }
+   return -1;
+}
+
+bool CopyBit::prepareOverlap(hwc_context_t *ctx,
+                             hwc_display_contents_1_t *list) {
+
+    if (ctx->mMDP.version < qdutils::MDP_V4_0) {
+        ALOGE("%s: Invalid request", __FUNCTION__);
+        return false;
+    }
+
+    if (mEngine == NULL || !(validateParams(ctx, list))) {
+        ALOGE("%s: Invalid Params", __FUNCTION__);
+        return false;
+    }
+    PtorInfo* ptorInfo = &(ctx->mPtorInfo);
+
+    // Allocate render buffers if they're not allocated
+    int alignW = 0, alignH = 0;
+    int finalW = 0, finalH = 0;
+    for (int i = 0; i < ptorInfo->count; i++) {
+        int ovlapIndex = ptorInfo->layerIndex[i];
+        hwc_rect_t overlap = list->hwLayers[ovlapIndex].displayFrame;
+        // render buffer width will be the max of two layers
+        // Align Widht and height to 32, Mdp would be configured
+        // with Aligned overlap w/h
+        finalW = max(finalW, ALIGN((overlap.right - overlap.left), 32));
+        finalH += ALIGN((overlap.bottom - overlap.top), 32);
+        if(finalH > ALIGN((overlap.bottom - overlap.top), 32)) {
+            // Calculate the offset for RGBA(4BPP)
+            ptorInfo->mRenderBuffOffset[i] = finalW *
+                (finalH - ALIGN((overlap.bottom - overlap.top), 32)) * 4;
+            // Calculate the dest top, left will always be zero
+            ptorInfo->displayFrame[i].top = (finalH -
+                                (ALIGN((overlap.bottom - overlap.top), 32)));
+        }
+        // calculate the right and bottom values
+        ptorInfo->displayFrame[i].right =  ptorInfo->displayFrame[i].left +
+                                            (overlap.right - overlap.left);
+        ptorInfo->displayFrame[i].bottom = ptorInfo->displayFrame[i].top +
+                                            (overlap.bottom - overlap.top);
+    }
+
+    getBufferSizeAndDimensions(finalW, finalH, HAL_PIXEL_FORMAT_RGBA_8888,
+                               alignW, alignH);
+
+    if ((mAlignedWidth != alignW) || (mAlignedHeight != alignH)) {
+        // Overlap rect has changed, so free render buffers
+        freeRenderBuffers();
+    }
+
+    int ret = allocRenderBuffers(alignW, alignH, HAL_PIXEL_FORMAT_RGBA_8888);
+
+    if (ret < 0) {
+        ALOGE("%s: Render buffer allocation failed", __FUNCTION__);
+        return false;
+    }
+
+    mAlignedWidth = alignW;
+    mAlignedHeight = alignH;
+    mCurRenderBufferIndex = (mCurRenderBufferIndex + 1) % NUM_RENDER_BUFFERS;
+    return true;
+}
+
 bool CopyBit::prepare(hwc_context_t *ctx, hwc_display_contents_1_t *list,
                                                             int dpy) {
 
@@ -195,8 +333,8 @@
                          __FUNCTION__, dst_w,src_w,dst_h,src_h);
               return false;
             }
-            dx = (float)dst_w/src_w;
-            dy = (float)dst_h/src_h;
+            dx = (float)dst_w/(float)src_w;
+            dy = (float)dst_h/(float)src_h;
 
             if (dx > MAX_SCALE_FACTOR || dx < MIN_SCALE_FACTOR)
                 return false;
@@ -209,8 +347,8 @@
     //Allocate render buffers if they're not allocated
     if (ctx->mMDP.version != qdutils::MDP_V3_0_4 &&
             (useCopybitForYUV || useCopybitForRGB)) {
-        int ret = allocRenderBuffers(mAlignedFBWidth,
-                                     mAlignedFBHeight,
+        int ret = allocRenderBuffers(mAlignedWidth,
+                                     mAlignedHeight,
                                      HAL_PIXEL_FORMAT_RGBA_8888);
         if (ret < 0) {
             return false;
@@ -232,11 +370,11 @@
         // Mark all layers to be drawn by copybit
         for (int i = ctx->listStats[dpy].numAppLayers-1; i >= 0 ; i--) {
             layerProp[i].mFlags |= HWC_COPYBIT;
-            if (ctx->mMDP.version == qdutils::MDP_V3_0_4) {
-                LOG_ALWAYS_FATAL("Cannot handle HWC_BLIT");
-                //list->hwLayers[i].compositionType = HWC_BLIT;
-            }
+#ifdef QCOM_BSP
+            if (ctx->mMDP.version == qdutils::MDP_V3_0_4)
+                list->hwLayers[i].compositionType = HWC_BLIT;
             else
+#endif
                 list->hwLayers[i].compositionType = HWC_OVERLAY;
         }
     }
@@ -263,8 +401,81 @@
     return ret;
 }
 
-bool CopyBit::draw(hwc_context_t *ctx, hwc_display_contents_1_t *list,
-                                                        int dpy, int32_t *fd) {
+bool CopyBit::drawUsingAppBufferComposition(hwc_context_t *ctx,
+                                      hwc_display_contents_1_t *list,
+                                      int dpy, int *copybitFd) {
+     int layerCount = 0;
+     uint32_t last = (uint32_t)list->numHwLayers - 1;
+     hwc_layer_1_t *fbLayer = &list->hwLayers[last];
+     private_handle_t *fbhnd = (private_handle_t *)fbLayer->handle;
+
+    if(ctx->enableABC == false)
+       return false;
+
+    if(ctx->listStats[dpy].numAppLayers > MAX_LAYERS_FOR_ABC )
+       return false;
+
+    layerCount = ctx->listStats[dpy].numAppLayers;
+    //bottom most layer should
+    //equal to FB
+    hwc_layer_1_t *tmpLayer = &list->hwLayers[0];
+    private_handle_t *hnd = (private_handle_t *)tmpLayer->handle;
+    if(hnd && fbhnd && (hnd->size == fbhnd->size) &&
+    (hnd->width == fbhnd->width) && (hnd->height == fbhnd->height)){
+       if(tmpLayer->transform  ||
+       (!(hnd->format == HAL_PIXEL_FORMAT_RGBA_8888 ||
+       hnd->format == HAL_PIXEL_FORMAT_RGBX_8888))  ||
+                   (needsScaling(tmpLayer) == true)) {
+          return false;
+       }else {
+          ctx->listStats[dpy].renderBufIndexforABC = 0;
+       }
+    }
+
+    if(ctx->listStats[dpy].renderBufIndexforABC == 0) {
+       if(layerCount == 1)
+          return true;
+
+       if(layerCount ==  MAX_LAYERS_FOR_ABC) {
+          int abcRenderBufIdx = ctx->listStats[dpy].renderBufIndexforABC;
+          //enable ABC only for non intersecting layers.
+          hwc_rect_t displayFrame =
+                  list->hwLayers[abcRenderBufIdx].displayFrame;
+          for (int i = abcRenderBufIdx + 1; i < layerCount; i++) {
+             hwc_rect_t tmpDisplayFrame = list->hwLayers[i].displayFrame;
+             hwc_rect_t result = getIntersection(displayFrame,tmpDisplayFrame);
+             if (isValidRect(result)) {
+                ctx->listStats[dpy].renderBufIndexforABC = -1;
+                return false;
+             }
+          }
+          // Pass the Acquire Fence FD to driver for base layer
+          private_handle_t *renderBuffer =
+          (private_handle_t *)list->hwLayers[abcRenderBufIdx].handle;
+          copybit_device_t *copybit = getCopyBitDevice();
+          if(list->hwLayers[abcRenderBufIdx].acquireFenceFd >=0){
+             copybit->set_sync(copybit,
+             list->hwLayers[abcRenderBufIdx].acquireFenceFd);
+          }
+          for(int i = abcRenderBufIdx + 1; i < layerCount; i++){
+             int retVal = drawLayerUsingCopybit(ctx,
+               &(list->hwLayers[i]),renderBuffer, 0);
+             if(retVal < 0) {
+                ALOGE("%s : Copybit failed", __FUNCTION__);
+             }
+          }
+          // Get Release Fence FD of copybit for the App layer(s)
+          copybit->flush_get_fence(copybit, copybitFd);
+          close(list->hwLayers[abcRenderBufIdx].acquireFenceFd);
+          list->hwLayers[abcRenderBufIdx].acquireFenceFd = -1;
+          return true;
+       }
+    }
+    return false;
+}
+
+bool  CopyBit::draw(hwc_context_t *ctx, hwc_display_contents_1_t *list,
+                                                          int dpy, int32_t *fd) {
     // draw layers marked for COPYBIT
     int retVal = true;
     int copybitLayerCount = 0;
@@ -272,12 +483,17 @@
     LayerProp *layerProp = ctx->layerProp[dpy];
     private_handle_t *renderBuffer;
 
-    if(mCopyBitDraw == false) // there is no layer marked for copybit
-        return false ;
+    if(mCopyBitDraw == false){
+       mFbCache.reset(); // there is no layer marked for copybit
+       return false ;
+    }
 
+    if(drawUsingAppBufferComposition(ctx, list, dpy, fd)) {
+       return true;
+    }
     //render buffer
     if (ctx->mMDP.version == qdutils::MDP_V3_0_4) {
-        last = list->numHwLayers - 1;
+        last = (uint32_t)list->numHwLayers - 1;
         renderBuffer = (private_handle_t *)list->hwLayers[last].handle;
     } else {
         renderBuffer = getCurrentRenderBuffer();
@@ -301,21 +517,29 @@
         }
     }
 
-    //Clear the transparent or left out region on the render buffer
-    hwc_rect_t clearRegion = {0,0,0,0};
-    if(CBUtils::getuiClearRegion(list, clearRegion, layerProp))
-        clear(renderBuffer, clearRegion);
+    mDirtyLayerIndex =  checkDirtyRect(ctx, list, dpy);
+    if( mDirtyLayerIndex != -1){
+          hwc_layer_1_t *layer = &list->hwLayers[mDirtyLayerIndex];
+#ifdef QCOM_BSP
+          clear(renderBuffer,layer->dirtyRect);
+#else
+          clear(renderBuffer,layer->displayFrame);
+#endif
+    } else {
+          hwc_rect_t clearRegion = {0,0,0,0};
+          if(CBUtils::getuiClearRegion(list, clearRegion, layerProp))
+             clear(renderBuffer, clearRegion);
+    }
 
     // numAppLayers-1, as we iterate from 0th layer index with HWC_COPYBIT flag
     for (int i = 0; i <= (ctx->listStats[dpy].numAppLayers-1); i++) {
-        hwc_layer_1_t *layer = &list->hwLayers[i];
         if(!(layerProp[i].mFlags & HWC_COPYBIT)) {
             ALOGD_IF(DEBUG_COPYBIT, "%s: Not Marked for copybit", __FUNCTION__);
             continue;
         }
-        if(layer->flags & HWC_SKIP_HWC_COMPOSITION){
+        //skip non updating layers
+        if((mDirtyLayerIndex != -1) && (mDirtyLayerIndex != i) )
             continue;
-        }
         int ret = -1;
         if (list->hwLayers[i].acquireFenceFd != -1
                 && ctx->mMDP.version >= qdutils::MDP_V4_0) {
@@ -329,7 +553,7 @@
             list->hwLayers[i].acquireFenceFd = -1;
         }
         retVal = drawLayerUsingCopybit(ctx, &(list->hwLayers[i]),
-                                                    renderBuffer, !i);
+                                          renderBuffer, !i);
         copybitLayerCount++;
         if(retVal < 0) {
             ALOGE("%s : drawLayerUsingCopybit failed", __FUNCTION__);
@@ -349,6 +573,149 @@
     return true;
 }
 
+int CopyBit::drawOverlap(hwc_context_t *ctx, hwc_display_contents_1_t *list) {
+    int fd = -1;
+    PtorInfo* ptorInfo = &(ctx->mPtorInfo);
+
+    if (ctx->mMDP.version < qdutils::MDP_V4_0) {
+        ALOGE("%s: Invalid request", __FUNCTION__);
+        return fd;
+    }
+
+    private_handle_t *renderBuffer = getCurrentRenderBuffer();
+
+    if (!renderBuffer) {
+        ALOGE("%s: Render buffer layer handle is NULL", __FUNCTION__);
+        return fd;
+    }
+
+    int copybitLayerCount = 0;
+    for(int j = 0; j < ptorInfo->count; j++) {
+        int ovlapIndex = ptorInfo->layerIndex[j];
+        hwc_rect_t overlap = list->hwLayers[ovlapIndex].displayFrame;
+
+        // Draw overlapped content of layers on render buffer
+        for (int i = 0; i <= ovlapIndex; i++) {
+            hwc_layer_1_t *layer = &list->hwLayers[i];
+            if(!isValidRect(getIntersection(layer->displayFrame,
+                                               overlap))) {
+                continue;
+            }
+            if ((list->hwLayers[i].acquireFenceFd != -1)) {
+                // Wait for acquire fence on the App buffers.
+                if(sync_wait(list->hwLayers[i].acquireFenceFd, 1000) < 0) {
+                    ALOGE("%s: sync_wait error!! error no = %d err str = %s",
+                          __FUNCTION__, errno, strerror(errno));
+                }
+                close(list->hwLayers[i].acquireFenceFd);
+                list->hwLayers[i].acquireFenceFd = -1;
+            }
+
+            int retVal = drawRectUsingCopybit(ctx, layer, renderBuffer, overlap,
+                                                ptorInfo->displayFrame[j]);
+            copybitLayerCount++;
+            if(retVal < 0) {
+                ALOGE("%s: drawRectUsingCopybit failed", __FUNCTION__);
+                copybitLayerCount = 0;
+            }
+        }
+    }
+
+    if (copybitLayerCount) {
+        copybit_device_t *copybit = getCopyBitDevice();
+        copybit->flush_get_fence(copybit, &fd);
+    }
+
+    ALOGD_IF(DEBUG_COPYBIT, "%s: done! copybitLayerCount = %d", __FUNCTION__,
+             copybitLayerCount);
+    return fd;
+}
+
+int CopyBit::drawRectUsingCopybit(hwc_context_t *dev, hwc_layer_1_t *layer,
+                        private_handle_t *renderBuffer, hwc_rect_t overlap,
+                        hwc_rect_t destRect)
+{
+    hwc_context_t* ctx = (hwc_context_t*)(dev);
+    if (!ctx) {
+        ALOGE("%s: null context ", __FUNCTION__);
+        return -1;
+    }
+
+    private_handle_t *hnd = (private_handle_t *)layer->handle;
+    if (!hnd) {
+        ALOGE("%s: invalid handle", __FUNCTION__);
+        return -1;
+    }
+
+    private_handle_t *dstHandle = (private_handle_t *)renderBuffer;
+    if (!dstHandle) {
+        ALOGE("%s: RenderBuffer handle is NULL", __FUNCTION__);
+        return -1;
+    }
+
+    // Set the Copybit Source
+    copybit_image_t src;
+    src.handle = (native_handle_t *)layer->handle;
+    src.w = hnd->width;
+    src.h = hnd->height;
+    src.base = (void *)hnd->base;
+    src.format = hnd->format;
+    src.horiz_padding = 0;
+    src.vert_padding = 0;
+
+
+    hwc_rect_t dispFrame = layer->displayFrame;
+    hwc_rect_t iRect = getIntersection(dispFrame, overlap);
+    hwc_rect_t crop = integerizeSourceCrop(layer->sourceCropf);
+    qhwc::calculate_crop_rects(crop, dispFrame, iRect,
+                               layer->transform);
+
+    // Copybit source rect
+    copybit_rect_t srcRect = {crop.left, crop.top, crop.right,
+        crop.bottom};
+
+    // Copybit destination rect
+    copybit_rect_t dstRect = {destRect.left, destRect.top, destRect.right,
+        destRect.bottom};
+
+    // Copybit dst
+    copybit_image_t dst;
+    dst.handle = (native_handle_t *)dstHandle;
+    dst.w = ALIGN(dstHandle->width, 32);
+    dst.h = dstHandle->height;
+    dst.base = (void *)dstHandle->base;
+    dst.format = dstHandle->format;
+
+    copybit_device_t *copybit = mEngine;
+
+    // Copybit region is the destRect
+    hwc_rect_t regRect = {dstRect.l,dstRect.t, dstRect.r, dstRect.b};
+    hwc_region_t region;
+    region.numRects = 1;
+    region.rects  = &regRect;
+    region_iterator copybitRegion(region);
+    int acquireFd = layer->acquireFenceFd;
+
+    copybit->set_parameter(copybit, COPYBIT_FRAMEBUFFER_WIDTH,
+                           renderBuffer->width);
+    copybit->set_parameter(copybit, COPYBIT_FRAMEBUFFER_HEIGHT,
+                           renderBuffer->height);
+    copybit->set_parameter(copybit, COPYBIT_TRANSFORM, layer->transform);
+    copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, layer->planeAlpha);
+    copybit->set_parameter(copybit, COPYBIT_BLEND_MODE, layer->blending);
+    copybit->set_parameter(copybit, COPYBIT_DITHER,
+        (dst.format == HAL_PIXEL_FORMAT_RGB_565) ? COPYBIT_ENABLE :
+        COPYBIT_DISABLE);
+    copybit->set_sync(copybit, acquireFd);
+    int err = copybit->stretch(copybit, &dst, &src, &dstRect, &srcRect,
+                               &copybitRegion);
+
+    if (err < 0)
+        ALOGE("%s: copybit stretch failed",__FUNCTION__);
+
+    return err;
+}
+
 int  CopyBit::drawLayerUsingCopybit(hwc_context_t *dev, hwc_layer_1_t *layer,
                           private_handle_t *renderBuffer, bool isFG)
 {
@@ -429,7 +796,16 @@
     copybit_rect_t dstRect = {displayFrame.left, displayFrame.top,
                               displayFrame.right,
                               displayFrame.bottom};
-
+#ifdef QCOM_BSP
+    //change src and dst with dirtyRect
+    if(mDirtyLayerIndex != -1) {
+      srcRect.l = layer->dirtyRect.left;
+      srcRect.t = layer->dirtyRect.top;
+      srcRect.r = layer->dirtyRect.right;
+      srcRect.b = layer->dirtyRect.bottom;
+      dstRect = srcRect;
+    }
+#endif
     // Copybit dst
     copybit_image_t dst;
     dst.w = ALIGN(fbHandle->width,32);
@@ -466,8 +842,8 @@
         return -1;
     }
 
-    float dsdx = (float)screen_w/src_crop_width;
-    float dtdy = (float)screen_h/src_crop_height;
+    float dsdx = (float)screen_w/(float)src_crop_width;
+    float dtdy = (float)screen_h/(float)src_crop_height;
 
     float scaleLimitMax = copybitsMaxScale * copybitsMaxScale;
     float scaleLimitMin = copybitsMinScale * copybitsMinScale;
@@ -498,14 +874,14 @@
        int tmp_h =  src_crop_height;
 
        if (dsdx > copybitsMaxScale || dtdy > copybitsMaxScale ){
-         tmp_w = src_crop_width*copybitsMaxScale;
-         tmp_h = src_crop_height*copybitsMaxScale;
+         tmp_w = (int)((float)src_crop_width*copybitsMaxScale);
+         tmp_h = (int)((float)src_crop_height*copybitsMaxScale);
        }else if (dsdx < 1/copybitsMinScale ||dtdy < 1/copybitsMinScale ){
          // ceil the tmp_w and tmp_h value to maintain proper ratio
          // b/w src and dst (should not cross the desired scale limit
          // due to float -> int )
-         tmp_w = ceil(src_crop_width/copybitsMinScale);
-         tmp_h = ceil(src_crop_height/copybitsMinScale);
+         tmp_w = (int)ceil((float)src_crop_width/copybitsMinScale);
+         tmp_h = (int)ceil((float)src_crop_height/copybitsMinScale);
        }
        ALOGD("%s:%d::tmp_w = %d,tmp_h = %d",__FUNCTION__,__LINE__,tmp_w,tmp_h);
 
@@ -710,18 +1086,30 @@
     mRelFd[mCurRenderBufferIndex] = dup(fd);
 }
 
+void CopyBit::setReleaseFdSync(int fd) {
+    if (mRelFd[mCurRenderBufferIndex] >=0) {
+        int ret = -1;
+        ret = sync_wait(mRelFd[mCurRenderBufferIndex], 1000);
+        if (ret < 0)
+            ALOGE("%s: sync_wait error! errno = %d, err str = %s",
+                  __FUNCTION__, errno, strerror(errno));
+        close(mRelFd[mCurRenderBufferIndex]);
+    }
+    mRelFd[mCurRenderBufferIndex] = dup(fd);
+}
+
 struct copybit_device_t* CopyBit::getCopyBitDevice() {
     return mEngine;
 }
 
-CopyBit::CopyBit(hwc_context_t *ctx, const int& dpy) : mIsModeOn(false),
-        mCopyBitDraw(false), mCurRenderBufferIndex(0) {
+CopyBit::CopyBit(hwc_context_t *ctx, const int& dpy) :  mEngine(0),
+    mIsModeOn(false), mCopyBitDraw(false), mCurRenderBufferIndex(0) {
 
     getBufferSizeAndDimensions(ctx->dpyAttr[dpy].xres,
             ctx->dpyAttr[dpy].yres,
             HAL_PIXEL_FORMAT_RGBA_8888,
-            mAlignedFBWidth,
-            mAlignedFBHeight);
+            mAlignedWidth,
+            mAlignedHeight);
 
     hw_module_t const *module;
     for (int i = 0; i < NUM_RENDER_BUFFERS; i++) {
@@ -733,6 +1121,9 @@
     property_get("debug.hwc.dynThreshold", value, "2");
     mDynThreshold = atof(value);
 
+    property_get("debug.sf.swaprect", value, "0");
+    mSwapRectEnable = atoi(value) ? true:false ;
+    mDirtyLayerIndex = -1;
     if (hw_get_module(COPYBIT_HARDWARE_MODULE_ID, &module) == 0) {
         if(copybit_open(module, &mEngine) < 0) {
             ALOGE("FATAL ERROR: copybit open failed.");
@@ -751,4 +1142,43 @@
         mEngine = NULL;
     }
 }
+CopyBit::LayerCache::LayerCache() {
+    reset();
+}
+void CopyBit::LayerCache::reset() {
+    memset(&hnd, 0, sizeof(hnd));
+    layerCount = 0;
+}
+void CopyBit::LayerCache::updateCounts(hwc_context_t *ctx,
+              hwc_display_contents_1_t *list, int dpy)
+{
+   layerCount = ctx->listStats[dpy].numAppLayers;
+   for (int i=0; i<ctx->listStats[dpy].numAppLayers; i++){
+      hnd[i] = list->hwLayers[i].handle;
+   }
+}
+
+CopyBit::FbCache::FbCache() {
+     reset();
+}
+void CopyBit::FbCache::reset() {
+     memset(&FbdirtyRect, 0, sizeof(FbdirtyRect));
+     FbIndex =0;
+}
+
+void CopyBit::FbCache::insertAndUpdateFbCache(hwc_rect_t dirtyRect) {
+   FbIndex =  FbIndex % NUM_RENDER_BUFFERS;
+   FbdirtyRect[FbIndex] = dirtyRect;
+   FbIndex++;
+}
+
+int CopyBit::FbCache::getUnchangedFbDRCount(hwc_rect_t dirtyRect){
+    int sameDirtyCount = 0;
+    for (int i = 0 ; i < NUM_RENDER_BUFFERS ; i++ ){
+      if( FbdirtyRect[i] == dirtyRect)
+           sameDirtyCount++;
+   }
+   return sameDirtyCount;
+}
+
 }; //namespace qhwc
diff --git a/msm8226/libhwcomposer/hwc_copybit.h b/msm8226/libhwcomposer/hwc_copybit.h
index f7be644..99a39c8 100644
--- a/msm8226/libhwcomposer/hwc_copybit.h
+++ b/msm8226/libhwcomposer/hwc_copybit.h
@@ -27,7 +27,7 @@
 //twice
 #define MAX_SCALE_FACTOR 16
 #define MIN_SCALE_FACTOR 0.0625
-
+#define MAX_LAYERS_FOR_ABC 2
 namespace qhwc {
 
 class CopyBit {
@@ -49,12 +49,46 @@
 
     void setReleaseFd(int fd);
 
+    void setReleaseFdSync(int fd);
+
+    bool prepareOverlap(hwc_context_t *ctx, hwc_display_contents_1_t *list);
+
+    int drawOverlap(hwc_context_t *ctx, hwc_display_contents_1_t *list);
+
 private:
+    /* cached data */
+    struct LayerCache {
+      int layerCount;
+      buffer_handle_t hnd[MAX_NUM_APP_LAYERS];
+      /* c'tor */
+      LayerCache();
+      /* clear caching info*/
+      void reset();
+      void updateCounts(hwc_context_t *ctx, hwc_display_contents_1_t *list,
+              int dpy);
+    };
+    /* framebuffer cache*/
+    struct FbCache {
+      hwc_rect_t  FbdirtyRect[NUM_RENDER_BUFFERS];
+      int FbIndex;
+      FbCache();
+      void reset();
+      void insertAndUpdateFbCache(hwc_rect_t dirtyRect);
+      int getUnchangedFbDRCount(hwc_rect_t dirtyRect);
+    };
+
     // holds the copybit device
     struct copybit_device_t *mEngine;
+    bool drawUsingAppBufferComposition(hwc_context_t *ctx,
+                                hwc_display_contents_1_t *list,
+                                int dpy, int *fd);
     // Helper functions for copybit composition
     int  drawLayerUsingCopybit(hwc_context_t *dev, hwc_layer_1_t *layer,
                           private_handle_t *renderBuffer, bool isFG);
+    // Helper function to draw copybit layer for PTOR comp
+    int drawRectUsingCopybit(hwc_context_t *dev, hwc_layer_1_t *layer,
+                          private_handle_t *renderBuffer, hwc_rect_t overlap,
+                          hwc_rect_t destRect);
     int fillColorUsingCopybit(hwc_layer_1_t *layer,
                           private_handle_t *renderBuffer);
     bool canUseCopybitForYUV (hwc_context_t *ctx);
@@ -89,8 +123,16 @@
 
     //Dynamic composition threshold for deciding copybit usage.
     double mDynThreshold;
-    int mAlignedFBWidth;
-    int mAlignedFBHeight;
+    bool mSwapRectEnable;
+    int mAlignedWidth;
+    int mAlignedHeight;
+    int mDirtyLayerIndex;
+    LayerCache mLayerCache;
+    FbCache mFbCache;
+    int getLayersChanging(hwc_context_t *ctx, hwc_display_contents_1_t *list,
+                  int dpy);
+    int checkDirtyRect(hwc_context_t *ctx, hwc_display_contents_1_t *list,
+                  int dpy);
 };
 
 }; //namespace qhwc
diff --git a/msm8226/libhwcomposer/hwc_dump_layers.cpp b/msm8226/libhwcomposer/hwc_dump_layers.cpp
index b7bc731..c8ebac9 100644
--- a/msm8226/libhwcomposer/hwc_dump_layers.cpp
+++ b/msm8226/libhwcomposer/hwc_dump_layers.cpp
@@ -36,6 +36,10 @@
 #include <cutils/log.h>
 #include <sys/stat.h>
 #include <comptype.h>
+#ifdef QCOM_BSP
+#include <SkBitmap.h>
+#include <SkImageEncoder.h>
+#endif
 #ifdef STDC_FORMAT_MACROS
 #include <inttypes.h>
 #endif
@@ -209,7 +213,7 @@
 void HwcDebug::logLayer(size_t layerIndex, hwc_layer_1_t hwLayers[])
 {
     if (NULL == hwLayers) {
-        ALOGE("Display[%s] Layer[%d] Error. No hwc layers to log.",
+        ALOGE("Display[%s] Layer[%zu] Error. No hwc layers to log.",
             mDisplayName, layerIndex);
         return;
     }
@@ -236,7 +240,7 @@
         getHalPixelFormatStr(hnd->format, pixFormatStr);
 
     // Log Line 1
-    ALOGI("Display[%s] Layer[%d] SrcBuff[%dx%d] SrcCrop[%dl, %dt, %dr, %db] "
+    ALOGI("Display[%s] Layer[%zu] SrcBuff[%dx%d] SrcCrop[%dl, %dt, %dr, %db] "
         "DispFrame[%dl, %dt, %dr, %db] VisRegsScr%s", mDisplayName, layerIndex,
         (hnd)? getWidth(hnd) : -1, (hnd)? getHeight(hnd) : -1,
         sourceCrop.left, sourceCrop.top,
@@ -245,7 +249,7 @@
         displayFrame.right, displayFrame.bottom,
         hwcVisRegsScrLog.string());
     // Log Line 2
-    ALOGI("Display[%s] Layer[%d] LayerCompType = %s, Format = %s, "
+    ALOGI("Display[%s] Layer[%zu] LayerCompType = %s, Format = %s, "
         "Orientation = %s, Flags = %s%s%s, Hints = %s%s%s, "
         "Blending = %s%s%s", mDisplayName, layerIndex,
         (layer->compositionType == HWC_FRAMEBUFFER)? "Framebuffer(GPU)":
@@ -272,19 +276,25 @@
 {
     char dumpLogStrPng[128] = "";
     char dumpLogStrRaw[128] = "";
+    bool needDumpPng = (mDumpCntrPng <= mDumpCntLimPng)? true:false;
     bool needDumpRaw = (mDumpCntrRaw <= mDumpCntLimRaw)? true:false;
 
+    if (needDumpPng) {
+        snprintf(dumpLogStrPng, sizeof(dumpLogStrPng),
+            "[png-dump-frame: %03d of %03d]", mDumpCntrPng,
+            mDumpCntLimPng);
+    }
     if (needDumpRaw) {
         snprintf(dumpLogStrRaw, sizeof(dumpLogStrRaw),
             "[raw-dump-frame: %03d of %03d]", mDumpCntrRaw,
             mDumpCntLimRaw);
     }
 
-    if (!needDumpRaw)
+    if (!(needDumpPng || needDumpRaw))
         return;
 
     if (NULL == hwLayers) {
-        ALOGE("Display[%s] Layer[%d] %s%s Error: No hwc layers to dump.",
+        ALOGE("Display[%s] Layer[%zu] %s%s Error: No hwc layers to dump.",
             mDisplayName, layerIndex, dumpLogStrRaw, dumpLogStrPng);
         return;
     }
@@ -294,18 +304,57 @@
     char pixFormatStr[32] = "None";
 
     if (NULL == hnd) {
-        ALOGI("Display[%s] Layer[%d] %s%s Skipping dump: Bufferless layer.",
+        ALOGI("Display[%s] Layer[%zu] %s%s Skipping dump: Bufferless layer.",
             mDisplayName, layerIndex, dumpLogStrRaw, dumpLogStrPng);
         return;
     }
 
     getHalPixelFormatStr(hnd->format, pixFormatStr);
+#ifdef QCOM_BSP
+    if (needDumpPng && hnd->base) {
+        bool bResult = false;
+        char dumpFilename[PATH_MAX];
+        SkBitmap *tempSkBmp = new SkBitmap();
+        SkBitmap::Config tempSkBmpConfig = SkBitmap::kNo_Config;
+        snprintf(dumpFilename, sizeof(dumpFilename),
+            "%s/sfdump%03d.layer%zu.%s.png", mDumpDirPng,
+            mDumpCntrPng, layerIndex, mDisplayName);
 
+        switch (hnd->format) {
+            case HAL_PIXEL_FORMAT_RGBA_8888:
+            case HAL_PIXEL_FORMAT_RGBX_8888:
+            case HAL_PIXEL_FORMAT_BGRA_8888:
+                tempSkBmpConfig = SkBitmap::kARGB_8888_Config;
+                break;
+            case HAL_PIXEL_FORMAT_RGB_565:
+                tempSkBmpConfig = SkBitmap::kRGB_565_Config;
+                break;
+            case HAL_PIXEL_FORMAT_RGB_888:
+            default:
+                tempSkBmpConfig = SkBitmap::kNo_Config;
+                break;
+        }
+        if (SkBitmap::kNo_Config != tempSkBmpConfig) {
+            tempSkBmp->setConfig(tempSkBmpConfig, getWidth(hnd), getHeight(hnd));
+            tempSkBmp->setPixels((void*)hnd->base);
+            bResult = SkImageEncoder::EncodeFile(dumpFilename,
+                                    *tempSkBmp, SkImageEncoder::kPNG_Type, 100);
+            ALOGI("Display[%s] Layer[%zu] %s Dump to %s: %s",
+                mDisplayName, layerIndex, dumpLogStrPng,
+                dumpFilename, bResult ? "Success" : "Fail");
+        } else {
+            ALOGI("Display[%s] Layer[%zu] %s Skipping dump: Unsupported layer"
+                " format %s for png encoder",
+                mDisplayName, layerIndex, dumpLogStrPng, pixFormatStr);
+        }
+        delete tempSkBmp; // Calls SkBitmap::freePixels() internally.
+    }
+#endif
     if (needDumpRaw && hnd->base) {
         char dumpFilename[PATH_MAX];
         bool bResult = false;
         snprintf(dumpFilename, sizeof(dumpFilename),
-            "%s/sfdump%03d.layer%d.%dx%d.%s.%s.raw",
+            "%s/sfdump%03d.layer%zu.%dx%d.%s.%s.raw",
             mDumpDirRaw, mDumpCntrRaw,
             layerIndex, getWidth(hnd), getHeight(hnd),
             pixFormatStr, mDisplayName);
@@ -314,7 +363,7 @@
             bResult = (bool) fwrite((void*)hnd->base, hnd->size, 1, fp);
             fclose(fp);
         }
-        ALOGI("Display[%s] Layer[%d] %s Dump to %s: %s",
+        ALOGI("Display[%s] Layer[%zu] %s Dump to %s: %s",
             mDisplayName, layerIndex, dumpLogStrRaw,
             dumpFilename, bResult ? "Success" : "Fail");
     }
@@ -385,7 +434,8 @@
             strlcpy(pixFormatStr, "YCbCr_420_SP_VENUS", sizeof(pixFormatStr));
             break;
         default:
-            snprintf(pixFormatStr, sizeof(pixFormatStr), "Unknown0x%X", format);
+            size_t len = sizeof(pixFormatStr);
+            snprintf(pixFormatStr, len, "Unknown0x%X", format);
             break;
     }
 }
diff --git a/msm8226/libhwcomposer/hwc_fbupdate.cpp b/msm8226/libhwcomposer/hwc_fbupdate.cpp
index bf2aee5..de4cd05 100644
--- a/msm8226/libhwcomposer/hwc_fbupdate.cpp
+++ b/msm8226/libhwcomposer/hwc_fbupdate.cpp
@@ -38,19 +38,25 @@
 namespace ovutils = overlay::utils;
 
 IFBUpdate* IFBUpdate::getObject(hwc_context_t *ctx, const int& dpy) {
-    if(isDisplaySplit(ctx, dpy)) {
-        if(qdutils::MDPVersion::getInstance().isSrcSplit()) {
-            return new FBSrcSplit(ctx, dpy);
-        }
+    if(qdutils::MDPVersion::getInstance().isSrcSplit()) {
+        return new FBSrcSplit(ctx, dpy);
+    } else if(isDisplaySplit(ctx, dpy)) {
         return new FBUpdateSplit(ctx, dpy);
     }
     return new FBUpdateNonSplit(ctx, dpy);
 }
 
 IFBUpdate::IFBUpdate(hwc_context_t *ctx, const int& dpy) : mDpy(dpy) {
-    size_t size = 0;
-    getBufferAttributes(ctx->dpyAttr[mDpy].xres,
-            ctx->dpyAttr[mDpy].yres,
+    unsigned int size = 0;
+    uint32_t xres = ctx->dpyAttr[mDpy].xres;
+    uint32_t yres = ctx->dpyAttr[mDpy].yres;
+    if (ctx->dpyAttr[dpy].customFBSize) {
+        //GPU will render and compose at new resolution
+        //So need to have FB at new resolution
+        xres = ctx->dpyAttr[mDpy].xres_new;
+        yres = ctx->dpyAttr[mDpy].yres_new;
+    }
+    getBufferAttributes((int)xres, (int)yres,
             HAL_PIXEL_FORMAT_RGBA_8888,
             0,
             mAlignedFBWidth,
@@ -66,8 +72,9 @@
 bool IFBUpdate::prepareAndValidate(hwc_context_t *ctx,
             hwc_display_contents_1 *list, int fbZorder) {
     hwc_layer_1_t *layer = &list->hwLayers[list->numHwLayers - 1];
-    return prepare(ctx, list, layer->displayFrame, fbZorder) &&
+    mModeOn = prepare(ctx, list, layer->displayFrame, fbZorder) &&
             ctx->mOverlay->validateAndSet(mDpy, ctx->dpyAttr[mDpy].fd);
+    return mModeOn;
 }
 
 //================= Low res====================================
@@ -91,6 +98,7 @@
     if(mDpy && (extOrient & HWC_TRANSFORM_ROT_90)) {
         mRot = ctx->mRotMgr->getNext();
         if(mRot == NULL) return false;
+        ctx->mLayerRotMap[mDpy]->add(layer, mRot);
         // Composed FB content will have black bars, if the viewFrame of the
         // external is different from {0, 0, fbWidth, fbHeight}, so intersect
         // viewFrame with sourceCrop to avoid those black bars
@@ -101,9 +109,7 @@
             mRot = NULL;
             return false;
         }
-        ctx->mLayerRotMap[mDpy]->add(layer, mRot);
-        info.format = (mRot)->getDstFormat();
-        updateSource(orient, info, sourceCrop);
+        updateSource(orient, info, sourceCrop, mRot);
         rotFlags |= ovutils::ROT_PREROTATED;
     }
     return true;
@@ -138,14 +144,14 @@
                 ovutils::getMdpFormat(HAL_PIXEL_FORMAT_RGBA_8888,
                     mTileEnabled));
 
-        //Request a pipe
-        ovutils::eMdpPipeType type = ovutils::OV_MDP_PIPE_ANY;
-        if((qdutils::MDPVersion::getInstance().is8x26() ||
-                   qdutils::MDPVersion::getInstance().is8x16()) && mDpy) {
-            //For 8x26 external always use DMA pipe
-            type = ovutils::OV_MDP_PIPE_DMA;
-        }
-        ovutils::eDest dest = ov.nextPipe(type, mDpy, Overlay::MIXER_DEFAULT);
+        Overlay::PipeSpecs pipeSpecs;
+        pipeSpecs.formatClass = Overlay::FORMAT_RGB;
+        pipeSpecs.needsScaling = qhwc::needsScaling(layer);
+        pipeSpecs.dpy = mDpy;
+        pipeSpecs.mixer = Overlay::MIXER_DEFAULT;
+        pipeSpecs.fb = true;
+
+        ovutils::eDest dest = ov.getPipe(pipeSpecs);
         if(dest == ovutils::OV_INVALID) { //None available
             ALOGE("%s: No pipes available to configure fb for dpy %d",
                 __FUNCTION__, mDpy);
@@ -191,7 +197,7 @@
                   (mDpy && !extOrient
                   && !ctx->dpyAttr[mDpy].mDownScaleMode))
                   && (extOnlyLayerIndex == -1)) {
-            if(!qdutils::MDPVersion::getInstance().is8x26() &&
+            if(ctx->mOverlay->isUIScalingOnExternalSupported() &&
                 !ctx->dpyAttr[mDpy].customFBSize) {
                 getNonWormholeRegion(list, sourceCrop);
                 displayFrame = sourceCrop;
@@ -201,14 +207,12 @@
                                    transform, orient);
         //Store the displayFrame, will be used in getDisplayViewFrame
         ctx->dpyAttr[mDpy].mDstRect = displayFrame;
-        setMdpFlags(layer, mdpFlags, 0, transform);
+        setMdpFlags(ctx, layer, mdpFlags, 0, transform);
         // For External use rotator if there is a rotation value set
         ret = preRotateExtDisplay(ctx, layer, info,
                 sourceCrop, mdpFlags, rotFlags);
         if(!ret) {
             ALOGE("%s: preRotate for external Failed!", __FUNCTION__);
-            ctx->mOverlay->clear(mDpy);
-            ctx->mLayerRotMap[mDpy]->clear();
             return false;
         }
         //For the mdp, since either we are pre-rotating or MDP does flips
@@ -223,7 +227,6 @@
         if(configMdp(ctx->mOverlay, parg, orient, sourceCrop, displayFrame,
                     NULL, mDest) < 0) {
             ALOGE("%s: configMdp failed for dpy %d", __FUNCTION__, mDpy);
-            ctx->mLayerRotMap[mDpy]->clear();
             ret = false;
         }
     }
@@ -239,7 +242,7 @@
     overlay::Overlay& ov = *(ctx->mOverlay);
     ovutils::eDest dest = mDest;
     int fd = hnd->fd;
-    uint32_t offset = hnd->offset;
+    uint32_t offset = (uint32_t)hnd->offset;
     if(mRot) {
         if(!mRot->queueBuffer(fd, offset))
             return false;
@@ -271,8 +274,8 @@
                  __FUNCTION__);
         return false;
     }
-    ALOGD_IF(DEBUG_FBUPDATE, "%s, mModeOn = %d", __FUNCTION__, mModeOn);
     mModeOn = configure(ctx, list, fbUpdatingRect, fbZorder);
+    ALOGD_IF(DEBUG_FBUPDATE, "%s, mModeOn = %d", __FUNCTION__, mModeOn);
     return mModeOn;
 }
 
@@ -307,10 +310,16 @@
         hwc_rect_t displayFrame = fbUpdatingRect;
 
         ret = true;
+        Overlay::PipeSpecs pipeSpecs;
+        pipeSpecs.formatClass = Overlay::FORMAT_RGB;
+        pipeSpecs.needsScaling = qhwc::needsScaling(layer);
+        pipeSpecs.dpy = mDpy;
+        pipeSpecs.fb = true;
+
         /* Configure left pipe */
         if(displayFrame.left < lSplit) {
-            ovutils::eDest destL = ov.nextPipe(ovutils::OV_MDP_PIPE_ANY, mDpy,
-                                               Overlay::MIXER_LEFT);
+            pipeSpecs.mixer = Overlay::MIXER_LEFT;
+            ovutils::eDest destL = ov.getPipe(pipeSpecs);
             if(destL == ovutils::OV_INVALID) { //None available
                 ALOGE("%s: No pipes available to configure fb for dpy %d's left"
                       " mixer", __FUNCTION__, mDpy);
@@ -343,8 +352,8 @@
 
         /* Configure right pipe */
         if(displayFrame.right > lSplit) {
-            ovutils::eDest destR = ov.nextPipe(ovutils::OV_MDP_PIPE_ANY, mDpy,
-                                               Overlay::MIXER_RIGHT);
+            pipeSpecs.mixer = Overlay::MIXER_RIGHT;
+            ovutils::eDest destR = ov.getPipe(pipeSpecs);
             if(destR == ovutils::OV_INVALID) { //None available
                 ALOGE("%s: No pipes available to configure fb for dpy %d's"
                       " right mixer", __FUNCTION__, mDpy);
@@ -380,10 +389,6 @@
                 ret = false;
             }
         }
-
-        if(ret == false) {
-            ctx->mLayerRotMap[mDpy]->clear();
-        }
     }
     return ret;
 }
@@ -396,14 +401,14 @@
     bool ret = true;
     overlay::Overlay& ov = *(ctx->mOverlay);
     if(mDestLeft != ovutils::OV_INVALID) {
-        if (!ov.queueBuffer(hnd->fd, hnd->offset, mDestLeft)) {
+        if (!ov.queueBuffer(hnd->fd, (uint32_t)hnd->offset, mDestLeft)) {
             ALOGE("%s: queue failed for left of dpy = %d",
                   __FUNCTION__, mDpy);
             ret = false;
         }
     }
     if(mDestRight != ovutils::OV_INVALID) {
-        if (!ov.queueBuffer(hnd->fd, hnd->offset, mDestRight)) {
+        if (!ov.queueBuffer(hnd->fd, (uint32_t)hnd->offset, mDestRight)) {
             ALOGE("%s: queue failed for right of dpy = %d",
                   __FUNCTION__, mDpy);
             ret = false;
@@ -418,7 +423,6 @@
 
 bool FBSrcSplit::configure(hwc_context_t *ctx, hwc_display_contents_1 *list,
         hwc_rect_t fbUpdatingRect, int fbZorder) {
-    bool ret = false;
     hwc_layer_1_t *layer = &list->hwLayers[list->numHwLayers - 1];
     int extOnlyLayerIndex = ctx->listStats[mDpy].extOnlyLayerIndex;
     // ext only layer present..
@@ -426,35 +430,13 @@
         layer = &list->hwLayers[extOnlyLayerIndex];
         layer->compositionType = HWC_OVERLAY;
     }
+
     overlay::Overlay& ov = *(ctx->mOverlay);
 
     ovutils::Whf info(mAlignedFBWidth,
             mAlignedFBHeight,
             ovutils::getMdpFormat(HAL_PIXEL_FORMAT_RGBA_8888,
                 mTileEnabled));
-    //Request left pipe, VG first owing to higher prio
-    ovutils::eDest destL = ov.nextPipe(ovutils::OV_MDP_PIPE_VG, mDpy,
-            Overlay::MIXER_DEFAULT);
-    if(destL == ovutils::OV_INVALID) {
-        destL = ov.nextPipe(ovutils::OV_MDP_PIPE_ANY, mDpy,
-            Overlay::MIXER_DEFAULT);
-        if(destL == ovutils::OV_INVALID) {
-            ALOGE("%s: No pipes available to configure fb for dpy %d's left"
-                    " mixer", __FUNCTION__, mDpy);
-            return false;
-        }
-    }
-    //Request right pipe
-    ovutils::eDest destR = ov.nextPipe(ovutils::OV_MDP_PIPE_ANY, mDpy,
-            Overlay::MIXER_DEFAULT);
-    if(destR == ovutils::OV_INVALID) {
-        ALOGE("%s: No pipes available to configure fb for dpy %d's right"
-                " mixer", __FUNCTION__, mDpy);
-        return false;
-    }
-
-    mDestLeft = destL;
-    mDestRight = destR;
 
     ovutils::eMdpFlags mdpFlags = OV_MDP_BLEND_FG_PREMULT;
     ovutils::eZorder zOrder = static_cast<ovutils::eZorder>(fbZorder);
@@ -467,46 +449,79 @@
             ovutils::DEFAULT_PLANE_ALPHA,
             (ovutils::eBlending)
             getBlending(layer->blending));
-    ov.setSource(parg, destL);
-    ov.setSource(parg, destR);
-
-    //Crop and Position are same for FB
-    ovutils::Dim cropPosL(
-            fbUpdatingRect.left,
-            fbUpdatingRect.top,
-            (fbUpdatingRect.right - fbUpdatingRect.left) / 2,
-            fbUpdatingRect.bottom - fbUpdatingRect.top);
-
-    ovutils::Dim cropPosR(
-            cropPosL.x + cropPosL.w,
-            cropPosL.y,
-            cropPosL.w,
-            cropPosL.h);
-
-    ov.setCrop(cropPosL, destL);
-    ov.setCrop(cropPosR, destR);
-    ov.setPosition(cropPosL, destL);
-    ov.setPosition(cropPosR, destR);
 
     int transform = layer->transform;
     ovutils::eTransform orient =
             static_cast<ovutils::eTransform>(transform);
-    ov.setTransform(orient, destL);
-    ov.setTransform(orient, destR);
 
-    ret = true;
-    if (!ov.commit(destL)) {
-        ALOGE("%s: commit fails for left", __FUNCTION__);
-        ret = false;
+    hwc_rect_t cropL = fbUpdatingRect;
+    hwc_rect_t cropR = fbUpdatingRect;
+
+    //Request left pipe (or 1 by default)
+    Overlay::PipeSpecs pipeSpecs;
+    pipeSpecs.formatClass = Overlay::FORMAT_RGB;
+    pipeSpecs.needsScaling = qhwc::needsScaling(layer);
+    pipeSpecs.dpy = mDpy;
+    pipeSpecs.mixer = Overlay::MIXER_DEFAULT;
+    pipeSpecs.fb = true;
+    ovutils::eDest destL = ov.getPipe(pipeSpecs);
+    if(destL == ovutils::OV_INVALID) {
+        ALOGE("%s: No pipes available to configure fb for dpy %d's left"
+                " mixer", __FUNCTION__, mDpy);
+        return false;
     }
-    if (!ov.commit(destR)) {
-        ALOGE("%s: commit fails for right", __FUNCTION__);
-        ret = false;
+
+    ovutils::eDest destR = ovutils::OV_INVALID;
+
+    /*  Use 2 pipes IF
+        a) FB's width is > 2048 or
+        b) On primary, driver has indicated with caps to split always. This is
+           based on an empirically derived value of panel height.
+    */
+
+    bool primarySplitAlways = (mDpy == HWC_DISPLAY_PRIMARY) and
+            qdutils::MDPVersion::getInstance().isSrcSplitAlways();
+
+    if(((fbUpdatingRect.right - fbUpdatingRect.left) >
+            qdutils::MAX_DISPLAY_DIM) or
+            primarySplitAlways) {
+        destR = ov.getPipe(pipeSpecs);
+        if(destR == ovutils::OV_INVALID) {
+            ALOGE("%s: No pipes available to configure fb for dpy %d's right"
+                    " mixer", __FUNCTION__, mDpy);
+            return false;
+        }
+
+        if(ctx->mOverlay->comparePipePriority(destL, destR) == -1) {
+            qhwc::swap(destL, destR);
+        }
+
+        //Split crop equally when using 2 pipes
+        cropL.right = (fbUpdatingRect.right + fbUpdatingRect.left) / 2;
+        cropR.left = cropL.right;
     }
-    if(ret == false) {
-        ctx->mLayerRotMap[mDpy]->clear();
+
+    mDestLeft = destL;
+    mDestRight = destR;
+
+    if(destL != OV_INVALID) {
+        if(configMdp(ctx->mOverlay, parg, orient,
+                    cropL, cropL, NULL /*metadata*/, destL) < 0) {
+            ALOGE("%s: commit failed for left mixer config", __FUNCTION__);
+            return false;
+        }
     }
-    return ret;
+
+    //configure right pipe
+    if(destR != OV_INVALID) {
+        if(configMdp(ctx->mOverlay, parg, orient,
+                    cropR, cropR, NULL /*metadata*/, destR) < 0) {
+            ALOGE("%s: commit failed for right mixer config", __FUNCTION__);
+            return false;
+        }
+    }
+
+    return true;
 }
 
 //---------------------------------------------------------------------
diff --git a/msm8226/libhwcomposer/hwc_mdpcomp.cpp b/msm8226/libhwcomposer/hwc_mdpcomp.cpp
index 95b477f..bbc6981 100644
--- a/msm8226/libhwcomposer/hwc_mdpcomp.cpp
+++ b/msm8226/libhwcomposer/hwc_mdpcomp.cpp
@@ -26,6 +26,7 @@
 #include "hwc_fbupdate.h"
 #include "hwc_ad.h"
 #include <overlayRotator.h>
+#include "hwc_copybit.h"
 
 using namespace overlay;
 using namespace qdutils;
@@ -42,17 +43,15 @@
 bool MDPComp::sDebugLogs = false;
 bool MDPComp::sEnabled = false;
 bool MDPComp::sEnableMixedMode = true;
-bool MDPComp::sEnablePartialFrameUpdate = false;
+int MDPComp::sSimulationFlags = 0;
 int MDPComp::sMaxPipesPerMixer = MAX_PIPES_PER_MIXER;
 bool MDPComp::sEnable4k2kYUVSplit = false;
 bool MDPComp::sSrcSplitEnabled = false;
 MDPComp* MDPComp::getObject(hwc_context_t *ctx, const int& dpy) {
-
-    if(isDisplaySplit(ctx, dpy)) {
-        if(qdutils::MDPVersion::getInstance().isSrcSplit()) {
-            sSrcSplitEnabled = true;
-            return new MDPCompSrcSplit(dpy);
-        }
+    if(qdutils::MDPVersion::getInstance().isSrcSplit()) {
+        sSrcSplitEnabled = true;
+        return new MDPCompSrcSplit(dpy);
+    } else if(isDisplaySplit(ctx, dpy)) {
         return new MDPCompSplit(dpy);
     }
     return new MDPCompNonSplit(dpy);
@@ -60,7 +59,7 @@
 
 MDPComp::MDPComp(int dpy):mDpy(dpy){};
 
-void MDPComp::dump(android::String8& buf)
+void MDPComp::dump(android::String8& buf, hwc_context_t *ctx)
 {
     if(mCurrentFrame.layerCount > MAX_NUM_APP_LAYERS)
         return;
@@ -74,6 +73,21 @@
     dumpsys_log(buf,"needsFBRedraw:%3s  pipesUsed:%2d  MaxPipesPerMixer: %d \n",
                 (mCurrentFrame.needsRedraw? "YES" : "NO"),
                 mCurrentFrame.mdpCount, sMaxPipesPerMixer);
+    if(isDisplaySplit(ctx, mDpy)) {
+        dumpsys_log(buf, "Programmed ROI's: Left: [%d, %d, %d, %d] "
+                "Right: [%d, %d, %d, %d] \n",
+                ctx->listStats[mDpy].lRoi.left, ctx->listStats[mDpy].lRoi.top,
+                ctx->listStats[mDpy].lRoi.right,
+                ctx->listStats[mDpy].lRoi.bottom,
+                ctx->listStats[mDpy].rRoi.left,ctx->listStats[mDpy].rRoi.top,
+                ctx->listStats[mDpy].rRoi.right,
+                ctx->listStats[mDpy].rRoi.bottom);
+    } else {
+        dumpsys_log(buf, "Programmed ROI: [%d, %d, %d, %d] \n",
+                ctx->listStats[mDpy].lRoi.left,ctx->listStats[mDpy].lRoi.top,
+                ctx->listStats[mDpy].lRoi.right,
+                ctx->listStats[mDpy].lRoi.bottom);
+    }
     dumpsys_log(buf," ---------------------------------------------  \n");
     dumpsys_log(buf," listIdx | cached? | mdpIndex | comptype  |  Z  \n");
     dumpsys_log(buf," ---------------------------------------------  \n");
@@ -113,19 +127,6 @@
         sEnableMixedMode = false;
     }
 
-    if(property_get("debug.mdpcomp.logs", property, NULL) > 0) {
-        if(atoi(property) != 0)
-            sDebugLogs = true;
-    }
-
-    if(property_get("persist.hwc.partialupdate", property, NULL) > 0) {
-        if((atoi(property) != 0) && ctx->mMDP.panel == MIPI_CMD_PANEL &&
-           qdutils::MDPVersion::getInstance().is8x74v2())
-            sEnablePartialFrameUpdate = true;
-    }
-    ALOGE_IF(isDebug(), "%s: Partial Update applicable?: %d",__FUNCTION__,
-                                                    sEnablePartialFrameUpdate);
-
     sMaxPipesPerMixer = MAX_PIPES_PER_MIXER;
     if(property_get("debug.mdpcomp.maxpermixer", property, "-1") > 0) {
         int val = atoi(property);
@@ -149,15 +150,25 @@
             ALOGE("%s: failed to instantiate idleInvalidator object",
                   __FUNCTION__);
         } else {
-            idleInvalidator->init(timeout_handler, ctx, idle_timeout);
+            idleInvalidator->init(timeout_handler, ctx,
+                                  (unsigned int)idle_timeout);
         }
     }
 
-    if((property_get("debug.mdpcomp.4k2kSplit", property, "0") > 0) &&
-            (!strncmp(property, "1", PROPERTY_VALUE_MAX ) ||
-             (!strncasecmp(property,"true", PROPERTY_VALUE_MAX )))) {
+    if(!qdutils::MDPVersion::getInstance().isSrcSplit() &&
+            property_get("persist.mdpcomp.4k2kSplit", property, "0") > 0 &&
+            (!strncmp(property, "1", PROPERTY_VALUE_MAX) ||
+            !strncasecmp(property,"true", PROPERTY_VALUE_MAX))) {
         sEnable4k2kYUVSplit = true;
     }
+
+    if ((property_get("persist.hwc.ptor.enable", property, NULL) > 0) &&
+            ((!strncasecmp(property, "true", PROPERTY_VALUE_MAX )) ||
+             (!strncmp(property, "1", PROPERTY_VALUE_MAX )))) {
+        ctx->mCopyBit[HWC_DISPLAY_PRIMARY] = new CopyBit(ctx,
+                                                    HWC_DISPLAY_PRIMARY);
+    }
+
     return true;
 }
 
@@ -168,6 +179,11 @@
     ctx->mLayerRotMap[mDpy]->clear();
 }
 
+void MDPComp::reset() {
+    sHandleTimeout = false;
+    mModeOn = false;
+}
+
 void MDPComp::timeout_handler(void *udata) {
     struct hwc_context_t* ctx = (struct hwc_context_t*)(udata);
 
@@ -269,7 +285,7 @@
 }
 
 void MDPComp::LayerCache::cacheAll(hwc_display_contents_1_t* list) {
-    const int numAppLayers = list->numHwLayers - 1;
+    const int numAppLayers = (int)list->numHwLayers - 1;
     for(int i = 0; i < numAppLayers; i++) {
         hnd[i] = list->hwLayers[i].handle;
     }
@@ -300,7 +316,7 @@
 
 bool MDPComp::isSupportedForMDPComp(hwc_context_t *ctx, hwc_layer_1_t* layer) {
     private_handle_t *hnd = (private_handle_t *)layer->handle;
-    if((not isYuvBuffer(hnd) and has90Transform(layer)) or
+    if((has90Transform(layer) and (not isRotationDoable(ctx, hnd))) ||
         (not isValidDimension(ctx,layer))
         //More conditions here, SKIP, sRGB+Blend etc
         ) {
@@ -327,8 +343,9 @@
 
     hwc_rect_t crop = integerizeSourceCrop(layer->sourceCropf);
     hwc_rect_t dst = layer->displayFrame;
-    int crop_w = crop.right - crop.left;
-    int crop_h = crop.bottom - crop.top;
+    bool rotated90 = (bool)(layer->transform & HAL_TRANSFORM_ROT_90);
+    int crop_w = rotated90 ? crop.bottom - crop.top : crop.right - crop.left;
+    int crop_h = rotated90 ? crop.right - crop.left : crop.bottom - crop.top;
     int dst_w = dst.right - dst.left;
     int dst_h = dst.bottom - dst.top;
     float w_scale = ((float)crop_w / (float)dst_w);
@@ -393,44 +410,15 @@
     return true;
 }
 
-ovutils::eDest MDPComp::getMdpPipe(hwc_context_t *ctx, ePipeType type,
-        int mixer) {
-    overlay::Overlay& ov = *ctx->mOverlay;
-    ovutils::eDest mdp_pipe = ovutils::OV_INVALID;
-
-    switch(type) {
-    case MDPCOMP_OV_DMA:
-        mdp_pipe = ov.nextPipe(ovutils::OV_MDP_PIPE_DMA, mDpy, mixer);
-        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, mDpy, mixer);
-        if(mdp_pipe != ovutils::OV_INVALID) {
-            return mdp_pipe;
-        }
-
-        if(type == MDPCOMP_OV_RGB) {
-            //Requested only for RGB pipe
-            break;
-        }
-    case  MDPCOMP_OV_VG:
-        return ov.nextPipe(ovutils::OV_MDP_PIPE_VG, mDpy, mixer);
-    default:
-        ALOGE("%s: Invalid pipe type",__FUNCTION__);
-        return ovutils::OV_INVALID;
-    };
-    return ovutils::OV_INVALID;
-}
-
 bool MDPComp::isFrameDoable(hwc_context_t *ctx) {
     bool ret = true;
 
     if(!isEnabled()) {
         ALOGD_IF(isDebug(),"%s: MDP Comp. not enabled.", __FUNCTION__);
         ret = false;
-    } else if(qdutils::MDPVersion::getInstance().is8x26() &&
+    } else if((qdutils::MDPVersion::getInstance().is8x26() ||
+               qdutils::MDPVersion::getInstance().is8x16() ||
+               qdutils::MDPVersion::getInstance().is8x39()) &&
             ctx->mVideoTransFlag &&
             isSecondaryConnected(ctx)) {
         //1 Padding round to shift pipes across mixers
@@ -449,23 +437,21 @@
     return ret;
 }
 
-/*
- * 1) Identify layers that are not visible in the updating ROI and drop them
- * from composition.
- * 2) If we have a scaling layers which needs cropping against generated ROI.
- * Reset ROI to full resolution.
- */
-bool MDPComp::validateAndApplyROI(hwc_context_t *ctx,
-                               hwc_display_contents_1_t* list, hwc_rect_t roi) {
+void MDPCompNonSplit::trimAgainstROI(hwc_context_t *ctx, hwc_rect_t& fbRect) {
+    hwc_rect_t roi = ctx->listStats[mDpy].lRoi;
+    fbRect = getIntersection(fbRect, roi);
+}
+
+/* 1) Identify layers that are not visible or lying outside the updating ROI and
+ *    drop them from composition.
+ * 2) If we have a scaling layer which needs cropping against generated
+ *    ROI, reset ROI to full resolution. */
+bool MDPCompNonSplit::validateAndApplyROI(hwc_context_t *ctx,
+        hwc_display_contents_1_t* list) {
     int numAppLayers = ctx->listStats[mDpy].numAppLayers;
-
-    if(!isValidRect(roi))
-        return false;
-
-    hwc_rect_t visibleRect = roi;
+    hwc_rect_t visibleRect = ctx->listStats[mDpy].lRoi;
 
     for(int i = numAppLayers - 1; i >= 0; i--){
-
         if(!isValidRect(visibleRect)) {
             mCurrentFrame.drop[i] = true;
             mCurrentFrame.dropCount++;
@@ -473,24 +459,16 @@
         }
 
         const hwc_layer_1_t* layer =  &list->hwLayers[i];
-
         hwc_rect_t dstRect = layer->displayFrame;
-        hwc_rect_t srcRect = integerizeSourceCrop(layer->sourceCropf);
-
         hwc_rect_t res  = getIntersection(visibleRect, dstRect);
 
-        int res_w = res.right - res.left;
-        int res_h = res.bottom - res.top;
-        int dst_w = dstRect.right - dstRect.left;
-        int dst_h = dstRect.bottom - dstRect.top;
-
         if(!isValidRect(res)) {
             mCurrentFrame.drop[i] = true;
             mCurrentFrame.dropCount++;
-        }else {
+        } 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(!isSameRect(res, dstRect) && needsScaling (layer)) {
                 ALOGI("%s: Resetting ROI due to scaling", __FUNCTION__);
                 memset(&mCurrentFrame.drop, 0, sizeof(mCurrentFrame.drop));
                 mCurrentFrame.dropCount = 0;
@@ -505,51 +483,190 @@
     return true;
 }
 
-void MDPComp::generateROI(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
+/* Calculate ROI for the frame by accounting all the layer's dispalyFrame which
+ * are updating. If DirtyRegion is applicable, calculate it by accounting all
+ * the changing layer's dirtyRegion. */
+void MDPCompNonSplit::generateROI(hwc_context_t *ctx,
+        hwc_display_contents_1_t* list) {
     int numAppLayers = ctx->listStats[mDpy].numAppLayers;
-
-    if(!sEnablePartialFrameUpdate) {
-        return;
-    }
-
-    if(mDpy || isDisplaySplit(ctx, mDpy)){
-        ALOGE_IF(isDebug(), "%s: ROI not supported for"
-                 "the (1) external / virtual display's (2) dual DSI displays",
-                 __FUNCTION__);
-        return;
-    }
-
-    if(isSkipPresent(ctx, mDpy))
-        return;
-
-    if(list->flags & HWC_GEOMETRY_CHANGED)
+    if(!canPartialUpdate(ctx, list))
         return;
 
     struct hwc_rect roi = (struct hwc_rect){0, 0, 0, 0};
-    for(int index = 0; index < numAppLayers; index++ ) {
-        if ((mCachedFrame.hnd[index] != list->hwLayers[index].handle) ||
-            isYuvBuffer((private_handle_t *)list->hwLayers[index].handle)) {
-            hwc_rect_t dstRect = list->hwLayers[index].displayFrame;
-            hwc_rect_t srcRect = integerizeSourceCrop(
-                                        list->hwLayers[index].sourceCropf);
+    hwc_rect fullFrame = (struct hwc_rect) {0, 0,(int)ctx->dpyAttr[mDpy].xres,
+        (int)ctx->dpyAttr[mDpy].yres};
 
-            /* Intersect against display boundaries */
-            roi = getUnion(roi, dstRect);
+    for(int index = 0; index < numAppLayers; index++ ) {
+        hwc_layer_1_t* layer = &list->hwLayers[index];
+        if ((mCachedFrame.hnd[index] != layer->handle) ||
+                isYuvBuffer((private_handle_t *)layer->handle)) {
+            hwc_rect_t dst = layer->displayFrame;
+            hwc_rect_t updatingRect = dst;
+
+#ifdef QCOM_BSP
+            if(!needsScaling(layer) && !layer->transform)
+            {
+                hwc_rect_t src = integerizeSourceCrop(layer->sourceCropf);
+                int x_off = dst.left - src.left;
+                int y_off = dst.top - src.top;
+                updatingRect = moveRect(layer->dirtyRect, x_off, y_off);
+            }
+#endif
+
+            roi = getUnion(roi, updatingRect);
         }
     }
 
-    if(!validateAndApplyROI(ctx, list, roi)){
-        roi = (struct hwc_rect) {0, 0,
-                    (int)ctx->dpyAttr[mDpy].xres, (int)ctx->dpyAttr[mDpy].yres};
-    }
+    /* No layer is updating. Still SF wants a refresh.*/
+    if(!isValidRect(roi))
+        return;
 
-    ctx->listStats[mDpy].roi.x = roi.left;
-    ctx->listStats[mDpy].roi.y = roi.top;
-    ctx->listStats[mDpy].roi.w = roi.right - roi.left;
-    ctx->listStats[mDpy].roi.h = roi.bottom - roi.top;
+    // Align ROI coordinates to panel restrictions
+    roi = getSanitizeROI(roi, fullFrame);
+
+    ctx->listStats[mDpy].lRoi = roi;
+    if(!validateAndApplyROI(ctx, list))
+        resetROI(ctx, mDpy);
 
     ALOGD_IF(isDebug(),"%s: generated ROI: [%d, %d, %d, %d]", __FUNCTION__,
-                               roi.left, roi.top, roi.right, roi.bottom);
+            ctx->listStats[mDpy].lRoi.left, ctx->listStats[mDpy].lRoi.top,
+            ctx->listStats[mDpy].lRoi.right, ctx->listStats[mDpy].lRoi.bottom);
+}
+
+void MDPCompSplit::trimAgainstROI(hwc_context_t *ctx, hwc_rect_t& fbRect) {
+    hwc_rect l_roi = ctx->listStats[mDpy].lRoi;
+    hwc_rect r_roi = ctx->listStats[mDpy].rRoi;
+
+    hwc_rect_t l_fbRect = getIntersection(fbRect, l_roi);
+    hwc_rect_t r_fbRect = getIntersection(fbRect, r_roi);
+    fbRect = getUnion(l_fbRect, r_fbRect);
+}
+/* 1) Identify layers that are not visible or lying outside BOTH the updating
+ *    ROI's and drop them from composition. If a layer is spanning across both
+ *    the halves of the screen but needed by only ROI, the non-contributing
+ *    half will not be programmed for MDP.
+ * 2) If we have a scaling layer which needs cropping against generated
+ *    ROI, reset ROI to full resolution. */
+bool MDPCompSplit::validateAndApplyROI(hwc_context_t *ctx,
+        hwc_display_contents_1_t* list) {
+
+    int numAppLayers = ctx->listStats[mDpy].numAppLayers;
+
+    hwc_rect_t visibleRectL = ctx->listStats[mDpy].lRoi;
+    hwc_rect_t visibleRectR = ctx->listStats[mDpy].rRoi;
+
+    for(int i = numAppLayers - 1; i >= 0; i--){
+        if(!isValidRect(visibleRectL) && !isValidRect(visibleRectR))
+        {
+            mCurrentFrame.drop[i] = true;
+            mCurrentFrame.dropCount++;
+            continue;
+        }
+
+        const hwc_layer_1_t* layer =  &list->hwLayers[i];
+        hwc_rect_t dstRect = layer->displayFrame;
+
+        hwc_rect_t l_res  = getIntersection(visibleRectL, dstRect);
+        hwc_rect_t r_res  = getIntersection(visibleRectR, dstRect);
+        hwc_rect_t res = getUnion(l_res, r_res);
+
+        if(!isValidRect(l_res) && !isValidRect(r_res)) {
+            mCurrentFrame.drop[i] = true;
+            mCurrentFrame.dropCount++;
+        } else {
+            /* Reset frame ROI when any layer which needs scaling also needs ROI
+             * cropping */
+            if(!isSameRect(res, dstRect) && needsScaling (layer)) {
+                memset(&mCurrentFrame.drop, 0, sizeof(mCurrentFrame.drop));
+                mCurrentFrame.dropCount = 0;
+                return false;
+            }
+
+            if (layer->blending == HWC_BLENDING_NONE) {
+                visibleRectL = deductRect(visibleRectL, l_res);
+                visibleRectR = deductRect(visibleRectR, r_res);
+            }
+        }
+    }
+    return true;
+}
+/* Calculate ROI for the frame by accounting all the layer's dispalyFrame which
+ * are updating. If DirtyRegion is applicable, calculate it by accounting all
+ * the changing layer's dirtyRegion. */
+void MDPCompSplit::generateROI(hwc_context_t *ctx,
+        hwc_display_contents_1_t* list) {
+    if(!canPartialUpdate(ctx, list))
+        return;
+
+    int numAppLayers = ctx->listStats[mDpy].numAppLayers;
+    int lSplit = getLeftSplit(ctx, mDpy);
+
+    int hw_h = (int)ctx->dpyAttr[mDpy].yres;
+    int hw_w = (int)ctx->dpyAttr[mDpy].xres;
+
+    struct hwc_rect l_frame = (struct hwc_rect){0, 0, lSplit, hw_h};
+    struct hwc_rect r_frame = (struct hwc_rect){lSplit, 0, hw_w, hw_h};
+
+    struct hwc_rect l_roi = (struct hwc_rect){0, 0, 0, 0};
+    struct hwc_rect r_roi = (struct hwc_rect){0, 0, 0, 0};
+
+    for(int index = 0; index < numAppLayers; index++ ) {
+        hwc_layer_1_t* layer = &list->hwLayers[index];
+        private_handle_t *hnd = (private_handle_t *)layer->handle;
+        if ((mCachedFrame.hnd[index] != layer->handle) ||
+                isYuvBuffer(hnd)) {
+            hwc_rect_t dst = layer->displayFrame;
+            hwc_rect_t updatingRect = dst;
+
+#ifdef QCOM_BSP
+            if(!needsScaling(layer) && !layer->transform)
+            {
+                hwc_rect_t src = integerizeSourceCrop(layer->sourceCropf);
+                int x_off = dst.left - src.left;
+                int y_off = dst.top - src.top;
+                updatingRect = moveRect(layer->dirtyRect, x_off, y_off);
+            }
+#endif
+
+            hwc_rect_t l_dst  = getIntersection(l_frame, updatingRect);
+            if(isValidRect(l_dst))
+                l_roi = getUnion(l_roi, l_dst);
+
+            hwc_rect_t r_dst  = getIntersection(r_frame, updatingRect);
+            if(isValidRect(r_dst))
+                r_roi = getUnion(r_roi, r_dst);
+        }
+    }
+
+    /* For panels that cannot accept commands in both the interfaces, we cannot
+     * send two ROI's (for each half). We merge them into single ROI and split
+     * them across lSplit for MDP mixer use. The ROI's will be merged again
+     * finally before udpating the panel in the driver. */
+    if(qdutils::MDPVersion::getInstance().needsROIMerge()) {
+        hwc_rect_t temp_roi = getUnion(l_roi, r_roi);
+        l_roi = getIntersection(temp_roi, l_frame);
+        r_roi = getIntersection(temp_roi, r_frame);
+    }
+
+    /* No layer is updating. Still SF wants a refresh. */
+    if(!isValidRect(l_roi) && !isValidRect(r_roi))
+        return;
+
+    l_roi = getSanitizeROI(l_roi, l_frame);
+    r_roi = getSanitizeROI(r_roi, r_frame);
+
+    ctx->listStats[mDpy].lRoi = l_roi;
+    ctx->listStats[mDpy].rRoi = r_roi;
+
+    if(!validateAndApplyROI(ctx, list))
+        resetROI(ctx, mDpy);
+
+    ALOGD_IF(isDebug(),"%s: generated L_ROI: [%d, %d, %d, %d]"
+            "R_ROI: [%d, %d, %d, %d]", __FUNCTION__,
+            ctx->listStats[mDpy].lRoi.left, ctx->listStats[mDpy].lRoi.top,
+            ctx->listStats[mDpy].lRoi.right, ctx->listStats[mDpy].lRoi.bottom,
+            ctx->listStats[mDpy].rRoi.left, ctx->listStats[mDpy].rRoi.top,
+            ctx->listStats[mDpy].rRoi.right, ctx->listStats[mDpy].rRoi.bottom);
 }
 
 /* Checks for conditions where all the layers marked for MDP comp cannot be
@@ -594,7 +711,7 @@
         hwc_layer_1_t* layer = &list->hwLayers[i];
         private_handle_t *hnd = (private_handle_t *)layer->handle;
 
-        if(isYuvBuffer(hnd) && has90Transform(layer)) {
+        if(has90Transform(layer) && isRotationDoable(ctx, hnd)) {
             if(!canUseRotator(ctx, mDpy)) {
                 ALOGD_IF(isDebug(), "%s: Can't use rotator for dpy %d",
                         __FUNCTION__, mDpy);
@@ -619,6 +736,8 @@
     bool ret = false;
     if(fullMDPComp(ctx, list)) {
         ret = true;
+    } else if(fullMDPCompWithPTOR(ctx, list)) {
+        ret = true;
     } else if(partialMDPComp(ctx, list)) {
         ret = true;
     }
@@ -627,6 +746,10 @@
 }
 
 bool MDPComp::fullMDPComp(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
+
+    if(sSimulationFlags & MDPCOMP_AVOID_FULL_MDP)
+        return false;
+
     //Will benefit presentation / secondary-only layer.
     if((mDpy > HWC_DISPLAY_PRIMARY) &&
             (list->numHwLayers - 1) > MAX_SEC_LAYERS) {
@@ -637,19 +760,11 @@
     const int numAppLayers = ctx->listStats[mDpy].numAppLayers;
     for(int i = 0; i < numAppLayers; i++) {
         hwc_layer_1_t* layer = &list->hwLayers[i];
-        if(not isSupportedForMDPComp(ctx, layer)) {
+        if(not mCurrentFrame.drop[i] and
+           not isSupportedForMDPComp(ctx, layer)) {
             ALOGD_IF(isDebug(), "%s: Unsupported layer in list",__FUNCTION__);
             return false;
         }
-
-        //For 8x26, if there is only one layer which needs scale for secondary
-        //while no scale for primary display, DMA pipe is occupied by primary.
-        //If need to fall back to GLES composition, virtual display lacks DMA
-        //pipe and error is reported.
-        if(qdutils::MDPVersion::getInstance().is8x26() &&
-                                mDpy >= HWC_DISPLAY_EXTERNAL &&
-                                qhwc::needsScaling(layer))
-            return false;
     }
 
     mCurrentFrame.fbCount = 0;
@@ -667,10 +782,182 @@
         reset(ctx);
         return false;
     }
-
+    ALOGD_IF(sSimulationFlags,"%s: FULL_MDP_COMP SUCCEEDED",
+             __FUNCTION__);
     return true;
 }
 
+/* Full MDP Composition with Peripheral Tiny Overlap Removal.
+ * MDP bandwidth limitations can be avoided, if the overlap region
+ * covered by the smallest layer at a higher z-order, gets composed
+ * by Copybit on a render buffer, which can be queued to MDP.
+ */
+bool MDPComp::fullMDPCompWithPTOR(hwc_context_t *ctx,
+    hwc_display_contents_1_t* list) {
+
+    const int numAppLayers = ctx->listStats[mDpy].numAppLayers;
+    const int stagesForMDP = min(sMaxPipesPerMixer,
+            ctx->mOverlay->availablePipes(mDpy, Overlay::MIXER_DEFAULT));
+
+    // Hard checks where we cannot use this mode
+    if (mDpy || !ctx->mCopyBit[mDpy] || isDisplaySplit(ctx, mDpy)) {
+        ALOGD_IF(isDebug(), "%s: Feature not supported!", __FUNCTION__);
+        return false;
+    }
+
+    // Frame level checks
+    if ((numAppLayers > stagesForMDP) || isSkipPresent(ctx, mDpy) ||
+        isYuvPresent(ctx, mDpy) || mCurrentFrame.dropCount ||
+        isSecurePresent(ctx, mDpy)) {
+        ALOGD_IF(isDebug(), "%s: Frame not supported!", __FUNCTION__);
+        return false;
+    }
+    // MDP comp checks
+    for(int i = 0; i < numAppLayers; i++) {
+        hwc_layer_1_t* layer = &list->hwLayers[i];
+        if(not isSupportedForMDPComp(ctx, layer)) {
+            ALOGD_IF(isDebug(), "%s: Unsupported layer in list",__FUNCTION__);
+            return false;
+        }
+    }
+
+    /* We cannot use this composition mode, if:
+     1. A below layer needs scaling.
+     2. Overlap is not peripheral to display.
+     3. Overlap or a below layer has 90 degree transform.
+     4. Overlap area > (1/3 * FrameBuffer) area, based on Perf inputs.
+     */
+
+    int minLayerIndex[MAX_PTOR_LAYERS] = { -1, -1};
+    hwc_rect_t overlapRect[MAX_PTOR_LAYERS];
+    memset(overlapRect, 0, sizeof(overlapRect));
+    int layerPixelCount, minPixelCount = 0;
+    int numPTORLayersFound = 0;
+    for (int i = numAppLayers-1; (i >= 0 &&
+                                  numPTORLayersFound < MAX_PTOR_LAYERS); i--) {
+        hwc_layer_1_t* layer = &list->hwLayers[i];
+        hwc_rect_t crop = integerizeSourceCrop(layer->sourceCropf);
+        hwc_rect_t dispFrame = layer->displayFrame;
+        layerPixelCount = (crop.right - crop.left) * (crop.bottom - crop.top);
+        // PTOR layer should be peripheral and cannot have transform
+        if (!isPeripheral(dispFrame, ctx->mViewFrame[mDpy]) ||
+                                has90Transform(layer)) {
+            continue;
+        }
+        if((3 * (layerPixelCount + minPixelCount)) >
+                ((int)ctx->dpyAttr[mDpy].xres * (int)ctx->dpyAttr[mDpy].yres)) {
+            // Overlap area > (1/3 * FrameBuffer) area, based on Perf inputs.
+            continue;
+        }
+        // Found the PTOR layer
+        bool found = true;
+        for (int j = i-1; j >= 0; j--) {
+            // Check if the layers below this layer qualifies for PTOR comp
+            hwc_layer_1_t* layer = &list->hwLayers[j];
+            hwc_rect_t disFrame = layer->displayFrame;
+            //layer below PTOR is intersecting and has 90 degree transform or
+            // needs scaling cannot be supported.
+            if ((isValidRect(getIntersection(dispFrame, disFrame)))
+                            && (has90Transform(layer) || needsScaling(layer))) {
+                found = false;
+                break;
+            }
+        }
+        // Store the minLayer Index
+        if(found) {
+            minLayerIndex[numPTORLayersFound] = i;
+            overlapRect[numPTORLayersFound] = list->hwLayers[i].displayFrame;
+            minPixelCount += layerPixelCount;
+            numPTORLayersFound++;
+        }
+    }
+
+    if(isValidRect(getIntersection(overlapRect[0], overlapRect[1]))) {
+        ALOGD_IF(isDebug(), "%s: Ignore Rect2 its intersects with Rect1",
+                 __FUNCTION__);
+        // reset second minLayerIndex[1];
+        minLayerIndex[1] = -1;
+        numPTORLayersFound--;
+    }
+
+    // No overlap layers
+    if (!numPTORLayersFound)
+        return false;
+
+    ctx->mPtorInfo.count = numPTORLayersFound;
+    for(int i = 0; i < MAX_PTOR_LAYERS; i++) {
+        ctx->mPtorInfo.layerIndex[i] = minLayerIndex[i];
+    }
+
+    if (!ctx->mCopyBit[mDpy]->prepareOverlap(ctx, list)) {
+        // reset PTOR
+        ctx->mPtorInfo.count = 0;
+        return false;
+    }
+    // Store the displayFrame and the sourceCrops of the layers
+    hwc_rect_t displayFrame[numAppLayers];
+    hwc_rect_t sourceCrop[numAppLayers];
+    for(int i = 0; i < numAppLayers; i++) {
+        hwc_layer_1_t* layer = &list->hwLayers[i];
+        displayFrame[i] = layer->displayFrame;
+        sourceCrop[i] = integerizeSourceCrop(layer->sourceCropf);
+    }
+
+    for(int j = 0; j < numPTORLayersFound; j++) {
+        int index =  ctx->mPtorInfo.layerIndex[j];
+        // Remove overlap from crop & displayFrame of below layers
+        for (int i = 0; i < index && index !=-1; i++) {
+            hwc_layer_1_t* layer = &list->hwLayers[i];
+            if(!isValidRect(getIntersection(layer->displayFrame,
+                                            overlapRect[j])))  {
+                continue;
+            }
+            // Update layer attributes
+            hwc_rect_t srcCrop = integerizeSourceCrop(layer->sourceCropf);
+            hwc_rect_t destRect = deductRect(layer->displayFrame,
+                                             overlapRect[j]);
+            qhwc::calculate_crop_rects(srcCrop, layer->displayFrame, destRect,
+                                       layer->transform);
+            layer->sourceCropf.left = (float)srcCrop.left;
+            layer->sourceCropf.top = (float)srcCrop.top;
+            layer->sourceCropf.right = (float)srcCrop.right;
+            layer->sourceCropf.bottom = (float)srcCrop.bottom;
+        }
+    }
+
+    mCurrentFrame.mdpCount = numAppLayers;
+    mCurrentFrame.fbCount = 0;
+    mCurrentFrame.fbZ = -1;
+
+    for (int j = 0; j < numAppLayers; j++)
+        mCurrentFrame.isFBComposed[j] = false;
+
+    bool result = postHeuristicsHandling(ctx, list);
+
+    // Restore layer attributes
+    for(int i = 0; i < numAppLayers; i++) {
+        hwc_layer_1_t* layer = &list->hwLayers[i];
+        layer->displayFrame = displayFrame[i];
+        layer->sourceCropf.left = (float)sourceCrop[i].left;
+        layer->sourceCropf.top = (float)sourceCrop[i].top;
+        layer->sourceCropf.right = (float)sourceCrop[i].right;
+        layer->sourceCropf.bottom = (float)sourceCrop[i].bottom;
+    }
+
+    if (!result) {
+        // reset PTOR
+        ctx->mPtorInfo.count = 0;
+        reset(ctx);
+    } else {
+        ALOGD_IF(isDebug(), "%s: PTOR Indexes: %d and %d", __FUNCTION__,
+                 ctx->mPtorInfo.layerIndex[0],  ctx->mPtorInfo.layerIndex[1]);
+    }
+
+    ALOGD_IF(isDebug(), "%s: Postheuristics %s!", __FUNCTION__,
+             (result ? "successful" : "failed"));
+    return result;
+}
+
 bool MDPComp::partialMDPComp(hwc_context_t *ctx, hwc_display_contents_1_t* list)
 {
     if(!sEnableMixedMode) {
@@ -692,6 +979,9 @@
 
 bool MDPComp::cacheBasedComp(hwc_context_t *ctx,
         hwc_display_contents_1_t* list) {
+    if(sSimulationFlags & MDPCOMP_AVOID_CACHE_MDP)
+        return false;
+
     int numAppLayers = ctx->listStats[mDpy].numAppLayers;
     mCurrentFrame.reset(numAppLayers);
     updateLayerCache(ctx, list);
@@ -736,12 +1026,17 @@
         reset(ctx);
         return false;
     }
+    ALOGD_IF(sSimulationFlags,"%s: CACHE_MDP_COMP SUCCEEDED",
+             __FUNCTION__);
 
     return true;
 }
 
 bool MDPComp::loadBasedComp(hwc_context_t *ctx,
         hwc_display_contents_1_t* list) {
+    if(sSimulationFlags & MDPCOMP_AVOID_LOAD_MDP)
+        return false;
+
     if(not isLoadBasedCompDoable(ctx)) {
         return false;
     }
@@ -813,7 +1108,9 @@
 
         if(postHeuristicsHandling(ctx, list)) {
             ALOGD_IF(isDebug(), "%s: Postheuristics handling succeeded",
-                    __FUNCTION__);
+                     __FUNCTION__);
+            ALOGD_IF(sSimulationFlags,"%s: LOAD_MDP_COMP SUCCEEDED",
+                     __FUNCTION__);
             return true;
         }
 
@@ -833,6 +1130,18 @@
     return true;
 }
 
+bool MDPComp::canPartialUpdate(hwc_context_t *ctx,
+        hwc_display_contents_1_t* list){
+    if(!qdutils::MDPVersion::getInstance().isPartialUpdateEnabled() ||
+            isSkipPresent(ctx, mDpy) || (list->flags & HWC_GEOMETRY_CHANGED) ||
+            mDpy ) {
+        return false;
+    }
+    if(ctx->listStats[mDpy].secureUI)
+        return false;
+    return true;
+}
+
 bool MDPComp::tryVideoOnly(hwc_context_t *ctx,
         hwc_display_contents_1_t* list) {
     const bool secureOnly = true;
@@ -842,9 +1151,12 @@
 
 bool MDPComp::videoOnlyComp(hwc_context_t *ctx,
         hwc_display_contents_1_t* list, bool secureOnly) {
+    if(sSimulationFlags & MDPCOMP_AVOID_VIDEO_ONLY)
+        return false;
     int numAppLayers = ctx->listStats[mDpy].numAppLayers;
 
     mCurrentFrame.reset(numAppLayers);
+    mCurrentFrame.fbCount -= mCurrentFrame.dropCount;
     updateYUV(ctx, list, secureOnly);
     int mdpCount = mCurrentFrame.mdpCount;
 
@@ -873,6 +1185,8 @@
         return false;
     }
 
+    ALOGD_IF(sSimulationFlags,"%s: VIDEO_ONLY_COMP SUCCEEDED",
+             __FUNCTION__);
     return true;
 }
 
@@ -883,7 +1197,7 @@
         return false;
     }
 
-    if(layer->transform & HWC_TRANSFORM_ROT_90 && !canUseRotator(ctx,mDpy)) {
+    if(has90Transform(layer) && !canUseRotator(ctx, mDpy)) {
         ALOGD_IF(isDebug(), "%s: no free DMA pipe",__FUNCTION__);
         return false;
     }
@@ -1129,7 +1443,6 @@
 hwc_rect_t MDPComp::getUpdatingFBRect(hwc_context_t *ctx,
         hwc_display_contents_1_t* list){
     hwc_rect_t fbRect = (struct hwc_rect){0, 0, 0, 0};
-    hwc_layer_1_t *fbLayer = &list->hwLayers[mCurrentFrame.layerCount];
 
     /* Update only the region of FB needed for composition */
     for(int i = 0; i < mCurrentFrame.layerCount; i++ ) {
@@ -1139,6 +1452,7 @@
             fbRect = getUnion(fbRect, dst);
         }
     }
+    trimAgainstROI(ctx, fbRect);
     return fbRect;
 }
 
@@ -1220,13 +1534,31 @@
     return true;
 }
 
-bool MDPComp::resourceCheck(hwc_context_t *ctx,
-        hwc_display_contents_1_t *list) {
+bool MDPComp::resourceCheck(hwc_context_t* ctx,
+        hwc_display_contents_1_t* list) {
     const bool fbUsed = mCurrentFrame.fbCount;
     if(mCurrentFrame.mdpCount > sMaxPipesPerMixer - fbUsed) {
         ALOGD_IF(isDebug(), "%s: Exceeds MAX_PIPES_PER_MIXER",__FUNCTION__);
         return false;
     }
+    // Init rotCount to number of rotate sessions used by other displays
+    int rotCount = ctx->mRotMgr->getNumActiveSessions();
+    // Count the number of rotator sessions required for current display
+    for (int index = 0; index < mCurrentFrame.layerCount; index++) {
+        if(!mCurrentFrame.isFBComposed[index]) {
+            hwc_layer_1_t* layer = &list->hwLayers[index];
+            private_handle_t *hnd = (private_handle_t *)layer->handle;
+            if(has90Transform(layer) && isRotationDoable(ctx, hnd)) {
+                rotCount++;
+            }
+        }
+    }
+    // if number of layers to rotate exceeds max rotator sessions, bail out.
+    if(rotCount > RotMgr::MAX_ROT_SESS) {
+        ALOGD_IF(isDebug(), "%s: Exceeds max rotator sessions  %d",
+                                    __FUNCTION__, mDpy);
+        return false;
+    }
     return true;
 }
 
@@ -1274,8 +1606,27 @@
 
 int MDPComp::prepare(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
     int ret = 0;
+    char property[PROPERTY_VALUE_MAX];
+
+    if(!ctx || !list) {
+        ALOGE("%s: Invalid context or list",__FUNCTION__);
+        mCachedFrame.reset();
+        return -1;
+    }
+
     const int numLayers = ctx->listStats[mDpy].numAppLayers;
-    MDPVersion& mdpVersion = qdutils::MDPVersion::getInstance();
+
+    if(property_get("debug.hwc.simulate", property, NULL) > 0) {
+        int currentFlags = atoi(property);
+        if(currentFlags != sSimulationFlags) {
+            sSimulationFlags = currentFlags;
+            ALOGE("%s: Simulation Flag read: 0x%x (%d)", __FUNCTION__,
+                    sSimulationFlags, sSimulationFlags);
+        }
+    }
+    // reset PTOR
+    if(!mDpy)
+        memset(&(ctx->mPtorInfo), 0, sizeof(ctx->mPtorInfo));
 
     //Do not cache the information for next draw cycle.
     if(numLayers > MAX_NUM_APP_LAYERS or (!numLayers)) {
@@ -1310,9 +1661,11 @@
     if(isFrameDoable(ctx)) {
         generateROI(ctx, list);
 
-        if(tryFullFrame(ctx, list) || tryVideoOnly(ctx, list)) {
+        mModeOn = tryFullFrame(ctx, list) || tryVideoOnly(ctx, list);
+        if(mModeOn) {
             setMDPCompLayerFlags(ctx, list);
         } else {
+            resetROI(ctx, mDpy);
             reset(ctx);
             memset(&mCurrentFrame.drop, 0, sizeof(mCurrentFrame.drop));
             mCurrentFrame.dropCount = 0;
@@ -1328,7 +1681,7 @@
         ALOGD("GEOMETRY change: %d",
                 (list->flags & HWC_GEOMETRY_CHANGED));
         android::String8 sDump("");
-        dump(sDump);
+        dump(sDump, ctx);
         ALOGD("%s",sDump.string());
     }
 
@@ -1345,18 +1698,23 @@
     info.pipeInfo = new MdpYUVPipeInfo;
     info.rot = NULL;
     MdpYUVPipeInfo& pipe_info = *(MdpYUVPipeInfo*)info.pipeInfo;
-    ePipeType type =  MDPCOMP_OV_VG;
 
     pipe_info.lIndex = ovutils::OV_INVALID;
     pipe_info.rIndex = ovutils::OV_INVALID;
 
-    pipe_info.lIndex = getMdpPipe(ctx, type, Overlay::MIXER_DEFAULT);
+    Overlay::PipeSpecs pipeSpecs;
+    pipeSpecs.formatClass = Overlay::FORMAT_YUV;
+    pipeSpecs.needsScaling = true;
+    pipeSpecs.dpy = mDpy;
+    pipeSpecs.fb = false;
+
+    pipe_info.lIndex = ctx->mOverlay->getPipe(pipeSpecs);
     if(pipe_info.lIndex == ovutils::OV_INVALID){
         bRet = false;
         ALOGD_IF(isDebug(),"%s: allocating first VG pipe failed",
                 __FUNCTION__);
     }
-    pipe_info.rIndex = getMdpPipe(ctx, type, Overlay::MIXER_DEFAULT);
+    pipe_info.rIndex = ctx->mOverlay->getPipe(pipeSpecs);
     if(pipe_info.rIndex == ovutils::OV_INVALID){
         bRet = false;
         ALOGD_IF(isDebug(),"%s: allocating second VG pipe failed",
@@ -1364,25 +1722,45 @@
     }
     return bRet;
 }
+
+int MDPComp::drawOverlap(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
+    int fd = -1;
+    if (ctx->mPtorInfo.isActive()) {
+        fd = ctx->mCopyBit[mDpy]->drawOverlap(ctx, list);
+        if (fd < 0) {
+            ALOGD_IF(isDebug(),"%s: failed", __FUNCTION__);
+        }
+    }
+    return fd;
+}
 //=============MDPCompNonSplit==================================================
 
 void MDPCompNonSplit::adjustForSourceSplit(hwc_context_t *ctx,
-        hwc_display_contents_1_t*) {
-    //As we split 4kx2k yuv layer and program to 2 VG pipes
-    //(if available) increase mdpcount accordingly
-    mCurrentFrame.mdpCount += ctx->listStats[mDpy].yuv4k2kCount;
-
+        hwc_display_contents_1_t* list) {
     //If 4k2k Yuv layer split is possible,  and if
     //fbz is above 4k2k layer, increment fb zorder by 1
     //as we split 4k2k layer and increment zorder for right half
     //of the layer
+    if(!ctx)
+        return;
     if(mCurrentFrame.fbZ >= 0) {
-        int n4k2kYuvCount = ctx->listStats[mDpy].yuv4k2kCount;
-        for(int index = 0; index < n4k2kYuvCount; index++){
-            int n4k2kYuvIndex =
-                    ctx->listStats[mDpy].yuv4k2kIndices[index];
-            if(mCurrentFrame.fbZ > n4k2kYuvIndex){
-                mCurrentFrame.fbZ += 1;
+        for (int index = 0, mdpNextZOrder = 0; index < mCurrentFrame.layerCount;
+                index++) {
+            if(!mCurrentFrame.isFBComposed[index]) {
+                if(mdpNextZOrder == mCurrentFrame.fbZ) {
+                    mdpNextZOrder++;
+                }
+                mdpNextZOrder++;
+                hwc_layer_1_t* layer = &list->hwLayers[index];
+                private_handle_t *hnd = (private_handle_t *)layer->handle;
+                if(is4kx2kYuvBuffer(hnd)) {
+                    if(mdpNextZOrder <= mCurrentFrame.fbZ)
+                        mCurrentFrame.fbZ += 1;
+                    mdpNextZOrder++;
+                    //As we split 4kx2k yuv layer and program to 2 VG pipes
+                    //(if available) increase mdpcount by 1.
+                    mCurrentFrame.mdpCount++;
+                }
             }
         }
     }
@@ -1426,28 +1804,21 @@
         info.pipeInfo = new MdpPipeInfoNonSplit;
         info.rot = NULL;
         MdpPipeInfoNonSplit& pipe_info = *(MdpPipeInfoNonSplit*)info.pipeInfo;
-        ePipeType type = MDPCOMP_OV_ANY;
 
-        if(isYuvBuffer(hnd)) {
-            type = MDPCOMP_OV_VG;
-        } else if(qdutils::MDPVersion::getInstance().is8x26() &&
-                (ctx->dpyAttr[HWC_DISPLAY_PRIMARY].xres > 1024)) {
-            if(qhwc::needsScaling(layer))
-                type = MDPCOMP_OV_RGB;
-        } else if(!qhwc::needsScaling(layer)
-            && Overlay::getDMAMode() != Overlay::DMA_BLOCK_MODE
-            && ctx->mMDP.version >= qdutils::MDSS_V5) {
-            type = MDPCOMP_OV_DMA;
-        } else if(qhwc::needsScaling(layer) &&
-                !(ctx->listStats[mDpy].yuvCount) &&
-                ! qdutils::MDPVersion::getInstance().isRGBScalarSupported()){
-            type = MDPCOMP_OV_VG;
-        }
+        Overlay::PipeSpecs pipeSpecs;
+        pipeSpecs.formatClass = isYuvBuffer(hnd) ?
+                Overlay::FORMAT_YUV : Overlay::FORMAT_RGB;
+        pipeSpecs.needsScaling = qhwc::needsScaling(layer) or
+                (qdutils::MDPVersion::getInstance().is8x26() and
+                ctx->dpyAttr[HWC_DISPLAY_PRIMARY].xres > 1024);
+        pipeSpecs.dpy = mDpy;
+        pipeSpecs.fb = false;
+        pipeSpecs.numActiveDisplays = ctx->numActiveDisplays;
 
-        pipe_info.index = getMdpPipe(ctx, type, Overlay::MIXER_DEFAULT);
+        pipe_info.index = ctx->mOverlay->getPipe(pipeSpecs);
+
         if(pipe_info.index == ovutils::OV_INVALID) {
-            ALOGD_IF(isDebug(), "%s: Unable to get pipe type = %d",
-                __FUNCTION__, (int) type);
+            ALOGD_IF(isDebug(), "%s: Unable to get pipe", __FUNCTION__);
             return false;
         }
     }
@@ -1470,18 +1841,8 @@
 
 bool MDPCompNonSplit::draw(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
 
-    if(!isEnabled()) {
-        ALOGD_IF(isDebug(),"%s: MDP Comp not configured", __FUNCTION__);
-        return true;
-    }
-
-    if(!ctx || !list) {
-        ALOGE("%s: invalid contxt or list",__FUNCTION__);
-        return false;
-    }
-
-    if(ctx->listStats[mDpy].numAppLayers > MAX_NUM_APP_LAYERS) {
-        ALOGD_IF(isDebug(),"%s: Exceeding max layer count", __FUNCTION__);
+    if(!isEnabled() or !mModeOn) {
+        ALOGD_IF(isDebug(),"%s: MDP Comp not enabled/configured", __FUNCTION__);
         return true;
     }
 
@@ -1520,7 +1881,7 @@
             ovutils::eDest indexL = pipe_info.lIndex;
             ovutils::eDest indexR = pipe_info.rIndex;
             int fd = hnd->fd;
-            uint32_t offset = hnd->offset;
+            uint32_t offset = (uint32_t)hnd->offset;
             if(rot) {
                 rot->queueBuffer(fd, offset);
                 fd = rot->getDstMemId();
@@ -1561,13 +1922,20 @@
                 continue;
             }
 
+            int fd = hnd->fd;
+            uint32_t offset = (uint32_t)hnd->offset;
+            int index = ctx->mPtorInfo.getPTORArrayIndex(i);
+            if (!mDpy && (index != -1)) {
+                hnd = ctx->mCopyBit[mDpy]->getCurrentRenderBuffer();
+                fd = hnd->fd;
+                // Use the offset of the RenderBuffer
+                offset = ctx->mPtorInfo.mRenderBuffOffset[index];
+            }
+
             ALOGD_IF(isDebug(),"%s: MDP Comp: Drawing layer: %p hnd: %p \
                     using  pipe: %d", __FUNCTION__, layer,
                     hnd, dest );
 
-            int fd = hnd->fd;
-            uint32_t offset = hnd->offset;
-
             Rotator *rot = mCurrentFrame.mdpToLayer[mdpIndex].rot;
             if(rot) {
                 if(!rot->queueBuffer(fd, offset))
@@ -1594,38 +1962,61 @@
          hwc_display_contents_1_t* list){
     //if 4kx2k yuv layer is totally present in either in left half
     //or right half then try splitting the yuv layer to avoid decimation
-    int n4k2kYuvCount = ctx->listStats[mDpy].yuv4k2kCount;
     const int lSplit = getLeftSplit(ctx, mDpy);
-    for(int index = 0; index < n4k2kYuvCount; index++){
-        int n4k2kYuvIndex = ctx->listStats[mDpy].yuv4k2kIndices[index];
-        hwc_layer_1_t* layer = &list->hwLayers[n4k2kYuvIndex];
-        hwc_rect_t dst = layer->displayFrame;
-        if((dst.left > lSplit) || (dst.right < lSplit)) {
-            mCurrentFrame.mdpCount += 1;
-        }
-        if(mCurrentFrame.fbZ > n4k2kYuvIndex){
-            mCurrentFrame.fbZ += 1;
+    if(mCurrentFrame.fbZ >= 0) {
+        for (int index = 0, mdpNextZOrder = 0; index < mCurrentFrame.layerCount;
+                index++) {
+            if(!mCurrentFrame.isFBComposed[index]) {
+                if(mdpNextZOrder == mCurrentFrame.fbZ) {
+                    mdpNextZOrder++;
+                }
+                mdpNextZOrder++;
+                hwc_layer_1_t* layer = &list->hwLayers[index];
+                private_handle_t *hnd = (private_handle_t *)layer->handle;
+                if(is4kx2kYuvBuffer(hnd)) {
+                    hwc_rect_t dst = layer->displayFrame;
+                    if((dst.left > lSplit) || (dst.right < lSplit)) {
+                        mCurrentFrame.mdpCount += 1;
+                    }
+                    if(mdpNextZOrder <= mCurrentFrame.fbZ)
+                        mCurrentFrame.fbZ += 1;
+                    mdpNextZOrder++;
+                }
+            }
         }
     }
 }
 
 bool MDPCompSplit::acquireMDPPipes(hwc_context_t *ctx, hwc_layer_1_t* layer,
-        MdpPipeInfoSplit& pipe_info,
-        ePipeType type) {
-    const int lSplit = getLeftSplit(ctx, mDpy);
+        MdpPipeInfoSplit& pipe_info) {
 
+    const int lSplit = getLeftSplit(ctx, mDpy);
+    private_handle_t *hnd = (private_handle_t *)layer->handle;
     hwc_rect_t dst = layer->displayFrame;
     pipe_info.lIndex = ovutils::OV_INVALID;
     pipe_info.rIndex = ovutils::OV_INVALID;
 
-    if (dst.left < lSplit) {
-        pipe_info.lIndex = getMdpPipe(ctx, type, Overlay::MIXER_LEFT);
+    Overlay::PipeSpecs pipeSpecs;
+    pipeSpecs.formatClass = isYuvBuffer(hnd) ?
+            Overlay::FORMAT_YUV : Overlay::FORMAT_RGB;
+    pipeSpecs.needsScaling = qhwc::needsScalingWithSplit(ctx, layer, mDpy);
+    pipeSpecs.dpy = mDpy;
+    pipeSpecs.mixer = Overlay::MIXER_LEFT;
+    pipeSpecs.fb = false;
+
+    // Acquire pipe only for the updating half
+    hwc_rect_t l_roi = ctx->listStats[mDpy].lRoi;
+    hwc_rect_t r_roi = ctx->listStats[mDpy].rRoi;
+
+    if (dst.left < lSplit && isValidRect(getIntersection(dst, l_roi))) {
+        pipe_info.lIndex = ctx->mOverlay->getPipe(pipeSpecs);
         if(pipe_info.lIndex == ovutils::OV_INVALID)
             return false;
     }
 
-    if(dst.right > lSplit) {
-        pipe_info.rIndex = getMdpPipe(ctx, type, Overlay::MIXER_RIGHT);
+    if(dst.right > lSplit && isValidRect(getIntersection(dst, r_roi))) {
+        pipeSpecs.mixer = Overlay::MIXER_RIGHT;
+        pipe_info.rIndex = ctx->mOverlay->getPipe(pipeSpecs);
         if(pipe_info.rIndex == ovutils::OV_INVALID)
             return false;
     }
@@ -1655,19 +2046,10 @@
         info.pipeInfo = new MdpPipeInfoSplit;
         info.rot = NULL;
         MdpPipeInfoSplit& pipe_info = *(MdpPipeInfoSplit*)info.pipeInfo;
-        ePipeType type = MDPCOMP_OV_ANY;
 
-        if(isYuvBuffer(hnd)) {
-            type = MDPCOMP_OV_VG;
-        } else if(!qhwc::needsScalingWithSplit(ctx, layer, mDpy)
-            && Overlay::getDMAMode() != Overlay::DMA_BLOCK_MODE
-            && ctx->mMDP.version >= qdutils::MDSS_V5) {
-            type = MDPCOMP_OV_DMA;
-        }
-
-        if(!acquireMDPPipes(ctx, layer, pipe_info, type)) {
-            ALOGD_IF(isDebug(), "%s: Unable to get pipe for type = %d",
-                    __FUNCTION__, (int) type);
+        if(!acquireMDPPipes(ctx, layer, pipe_info)) {
+            ALOGD_IF(isDebug(), "%s: Unable to get pipe for type",
+                    __FUNCTION__);
             return false;
         }
     }
@@ -1717,18 +2099,8 @@
 
 bool MDPCompSplit::draw(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
 
-    if(!isEnabled()) {
-        ALOGD_IF(isDebug(),"%s: MDP Comp not configured", __FUNCTION__);
-        return true;
-    }
-
-    if(!ctx || !list) {
-        ALOGE("%s: invalid contxt or list",__FUNCTION__);
-        return false;
-    }
-
-    if(ctx->listStats[mDpy].numAppLayers > MAX_NUM_APP_LAYERS) {
-        ALOGD_IF(isDebug(),"%s: Exceeding max layer count", __FUNCTION__);
+    if(!isEnabled() or !mModeOn) {
+        ALOGD_IF(isDebug(),"%s: MDP Comp not enabled/configured", __FUNCTION__);
         return true;
     }
 
@@ -1766,7 +2138,7 @@
             ovutils::eDest indexL = pipe_info.lIndex;
             ovutils::eDest indexR = pipe_info.rIndex;
             int fd = hnd->fd;
-            uint32_t offset = hnd->offset;
+            uint32_t offset = (uint32_t)hnd->offset;
             if(rot) {
                 rot->queueBuffer(fd, offset);
                 fd = rot->getDstMemId();
@@ -1803,13 +2175,17 @@
             ovutils::eDest indexR = pipe_info.rIndex;
 
             int fd = hnd->fd;
-            int offset = hnd->offset;
+            uint32_t offset = (uint32_t)hnd->offset;
+            int index = ctx->mPtorInfo.getPTORArrayIndex(i);
+            if (!mDpy && (index != -1)) {
+                hnd = ctx->mCopyBit[mDpy]->getCurrentRenderBuffer();
+                fd = hnd->fd;
+                offset = ctx->mPtorInfo.mRenderBuffOffset[index];
+            }
 
-            if(ctx->mAD->isModeOn()) {
-                if(ctx->mAD->draw(ctx, fd, offset)) {
-                    fd = ctx->mAD->getDstFd();
-                    offset = ctx->mAD->getDstOffset();
-                }
+            if(ctx->mAD->draw(ctx, fd, offset)) {
+                fd = ctx->mAD->getDstFd();
+                offset = ctx->mAD->getDstOffset();
             }
 
             if(rot) {
@@ -1851,7 +2227,7 @@
 
 //================MDPCompSrcSplit==============================================
 bool MDPCompSrcSplit::acquireMDPPipes(hwc_context_t *ctx, hwc_layer_1_t* layer,
-        MdpPipeInfoSplit& pipe_info, ePipeType /*type*/) {
+        MdpPipeInfoSplit& pipe_info) {
     private_handle_t *hnd = (private_handle_t *)layer->handle;
     hwc_rect_t dst = layer->displayFrame;
     hwc_rect_t crop = integerizeSourceCrop(layer->sourceCropf);
@@ -1861,56 +2237,52 @@
     //If 2 pipes are staged on a single stage of a mixer, then the left pipe
     //should have a higher priority than the right one. Pipe priorities are
     //starting with VG0, VG1 ... , RGB0 ..., DMA1
-    //TODO Currently we acquire VG pipes for left side and RGB/DMA for right to
-    //make sure pipe priorities are satisfied. A better way is to have priority
-    //as part of overlay object and acquire any 2 pipes. Assign the higher
-    //priority one to left side and lower to right side.
+
+    Overlay::PipeSpecs pipeSpecs;
+    pipeSpecs.formatClass = isYuvBuffer(hnd) ?
+            Overlay::FORMAT_YUV : Overlay::FORMAT_RGB;
+    pipeSpecs.needsScaling = qhwc::needsScaling(layer);
+    pipeSpecs.dpy = mDpy;
+    pipeSpecs.fb = false;
 
     //1 pipe by default for a layer
-    pipe_info.lIndex = getMdpPipe(ctx, MDPCOMP_OV_VG, Overlay::MIXER_DEFAULT);
+    pipe_info.lIndex = ctx->mOverlay->getPipe(pipeSpecs);
     if(pipe_info.lIndex == ovutils::OV_INVALID) {
-        if(isYuvBuffer(hnd)) {
-            return false;
-        }
-        pipe_info.lIndex = getMdpPipe(ctx, MDPCOMP_OV_ANY,
-                Overlay::MIXER_DEFAULT);
-        if(pipe_info.lIndex == ovutils::OV_INVALID) {
-            return false;
-        }
+        return false;
     }
 
-    //If layer's crop width or dest width > 2048, use 2 pipes
-    if((dst.right - dst.left) > qdutils::MAX_DISPLAY_DIM or
-            (crop.right - crop.left) > qdutils::MAX_DISPLAY_DIM) {
-        ePipeType rightType = isYuvBuffer(hnd) ?
-                MDPCOMP_OV_VG : MDPCOMP_OV_ANY;
-        pipe_info.rIndex = getMdpPipe(ctx, rightType, Overlay::MIXER_DEFAULT);
+    /* Use 2 pipes IF
+        a) Layer's crop width is > 2048 or
+        b) Layer's dest width > 2048 or
+        c) On primary, driver has indicated with caps to split always. This is
+           based on an empirically derived value of panel height. Applied only
+           if the layer's width is > mixer's width
+    */
+
+    bool primarySplitAlways = (mDpy == HWC_DISPLAY_PRIMARY) and
+            qdutils::MDPVersion::getInstance().isSrcSplitAlways();
+    int lSplit = getLeftSplit(ctx, mDpy);
+    int dstWidth = dst.right - dst.left;
+    int cropWidth = crop.right - crop.left;
+
+    if(dstWidth > qdutils::MAX_DISPLAY_DIM or
+            cropWidth > qdutils::MAX_DISPLAY_DIM or
+            (primarySplitAlways and (cropWidth > lSplit))) {
+        pipe_info.rIndex = ctx->mOverlay->getPipe(pipeSpecs);
         if(pipe_info.rIndex == ovutils::OV_INVALID) {
             return false;
         }
-    }
 
-    return true;
-}
-
-bool MDPCompSrcSplit::allocLayerPipes(hwc_context_t *ctx,
-        hwc_display_contents_1_t* list) {
-    for(int index = 0 ; index < mCurrentFrame.layerCount; index++) {
-        if(mCurrentFrame.isFBComposed[index]) continue;
-        hwc_layer_1_t* layer = &list->hwLayers[index];
-        int mdpIndex = mCurrentFrame.layerToMDP[index];
-        PipeLayerPair& info = mCurrentFrame.mdpToLayer[mdpIndex];
-        info.pipeInfo = new MdpPipeInfoSplit;
-        info.rot = NULL;
-        MdpPipeInfoSplit& pipe_info = *(MdpPipeInfoSplit*)info.pipeInfo;
-
-        ePipeType type = MDPCOMP_OV_ANY;
-        if(!acquireMDPPipes(ctx, layer, pipe_info, type)) {
-            ALOGD_IF(isDebug(), "%s: Unable to get pipe for type = %d",
-                    __FUNCTION__, (int) type);
-            return false;
+        // Return values
+        // 1  Left pipe is higher priority, do nothing.
+        // 0  Pipes of same priority.
+        //-1  Right pipe is of higher priority, needs swap.
+        if(ctx->mOverlay->comparePipePriority(pipe_info.lIndex,
+                pipe_info.rIndex) == -1) {
+            qhwc::swap(pipe_info.lIndex, pipe_info.rIndex);
         }
     }
+
     return true;
 }
 
@@ -1949,26 +2321,28 @@
             whf.format = getMdpFormat(HAL_PIXEL_FORMAT_BGRX_8888);
     }
 
-    eMdpFlags mdpFlagsL = OV_MDP_BACKEND_COMPOSITION;
-    setMdpFlags(layer, mdpFlagsL, 0, transform);
-    eMdpFlags mdpFlagsR = mdpFlagsL;
+    eMdpFlags mdpFlags = OV_MDP_BACKEND_COMPOSITION;
+    setMdpFlags(ctx, layer, mdpFlags, 0, transform);
 
     if(lDest != OV_INVALID && rDest != OV_INVALID) {
         //Enable overfetch
-        setMdpFlags(mdpFlagsL, OV_MDSS_MDP_DUAL_PIPE);
+        setMdpFlags(mdpFlags, OV_MDSS_MDP_DUAL_PIPE);
     }
 
-    if(isYuvBuffer(hnd) && (transform & HWC_TRANSFORM_ROT_90)) {
+    if(has90Transform(layer) && isRotationDoable(ctx, hnd)) {
         (*rot) = ctx->mRotMgr->getNext();
         if((*rot) == NULL) return -1;
+        ctx->mLayerRotMap[mDpy]->add(layer, *rot);
+        //If the video is using a single pipe, enable BWC
+        if(rDest == OV_INVALID) {
+            BwcPM::setBwc(crop, dst, transform, mdpFlags);
+        }
         //Configure rotator for pre-rotation
-        if(configRotator(*rot, whf, crop, mdpFlagsL, orient, downscale) < 0) {
+        if(configRotator(*rot, whf, crop, mdpFlags, orient, downscale) < 0) {
             ALOGE("%s: configRotator failed!", __FUNCTION__);
             return -1;
         }
-        ctx->mLayerRotMap[mDpy]->add(layer, *rot);
-        whf.format = (*rot)->getDstFormat();
-        updateSource(orient, whf, crop);
+        updateSource(orient, whf, crop, *rot);
         rotFlags |= ROT_PREROTATED;
     }
 
@@ -1999,7 +2373,7 @@
 
     //configure left pipe
     if(lDest != OV_INVALID) {
-        PipeArgs pargL(mdpFlagsL, whf, z, isFg,
+        PipeArgs pargL(mdpFlags, whf, z, isFg,
                 static_cast<eRotFlags>(rotFlags), layer->planeAlpha,
                 (ovutils::eBlending) getBlending(layer->blending));
 
@@ -2012,7 +2386,7 @@
 
     //configure right pipe
     if(rDest != OV_INVALID) {
-        PipeArgs pargR(mdpFlagsR, whf, z, isFg,
+        PipeArgs pargR(mdpFlags, whf, z, isFg,
                 static_cast<eRotFlags>(rotFlags),
                 layer->planeAlpha,
                 (ovutils::eBlending) getBlending(layer->blending));
diff --git a/msm8226/libhwcomposer/hwc_mdpcomp.h b/msm8226/libhwcomposer/hwc_mdpcomp.h
index 2d65755..1ebe0bd 100644
--- a/msm8226/libhwcomposer/hwc_mdpcomp.h
+++ b/msm8226/libhwcomposer/hwc_mdpcomp.h
@@ -43,17 +43,20 @@
     int prepare(hwc_context_t *ctx, hwc_display_contents_1_t* list);
     /* draw */
     virtual bool draw(hwc_context_t *ctx, hwc_display_contents_1_t *list) = 0;
+    //Reset values
+    void reset();
     /* dumpsys */
-    void dump(android::String8& buf);
+    void dump(android::String8& buf, hwc_context_t *ctx);
     bool isGLESOnlyComp() { return (mCurrentFrame.mdpCount == 0); }
+    int drawOverlap(hwc_context_t *ctx, hwc_display_contents_1_t* list);
     static MDPComp* getObject(hwc_context_t *ctx, const int& dpy);
     /* Handler to invoke frame redraw on Idle Timer expiry */
     static void timeout_handler(void *udata);
     /* Initialize MDP comp*/
     static bool init(hwc_context_t *ctx);
     static void resetIdleFallBack() { sIdleFallBack = false; }
-    static void reset() { sHandleTimeout = false; };
     static bool isIdleFallback() { return sIdleFallBack; }
+    static void dynamicDebug(bool enable){ sDebugLogs = enable; }
 
 protected:
     enum { MAX_SEC_LAYERS = 1 }; //TODO add property support
@@ -65,6 +68,14 @@
         MDPCOMP_OV_ANY,
     };
 
+    //Simulation flags
+    enum {
+        MDPCOMP_AVOID_FULL_MDP = 0x001,
+        MDPCOMP_AVOID_CACHE_MDP = 0x002,
+        MDPCOMP_AVOID_LOAD_MDP = 0x004,
+        MDPCOMP_AVOID_VIDEO_ONLY = 0x008,
+    };
+
     /* mdp pipe data */
     struct MdpPipeInfo {
         int zOrder;
@@ -132,8 +143,6 @@
     /* allocates pipe from pipe book */
     virtual bool allocLayerPipes(hwc_context_t *ctx,
                                  hwc_display_contents_1_t* list) = 0;
-    /* allocate MDP pipes from overlay */
-    ovutils::eDest getMdpPipe(hwc_context_t *ctx, ePipeType type, int mixer);
     /* configures MPD pipes */
     virtual int configure(hwc_context_t *ctx, hwc_layer_1_t *layer,
                           PipeLayerPair& pipeLayerPair) = 0;
@@ -144,6 +153,15 @@
     /* configures 4kx2k yuv layer*/
     virtual int configure4k2kYuv(hwc_context_t *ctx, hwc_layer_1_t *layer,
             PipeLayerPair& PipeLayerPair) = 0;
+    /* generates ROI based on the modified area of the frame */
+    virtual void generateROI(hwc_context_t *ctx,
+            hwc_display_contents_1_t* list) = 0;
+    /* validates the ROI generated for fallback conditions */
+    virtual bool validateAndApplyROI(hwc_context_t *ctx,
+            hwc_display_contents_1_t* list) = 0;
+    /* Trims fbRect calculated against ROI generated */
+    virtual void trimAgainstROI(hwc_context_t *ctx, hwc_rect_t& fbRect) = 0;
+
     /* set/reset flags for MDPComp */
     void setMDPCompLayerFlags(hwc_context_t *ctx,
                               hwc_display_contents_1_t* list);
@@ -155,6 +173,8 @@
     bool tryFullFrame(hwc_context_t *ctx, hwc_display_contents_1_t* list);
     /* checks if full MDP comp can be done */
     bool fullMDPComp(hwc_context_t *ctx, hwc_display_contents_1_t* list);
+    /* Full MDP Composition with Peripheral Tiny Overlap Removal */
+    bool fullMDPCompWithPTOR(hwc_context_t *ctx,hwc_display_contents_1_t* list);
     /* check if we can use layer cache to do at least partial MDP comp */
     bool partialMDPComp(hwc_context_t *ctx, hwc_display_contents_1_t* list);
     /* Partial MDP comp that uses caching to save power as primary goal */
@@ -175,11 +195,6 @@
     /* checks if MDP/MDSS can process current list w.r.to HW limitations
      * All peculiar HW limitations should go here */
     bool hwLimitationsCheck(hwc_context_t* ctx, hwc_display_contents_1_t* list);
-    /* generates ROI based on the modified area of the frame */
-    void generateROI(hwc_context_t *ctx, hwc_display_contents_1_t* list);
-    bool validateAndApplyROI(hwc_context_t *ctx, hwc_display_contents_1_t* list,
-                             hwc_rect_t roi);
-
     /* Is debug enabled */
     static bool isDebug() { return sDebugLogs ? true : false; };
     /* Is feature enabled */
@@ -213,15 +228,16 @@
             hwc_display_contents_1_t* list);
     void reset(hwc_context_t *ctx);
     bool isSupportedForMDPComp(hwc_context_t *ctx, hwc_layer_1_t* layer);
-    bool resourceCheck(hwc_context_t *ctx, hwc_display_contents_1_t *list);
+    bool resourceCheck(hwc_context_t* ctx, hwc_display_contents_1_t* list);
     hwc_rect_t getUpdatingFBRect(hwc_context_t *ctx,
             hwc_display_contents_1_t* list);
+    /* checks for conditions to enable partial udpate */
+    bool canPartialUpdate(hwc_context_t *ctx, hwc_display_contents_1_t* list);
 
     int mDpy;
     static bool sEnabled;
     static bool sEnableMixedMode;
-    /* Enables Partial frame composition */
-    static bool sEnablePartialFrameUpdate;
+    static int sSimulationFlags;
     static bool sDebugLogs;
     static bool sIdleFallBack;
     /* Handles the timeout event from kernel, if the value is set to true */
@@ -233,6 +249,7 @@
     struct LayerCache mCachedFrame;
     //Enable 4kx2k yuv layer split
     static bool sEnable4k2kYUVSplit;
+    bool mModeOn; // if prepare happened
     bool allocSplitVGPipesfor4k2k(hwc_context_t *ctx, int index);
 };
 
@@ -264,6 +281,14 @@
     /* configures 4kx2k yuv layer to 2 VG pipes*/
     virtual int configure4k2kYuv(hwc_context_t *ctx, hwc_layer_1_t *layer,
             PipeLayerPair& PipeLayerPair);
+    /* generates ROI based on the modified area of the frame */
+    virtual void generateROI(hwc_context_t *ctx,
+            hwc_display_contents_1_t* list);
+    /* validates the ROI generated for fallback conditions */
+    virtual bool validateAndApplyROI(hwc_context_t *ctx,
+            hwc_display_contents_1_t* list);
+    /* Trims fbRect calculated against ROI generated */
+    virtual void trimAgainstROI(hwc_context_t *ctx, hwc_rect_t& fbRect);
 };
 
 class MDPCompSplit : public MDPComp {
@@ -280,7 +305,7 @@
     };
 
     virtual bool acquireMDPPipes(hwc_context_t *ctx, hwc_layer_1_t* layer,
-                         MdpPipeInfoSplit& pipe_info, ePipeType type);
+                         MdpPipeInfoSplit& pipe_info);
 
     /* configure's overlay pipes for the frame */
     virtual int configure(hwc_context_t *ctx, hwc_layer_1_t *layer,
@@ -289,7 +314,6 @@
     /* allocates pipes to selected candidates */
     virtual bool allocLayerPipes(hwc_context_t *ctx,
                                  hwc_display_contents_1_t* list);
-
 private:
     /* Increments mdpCount if 4k2k yuv layer split is enabled.
      * updates framebuffer z order if fb lies above source-split layer */
@@ -299,6 +323,14 @@
     /* configures 4kx2k yuv layer*/
     virtual int configure4k2kYuv(hwc_context_t *ctx, hwc_layer_1_t *layer,
             PipeLayerPair& PipeLayerPair);
+    /* generates ROI based on the modified area of the frame */
+    virtual void generateROI(hwc_context_t *ctx,
+            hwc_display_contents_1_t* list);
+    /* validates the ROI generated for fallback conditions */
+    virtual bool validateAndApplyROI(hwc_context_t *ctx,
+            hwc_display_contents_1_t* list);
+    /* Trims fbRect calculated against ROI generated */
+    virtual void trimAgainstROI(hwc_context_t *ctx, hwc_rect_t& fbRect);
 };
 
 class MDPCompSrcSplit : public MDPCompSplit {
@@ -307,10 +339,7 @@
     virtual ~MDPCompSrcSplit(){};
 private:
     virtual bool acquireMDPPipes(hwc_context_t *ctx, hwc_layer_1_t* layer,
-            MdpPipeInfoSplit& pipe_info, ePipeType type);
-
-    virtual bool allocLayerPipes(hwc_context_t *ctx,
-            hwc_display_contents_1_t* list);
+            MdpPipeInfoSplit& pipe_info);
 
     virtual int configure(hwc_context_t *ctx, hwc_layer_1_t *layer,
             PipeLayerPair& pipeLayerPair);
diff --git a/msm8226/libhwcomposer/hwc_qclient.cpp b/msm8226/libhwcomposer/hwc_qclient.cpp
index 5313795..892e9c0 100644
--- a/msm8226/libhwcomposer/hwc_qclient.cpp
+++ b/msm8226/libhwcomposer/hwc_qclient.cpp
@@ -31,6 +31,7 @@
 #include <IQService.h>
 #include <hwc_utils.h>
 #include <mdp_version.h>
+#include <hwc_mdpcomp.h>
 
 #define QCLIENT_DEBUG 0
 
@@ -108,8 +109,13 @@
         Parcel* outParcel) {
     int dpy = inParcel->readInt32();
     outParcel->writeInt32(ctx->dpyAttr[dpy].vsync_period);
-    outParcel->writeInt32(ctx->dpyAttr[dpy].xres);
-    outParcel->writeInt32(ctx->dpyAttr[dpy].yres);
+    if (ctx->dpyAttr[dpy].customFBSize) {
+        outParcel->writeInt32(ctx->dpyAttr[dpy].xres_new);
+        outParcel->writeInt32(ctx->dpyAttr[dpy].yres_new);
+    } else {
+        outParcel->writeInt32(ctx->dpyAttr[dpy].xres);
+        outParcel->writeInt32(ctx->dpyAttr[dpy].yres);
+    }
     outParcel->writeFloat(ctx->dpyAttr[dpy].xdpi);
     outParcel->writeFloat(ctx->dpyAttr[dpy].ydpi);
     //XXX: Need to check what to return for HDMI
@@ -157,6 +163,9 @@
 }
 
 static void pauseWFD(hwc_context_t *ctx, uint32_t pause) {
+    /* TODO: Will remove pauseWFD once all the clients start using
+     * setWfdStatus to indicate the status of WFD display
+     */
     int dpy = HWC_DISPLAY_VIRTUAL;
     if(pause) {
         //WFD Pause
@@ -167,6 +176,64 @@
     }
 }
 
+static void setWfdStatus(hwc_context_t *ctx, uint32_t wfdStatus) {
+
+    ALOGD_IF(HWC_WFDDISPSYNC_LOG,
+             "%s: Received a binder call that WFD state is %s",
+             __FUNCTION__,getExternalDisplayState(wfdStatus));
+    int dpy = HWC_DISPLAY_VIRTUAL;
+
+    if(wfdStatus == EXTERNAL_OFFLINE) {
+        ctx->mWfdSyncLock.lock();
+        ctx->mWfdSyncLock.signal();
+        ctx->mWfdSyncLock.unlock();
+    } else if(wfdStatus == EXTERNAL_PAUSE) {
+        handle_pause(ctx, dpy);
+    } else if(wfdStatus == EXTERNAL_RESUME) {
+        handle_resume(ctx, dpy);
+    }
+}
+
+
+static status_t setViewFrame(hwc_context_t* ctx, const Parcel* inParcel) {
+    int dpy = inParcel->readInt32();
+    if(dpy >= HWC_DISPLAY_PRIMARY && dpy <= HWC_DISPLAY_VIRTUAL) {
+        Locker::Autolock _sl(ctx->mDrawLock);
+        ctx->mViewFrame[dpy].left   = inParcel->readInt32();
+        ctx->mViewFrame[dpy].top    = inParcel->readInt32();
+        ctx->mViewFrame[dpy].right  = inParcel->readInt32();
+        ctx->mViewFrame[dpy].bottom = inParcel->readInt32();
+        ALOGD_IF(QCLIENT_DEBUG, "%s: mViewFrame[%d] = [%d %d %d %d]",
+            __FUNCTION__, dpy,
+            ctx->mViewFrame[dpy].left, ctx->mViewFrame[dpy].top,
+            ctx->mViewFrame[dpy].right, ctx->mViewFrame[dpy].bottom);
+        return NO_ERROR;
+    } else {
+        ALOGE("In %s: invalid dpy index %d", __FUNCTION__, dpy);
+        return BAD_VALUE;
+    }
+}
+
+static void toggleDynamicDebug(hwc_context_t* ctx, const Parcel* inParcel) {
+    int debug_type = inParcel->readInt32();
+    bool enable = !!inParcel->readInt32();
+    ALOGD("%s: debug_type: %d enable:%d",
+            __FUNCTION__, debug_type, enable);
+    Locker::Autolock _sl(ctx->mDrawLock);
+    switch (debug_type) {
+        //break is ignored for DEBUG_ALL to toggle all of them at once
+        case IQService::DEBUG_ALL:
+        case IQService::DEBUG_MDPCOMP:
+            qhwc::MDPComp::dynamicDebug(enable);
+            if (debug_type != IQService::DEBUG_ALL)
+                break;
+        case IQService::DEBUG_VSYNC:
+            ctx->vstate.debug = enable;
+            if (debug_type != IQService::DEBUG_ALL)
+                break;
+    }
+}
+
 status_t QClient::notifyCallback(uint32_t command, const Parcel* inParcel,
         Parcel* outParcel) {
     status_t ret = NO_ERROR;
@@ -199,15 +266,23 @@
             break;
         case IQService::SET_HSIC_DATA:
             setHSIC(inParcel);
+            break;
         case IQService::PAUSE_WFD:
             pauseWFD(mHwcContext, inParcel->readInt32());
             break;
+        case IQService::SET_WFD_STATUS:
+            setWfdStatus(mHwcContext,inParcel->readInt32());
+            break;
+        case IQService::SET_VIEW_FRAME:
+            setViewFrame(mHwcContext, inParcel);
+            break;
+        case IQService::DYNAMIC_DEBUG:
+            toggleDynamicDebug(mHwcContext, inParcel);
+            break;
         default:
             ret = NO_ERROR;
     }
     return ret;
 }
 
-
-
 }
diff --git a/msm8226/libhwcomposer/hwc_uevents.cpp b/msm8226/libhwcomposer/hwc_uevents.cpp
index e51a1a4..fed6f3c 100644
--- a/msm8226/libhwcomposer/hwc_uevents.cpp
+++ b/msm8226/libhwcomposer/hwc_uevents.cpp
@@ -32,20 +32,13 @@
 #include "comptype.h"
 #include "external.h"
 #include "virtual.h"
+#include "hwc_virtual.h"
 #include "mdp_version.h"
 using namespace overlay;
 namespace qhwc {
 #define HWC_UEVENT_SWITCH_STR  "change@/devices/virtual/switch/"
 #define HWC_UEVENT_THREAD_NAME "hwcUeventThread"
 
-/* External Display states */
-enum {
-    EXTERNAL_OFFLINE = 0,
-    EXTERNAL_ONLINE,
-    EXTERNAL_PAUSE,
-    EXTERNAL_RESUME
-};
-
 static void setup(hwc_context_t* ctx, int dpy)
 {
     ctx->mFBUpdate[dpy] = IFBUpdate::getObject(ctx, dpy);
@@ -107,53 +100,15 @@
 }
 
 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);
-        }
+    if(ctx->mHWCVirtual) {
+        ctx->mHWCVirtual->pause(ctx, 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);
+    if(ctx->mHWCVirtual) {
+        ctx->mHWCVirtual->resume(ctx, dpy);
     }
     return;
 }
@@ -182,9 +137,24 @@
             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);
+
+    if(ctx->mVDSEnabled) {
+        ctx->mWfdSyncLock.lock();
+        ALOGD_IF(HWC_WFDDISPSYNC_LOG,
+                 "%s: Waiting for wfd-teardown to be signalled",__FUNCTION__);
+        ctx->mWfdSyncLock.wait();
+        ALOGD_IF(HWC_WFDDISPSYNC_LOG,
+                 "%s: Teardown signalled. Completed waiting in uevent thread",
+                 __FUNCTION__);
+        ctx->mWfdSyncLock.unlock();
+    } else {
+        /*TODO: Remove this else block and have wait rather than usleep
+          once wfd module issues binder call on teardown.*/
+
+        /* For now, 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)
@@ -203,7 +173,7 @@
 
     int switch_state = getConnectedState(udata, len);
 
-    ALOGE_IF(UEVENT_DEBUG,"%s: uevent recieved: %s switch state: %d",
+    ALOGE_IF(UEVENT_DEBUG,"%s: uevent received: %s switch state: %d",
              __FUNCTION__,udata, switch_state);
 
     switch(switch_state) {
@@ -360,7 +330,7 @@
     }
 
     while(1) {
-        len = uevent_next_event(udata, sizeof(udata) - 2);
+        len = uevent_next_event(udata, (int)sizeof(udata) - 2);
         handle_uevent(ctx, udata, len);
     }
 
diff --git a/msm8226/libhwcomposer/hwc_utils.cpp b/msm8226/libhwcomposer/hwc_utils.cpp
index 4377725..36de703 100644
--- a/msm8226/libhwcomposer/hwc_utils.cpp
+++ b/msm8226/libhwcomposer/hwc_utils.cpp
@@ -83,23 +83,29 @@
             (xres < MIN_DISPLAY_XRES || yres < MIN_DISPLAY_YRES));
 }
 
-void changeResolution(hwc_context_t *ctx, int xres_orig, int yres_orig) {
+void changeResolution(hwc_context_t *ctx, int xres_orig, int yres_orig,
+                      int width, int height) {
     //Store original display resolution.
-    ctx->dpyAttr[HWC_DISPLAY_PRIMARY].xres_orig = xres_orig;
-    ctx->dpyAttr[HWC_DISPLAY_PRIMARY].yres_orig = yres_orig;
+    ctx->dpyAttr[HWC_DISPLAY_PRIMARY].xres_new = xres_orig;
+    ctx->dpyAttr[HWC_DISPLAY_PRIMARY].yres_new = yres_orig;
     ctx->dpyAttr[HWC_DISPLAY_PRIMARY].customFBSize = false;
-
     char property[PROPERTY_VALUE_MAX] = {'\0'};
     char *yptr = NULL;
     if (property_get("debug.hwc.fbsize", property, NULL) > 0) {
         yptr = strcasestr(property,"x");
-        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;
+        int xres_new = atoi(property);
+        int yres_new = atoi(yptr + 1);
+        if (isValidResolution(ctx,xres_new,yres_new) &&
+                 xres_new != xres_orig && yres_new != yres_orig) {
+            ctx->dpyAttr[HWC_DISPLAY_PRIMARY].xres_new = xres_new;
+            ctx->dpyAttr[HWC_DISPLAY_PRIMARY].yres_new = yres_new;
             ctx->dpyAttr[HWC_DISPLAY_PRIMARY].customFBSize = true;
+
+            //Caluculate DPI according to changed resolution.
+            float xdpi = ((float)xres_new * 25.4f) / (float)width;
+            float ydpi = ((float)yres_new * 25.4f) / (float)height;
+            ctx->dpyAttr[HWC_DISPLAY_PRIMARY].xdpi = xdpi;
+            ctx->dpyAttr[HWC_DISPLAY_PRIMARY].ydpi = ydpi;
         }
     }
 }
@@ -125,12 +131,12 @@
     if (int(info.width) <= 0 || int(info.height) <= 0) {
         // the driver doesn't return that information
         // default to 160 dpi
-        info.width  = ((info.xres * 25.4f)/160.0f + 0.5f);
-        info.height = ((info.yres * 25.4f)/160.0f + 0.5f);
+        info.width  = (int)(((float)info.xres * 25.4f)/160.0f + 0.5f);
+        info.height = (int)(((float)info.yres * 25.4f)/160.0f + 0.5f);
     }
 
-    float xdpi = (info.xres * 25.4f) / info.width;
-    float ydpi = (info.yres * 25.4f) / info.height;
+    float xdpi = ((float)info.xres * 25.4f) / (float)info.width;
+    float ydpi = ((float)info.yres * 25.4f) / (float)info.height;
 
 #ifdef MSMFB_METADATA_GET
     struct msmfb_metadata metadata;
@@ -144,7 +150,7 @@
         return -errno;
     }
 
-    float fps  = metadata.data.panel_frame_rate;
+    float fps  = (float)metadata.data.panel_frame_rate;
 #else
     //XXX: Remove reserved field usage on all baselines
     //The reserved[3] field is used to store FPS by the driver.
@@ -165,10 +171,11 @@
     ctx->dpyAttr[HWC_DISPLAY_PRIMARY].yres = info.yres;
     ctx->dpyAttr[HWC_DISPLAY_PRIMARY].xdpi = xdpi;
     ctx->dpyAttr[HWC_DISPLAY_PRIMARY].ydpi = ydpi;
-    ctx->dpyAttr[HWC_DISPLAY_PRIMARY].vsync_period = 1000000000l / fps;
+    ctx->dpyAttr[HWC_DISPLAY_PRIMARY].vsync_period =
+            (uint32_t)(1000000000l / fps);
 
     //To change resolution of primary display
-    changeResolution(ctx, info.xres, info.yres);
+    changeResolution(ctx, info.xres, info.yres, info.width, info.height);
 
     //Unblank primary on first boot
     if(ioctl(fb_fd, FBIOBLANK,FB_BLANK_UNBLANK) < 0) {
@@ -183,6 +190,7 @@
 void initContext(hwc_context_t *ctx)
 {
     openFramebufferDevice(ctx);
+    char value[PROPERTY_VALUE_MAX];
     ctx->mMDP.version = qdutils::MDPVersion::getInstance().getMDPVersion();
     ctx->mMDP.hasOverlay = qdutils::MDPVersion::getInstance().hasOverlay();
     ctx->mMDP.panel = qdutils::MDPVersion::getInstance().getPanelType();
@@ -224,7 +232,21 @@
     ctx->mMDPComp[HWC_DISPLAY_PRIMARY] =
          MDPComp::getObject(ctx, HWC_DISPLAY_PRIMARY);
     ctx->dpyAttr[HWC_DISPLAY_PRIMARY].connected = true;
-    ctx->mHWCVirtual = HWCVirtualBase::getObject();
+    //Initialize the primary display viewFrame info
+    ctx->mViewFrame[HWC_DISPLAY_PRIMARY].left = 0;
+    ctx->mViewFrame[HWC_DISPLAY_PRIMARY].top = 0;
+    ctx->mViewFrame[HWC_DISPLAY_PRIMARY].right =
+        (int)ctx->dpyAttr[HWC_DISPLAY_PRIMARY].xres;
+    ctx->mViewFrame[HWC_DISPLAY_PRIMARY].bottom =
+         (int)ctx->dpyAttr[HWC_DISPLAY_PRIMARY].yres;
+
+    ctx->mVDSEnabled = false;
+    if((property_get("persist.hwc.enable_vds", value, NULL) > 0)) {
+        if(atoi(value) != 0) {
+            ctx->mVDSEnabled = true;
+        }
+    }
+    ctx->mHWCVirtual = HWCVirtualBase::getObject(ctx->mVDSEnabled);
 
     for (uint32_t i = 0; i < HWC_NUM_DISPLAY_TYPES; i++) {
         ctx->mHwcDebug[i] = new HwcDebug(i);
@@ -261,12 +283,15 @@
 
     // Read the system property to determine if downscale feature is enabled.
     ctx->mMDPDownscaleEnabled = false;
-    char value[PROPERTY_VALUE_MAX];
     if(property_get("sys.hwc.mdp_downscale_enabled", value, "false")
             && !strcmp(value, "true")) {
         ctx->mMDPDownscaleEnabled = true;
     }
 
+    ctx->enableABC = false;
+    property_get("debug.sf.hwc.canUseABC", value, "0");
+    ctx->enableABC  = atoi(value) ? true : false;
+
     // Initialize gpu perfomance hint related parameters
     property_get("sys.hwc.gpu_perf_mode", value, "0");
 #ifdef QCOM_BSP
@@ -274,9 +299,10 @@
 
     ctx->mGPUHintInfo.mEGLDisplay = NULL;
     ctx->mGPUHintInfo.mEGLContext = NULL;
-    ctx->mGPUHintInfo.mPrevCompositionGLES = false;
+    ctx->mGPUHintInfo.mCompositionState = COMPOSITION_STATE_MDP;
     ctx->mGPUHintInfo.mCurrGPUPerfMode = EGL_GPU_LEVEL_0;
 #endif
+    memset(&(ctx->mPtorInfo), 0, sizeof(ctx->mPtorInfo));
     ALOGI("Initializing Qualcomm Hardware Composer");
     ALOGI("MDP version: %d", ctx->mMDP.version);
 }
@@ -391,26 +417,26 @@
 
     float asX = 0;
     float asY = 0;
-    float asW = fbWidth;
-    float asH = fbHeight;
+    float asW = (float)fbWidth;
+    float asH = (float)fbHeight;
 
     // based on the action safe ratio, get the Action safe rectangle
-    asW = fbWidth * (1.0f -  asWidthRatio / 100.0f);
-    asH = fbHeight * (1.0f -  asHeightRatio / 100.0f);
-    asX = (fbWidth - asW) / 2;
-    asY = (fbHeight - asH) / 2;
+    asW = ((float)fbWidth * (1.0f -  (float)asWidthRatio / 100.0f));
+    asH = ((float)fbHeight * (1.0f -  (float)asHeightRatio / 100.0f));
+    asX = ((float)fbWidth - asW) / 2;
+    asY = ((float)fbHeight - asH) / 2;
 
     // calculate the position ratio
-    xRatio = (float)x/fbWidth;
-    yRatio = (float)y/fbHeight;
-    wRatio = (float)w/fbWidth;
-    hRatio = (float)h/fbHeight;
+    xRatio = (float)x/(float)fbWidth;
+    yRatio = (float)y/(float)fbHeight;
+    wRatio = (float)w/(float)fbWidth;
+    hRatio = (float)h/(float)fbHeight;
 
     //Calculate the position...
-    x = (xRatio * asW) + asX;
-    y = (yRatio * asH) + asY;
-    w = (wRatio * asW);
-    h = (hRatio * asH);
+    x = int((xRatio * asW) + asX);
+    y = int((yRatio * asH) + asY);
+    w = int(wRatio * asW);
+    h = int(hRatio * asH);
 
     // Convert it back to hwc_rect_t
     rect.left = x;
@@ -425,10 +451,9 @@
 // based on the position and aspect ratio with orientation
 void getAspectRatioPosition(hwc_context_t* ctx, int dpy, int extOrientation,
                             hwc_rect_t& inRect, hwc_rect_t& outRect) {
-    hwc_rect_t viewFrame = ctx->mViewFrame[dpy];
     // Physical display resolution
-    float fbWidth  = ctx->dpyAttr[dpy].xres;
-    float fbHeight = ctx->dpyAttr[dpy].yres;
+    float fbWidth  = (float)ctx->dpyAttr[dpy].xres;
+    float fbHeight = (float)ctx->dpyAttr[dpy].yres;
     //display position(x,y,w,h) in correct aspectratio after rotation
     int xPos = 0;
     int yPos = 0;
@@ -449,7 +474,7 @@
     Dim outPos(outRect.left, outRect.top, outRect.right - outRect.left,
                 outRect.bottom - outRect.top);
 
-    Whf whf(fbWidth, fbHeight, 0);
+    Whf whf((uint32_t)fbWidth, (uint32_t)fbHeight, 0);
     eTransform extorient = static_cast<eTransform>(extOrientation);
     // To calculate the destination co-ordinates in the new orientation
     preRotateSource(extorient, whf, inPos);
@@ -457,30 +482,23 @@
     if(extOrientation & HAL_TRANSFORM_ROT_90) {
         // Swap width/height for input position
         swapWidthHeight(actualWidth, actualHeight);
-        getAspectRatioPosition(fbWidth, fbHeight, (int)actualWidth,
+        getAspectRatioPosition((int)fbWidth, (int)fbHeight, (int)actualWidth,
                                (int)actualHeight, rect);
         xPos = rect.left;
         yPos = rect.top;
-        width = rect.right - rect.left;
-        height = rect.bottom - rect.top;
-        // swap viewframe coordinates for 90 degree rotation.
-        swap(viewFrame.left, viewFrame.top);
-        swap(viewFrame.right, viewFrame.bottom);
+        width = float(rect.right - rect.left);
+        height = float(rect.bottom - rect.top);
     }
-    // if viewframe left and top coordinates are non zero value then exclude it
-    // during the computation of xRatio and yRatio
-    xRatio = (inPos.x - viewFrame.left)/actualWidth;
-    yRatio = (inPos.y - viewFrame.top)/actualHeight;
-    // Use viewframe width and height to compute wRatio and hRatio.
-    wRatio = (float)inPos.w/(float)(viewFrame.right - viewFrame.left);
-    hRatio = (float)inPos.h/(float)(viewFrame.bottom - viewFrame.top);
+    xRatio = (float)((float)inPos.x/actualWidth);
+    yRatio = (float)((float)inPos.y/actualHeight);
+    wRatio = (float)((float)inPos.w/actualWidth);
+    hRatio = (float)((float)inPos.h/actualHeight);
 
-
-    //Calculate the position...
-    outPos.x = (xRatio * width) + xPos;
-    outPos.y = (yRatio * height) + yPos;
-    outPos.w = wRatio * width;
-    outPos.h = hRatio * height;
+    //Calculate the pos9ition...
+    outPos.x = uint32_t((xRatio * width) + (float)xPos);
+    outPos.y = uint32_t((yRatio * height) + (float)yPos);
+    outPos.w = uint32_t(wRatio * width);
+    outPos.h = uint32_t(hRatio * height);
     ALOGD_IF(HWC_UTILS_DEBUG, "%s: Calculated AspectRatio Position: x = %d,"
                  "y = %d w = %d h = %d", __FUNCTION__, outPos.x, outPos.y,
                  outPos.w, outPos.h);
@@ -493,22 +511,23 @@
                         isOrientationPortrait(ctx)) {
         hwc_rect_t r = {0, 0, 0, 0};
         //Calculate the position
-        xRatio = (outPos.x - xPos)/width;
+        xRatio = (float)(outPos.x - xPos)/width;
         // GetaspectRatio -- tricky to get the correct aspect ratio
         // But we need to do this.
-        getAspectRatioPosition(width, height, width, height, r);
+        getAspectRatioPosition((int)width, (int)height,
+                               (int)width,(int)height, r);
         xPos = r.left;
         yPos = r.top;
-        float tempHeight = r.bottom - r.top;
-        yRatio = yPos/height;
-        wRatio = outPos.w/width;
+        float tempHeight = float(r.bottom - r.top);
+        yRatio = (float)yPos/height;
+        wRatio = (float)outPos.w/width;
         hRatio = tempHeight/height;
 
         //Map the coordinates back to Framebuffer domain
-        outPos.x = (xRatio * fbWidth);
-        outPos.y = (yRatio * fbHeight);
-        outPos.w = wRatio * fbWidth;
-        outPos.h = hRatio * fbHeight;
+        outPos.x = uint32_t(xRatio * fbWidth);
+        outPos.y = uint32_t(yRatio * fbHeight);
+        outPos.w = uint32_t(wRatio * fbWidth);
+        outPos.h = uint32_t(hRatio * fbHeight);
 
         ALOGD_IF(HWC_UTILS_DEBUG, "%s: Calculated AspectRatio for device in"
                  "portrait: x = %d,y = %d w = %d h = %d", __FUNCTION__,
@@ -521,18 +540,18 @@
             ctx->mExtDisplay->getAttributes(extW, extH);
         else
             ctx->mVirtualDisplay->getAttributes(extW, extH);
-        fbWidth  = ctx->dpyAttr[dpy].xres;
-        fbHeight = ctx->dpyAttr[dpy].yres;
+        fbWidth  = (float)ctx->dpyAttr[dpy].xres;
+        fbHeight = (float)ctx->dpyAttr[dpy].yres;
         //Calculate the position...
-        xRatio = outPos.x/fbWidth;
-        yRatio = outPos.y/fbHeight;
-        wRatio = outPos.w/fbWidth;
-        hRatio = outPos.h/fbHeight;
+        xRatio = (float)outPos.x/fbWidth;
+        yRatio = (float)outPos.y/fbHeight;
+        wRatio = (float)outPos.w/fbWidth;
+        hRatio = (float)outPos.h/fbHeight;
 
-        outPos.x = xRatio * extW;
-        outPos.y = yRatio * extH;
-        outPos.w = wRatio * extW;
-        outPos.h = hRatio * extH;
+        outPos.x = uint32_t(xRatio * (float)extW);
+        outPos.y = uint32_t(yRatio * (float)extH);
+        outPos.w = uint32_t(wRatio * (float)extW);
+        outPos.h = uint32_t(hRatio * (float)extH);
     }
     // Convert Dim to hwc_rect_t
     outRect.left = outPos.x;
@@ -568,7 +587,7 @@
                                ovutils::eTransform& orient) {
     // Swap width and height when there is a 90deg transform
     int extOrient = getExtOrientation(ctx);
-    if(dpy && !qdutils::MDPVersion::getInstance().is8x26()) {
+    if(dpy && ctx->mOverlay->isUIScalingOnExternalSupported()) {
         if(!isYuvBuffer(hnd)) {
             if(extOrient & HWC_TRANSFORM_ROT_90) {
                 int dstWidth = ctx->dpyAttr[dpy].xres;
@@ -595,8 +614,8 @@
                 int extW, extH;
                 // if downscale is enabled, map the co-ordinates to new
                 // domain(downscaled)
-                float fbWidth  = ctx->dpyAttr[dpy].xres;
-                float fbHeight = ctx->dpyAttr[dpy].yres;
+                float fbWidth  = (float)ctx->dpyAttr[dpy].xres;
+                float fbHeight = (float)ctx->dpyAttr[dpy].yres;
                 // query MDP configured attributes
                 if(dpy == HWC_DISPLAY_EXTERNAL)
                     ctx->mExtDisplay->getAttributes(extW, extH);
@@ -607,10 +626,10 @@
                 float hRatio = ((float)extH)/fbHeight;
 
                 //convert Dim to hwc_rect_t
-                displayFrame.left *= wRatio;
-                displayFrame.top *= hRatio;
-                displayFrame.right *= wRatio;
-                displayFrame.bottom *= hRatio;
+                displayFrame.left = int(wRatio*(float)displayFrame.left);
+                displayFrame.top = int(hRatio*(float)displayFrame.top);
+                displayFrame.right = int(wRatio*(float)displayFrame.right);
+                displayFrame.bottom = int(hRatio*(float)displayFrame.bottom);
             }
         }else {
             if(extOrient || ctx->dpyAttr[dpy].mDownScaleMode) {
@@ -648,6 +667,21 @@
     return extOrientation;
 }
 
+/* Get External State names */
+const char* getExternalDisplayState(uint32_t external_state) {
+    static const char* externalStates[EXTERNAL_MAXSTATES] = {0};
+    externalStates[EXTERNAL_OFFLINE] = STR(EXTERNAL_OFFLINE);
+    externalStates[EXTERNAL_ONLINE]  = STR(EXTERNAL_ONLINE);
+    externalStates[EXTERNAL_PAUSE]   = STR(EXTERNAL_PAUSE);
+    externalStates[EXTERNAL_RESUME]  = STR(EXTERNAL_RESUME);
+
+    if(external_state >= EXTERNAL_MAXSTATES) {
+        return "EXTERNAL_INVALID";
+    }
+
+    return externalStates[external_state];
+}
+
 bool isDownscaleRequired(hwc_layer_1_t const* layer) {
     hwc_rect_t displayFrame  = layer->displayFrame;
     hwc_rect_t sourceCrop = integerizeSourceCrop(layer->sourceCropf);
@@ -775,41 +809,19 @@
                 list->hwLayers[i].transform,
                 (hwc_rect_t&)crop,
                 (hwc_rect_t&)list->hwLayers[i].displayFrame);
-        layer->sourceCropf.left = crop.left;
-        layer->sourceCropf.right = crop.right;
-        layer->sourceCropf.top = crop.top;
-        layer->sourceCropf.bottom = crop.bottom;
+        layer->sourceCropf.left = (float)crop.left;
+        layer->sourceCropf.right = (float)crop.right;
+        layer->sourceCropf.top = (float)crop.top;
+        layer->sourceCropf.bottom = (float)crop.bottom;
     }
 }
 
-hwc_rect_t calculateDisplayViewFrame(hwc_context_t *ctx, int dpy) {
-    int dstWidth = ctx->dpyAttr[dpy].xres;
-    int dstHeight = ctx->dpyAttr[dpy].yres;
-    int srcWidth = ctx->dpyAttr[HWC_DISPLAY_PRIMARY].xres;
-    int srcHeight = ctx->dpyAttr[HWC_DISPLAY_PRIMARY].yres;
-    // default we assume viewframe as a full frame for primary display
-    hwc_rect outRect = {0, 0, dstWidth, dstHeight};
-    if(dpy) {
-        // swap srcWidth and srcHeight, if the device orientation is 90 or 270.
-        if(ctx->deviceOrientation & 0x1) {
-            swap(srcWidth, srcHeight);
-        }
-        // Get Aspect Ratio for external
-        getAspectRatioPosition(dstWidth, dstHeight, srcWidth,
-                            srcHeight, outRect);
-    }
-    ALOGD_IF(HWC_UTILS_DEBUG, "%s: view frame for dpy %d is [%d %d %d %d]",
-        __FUNCTION__, dpy, outRect.left, outRect.top,
-        outRect.right, outRect.bottom);
-    return outRect;
-}
-
 void setListStats(hwc_context_t *ctx,
         hwc_display_contents_1_t *list, int dpy) {
     const int prevYuvCount = ctx->listStats[dpy].yuvCount;
     memset(&ctx->listStats[dpy], 0, sizeof(ListStats));
-    ctx->listStats[dpy].numAppLayers = list->numHwLayers - 1;
-    ctx->listStats[dpy].fbLayerIndex = list->numHwLayers - 1;
+    ctx->listStats[dpy].numAppLayers = (int)list->numHwLayers - 1;
+    ctx->listStats[dpy].fbLayerIndex = (int)list->numHwLayers - 1;
     ctx->listStats[dpy].skipCount = 0;
     ctx->listStats[dpy].preMultipliedAlpha = false;
     ctx->listStats[dpy].isSecurePresent = false;
@@ -817,20 +829,15 @@
     char property[PROPERTY_VALUE_MAX];
     ctx->listStats[dpy].extOnlyLayerIndex = -1;
     ctx->listStats[dpy].isDisplayAnimating = false;
-    ctx->listStats[dpy].roi = ovutils::Dim(0, 0,
-                      (int)ctx->dpyAttr[dpy].xres, (int)ctx->dpyAttr[dpy].yres);
     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);
+    ctx->listStats[dpy].renderBufIndexforABC = -1;
+
+    resetROI(ctx, dpy);
 
     trimList(ctx, list, dpy);
     optimizeLayerRects(list);
-
-    // Calculate view frame of ext display from primary resolution
-    // and primary device orientation.
-    ctx->mViewFrame[dpy] = calculateDisplayViewFrame(ctx, dpy);
-
     for (size_t i = 0; i < (size_t)ctx->listStats[dpy].numAppLayers; i++) {
         hwc_layer_1_t const* layer = &list->hwLayers[i];
         private_handle_t *hnd = (private_handle_t *)layer->handle;
@@ -861,30 +868,21 @@
 
         if (UNLIKELY(isYuvBuffer(hnd))) {
             int& yuvCount = ctx->listStats[dpy].yuvCount;
-            ctx->listStats[dpy].yuvIndices[yuvCount] = i;
+            ctx->listStats[dpy].yuvIndices[yuvCount] = (int)i;
             yuvCount++;
 
             if(UNLIKELY(is4kx2kYuvBuffer(hnd))){
                 int& yuv4k2kCount = ctx->listStats[dpy].yuv4k2kCount;
-                ctx->listStats[dpy].yuv4k2kIndices[yuv4k2kCount] = i;
+                ctx->listStats[dpy].yuv4k2kIndices[yuv4k2kCount] = (int)i;
                 yuv4k2kCount++;
             }
-
-            if((layer->transform & HWC_TRANSFORM_ROT_90) &&
-                    canUseRotator(ctx, dpy)) {
-                if( (dpy == HWC_DISPLAY_PRIMARY) &&
-                        ctx->mOverlay->isPipeTypeAttached(OV_MDP_PIPE_DMA)) {
-                    ctx->isPaddingRound = true;
-                }
-                Overlay::setDMAMode(Overlay::DMA_BLOCK_MODE);
-            }
         }
         if(layer->blending == HWC_BLENDING_PREMULT)
             ctx->listStats[dpy].preMultipliedAlpha = true;
 
 
         if(UNLIKELY(isExtOnly(hnd))){
-            ctx->listStats[dpy].extOnlyLayerIndex = i;
+            ctx->listStats[dpy].extOnlyLayerIndex = (int)i;
         }
     }
     if(ctx->listStats[dpy].yuvCount > 0) {
@@ -900,25 +898,6 @@
             }
         }
     }
-    if(dpy) {
-        //uncomment the below code for testing purpose.
-        /* char value[PROPERTY_VALUE_MAX];
-        property_get("sys.ext_orientation", value, "0");
-        // Assuming the orientation value is in terms of HAL_TRANSFORM,
-        // This needs mapping to HAL, if its in different convention
-        ctx->mExtOrientation = atoi(value); */
-        // Assuming the orientation value is in terms of HAL_TRANSFORM,
-        // This needs mapping to HAL, if its in different convention
-        if(ctx->mExtOrientation || ctx->mBufferMirrorMode) {
-            ALOGD_IF(HWC_UTILS_DEBUG, "%s: ext orientation = %d"
-                     "BufferMirrorMode = %d", __FUNCTION__,
-                     ctx->mExtOrientation, ctx->mBufferMirrorMode);
-            if(ctx->mOverlay->isPipeTypeAttached(OV_MDP_PIPE_DMA)) {
-                ctx->isPaddingRound = true;
-            }
-            Overlay::setDMAMode(Overlay::DMA_BLOCK_MODE);
-        }
-    }
 
     //The marking of video begin/end is useful on some targets where we need
     //to have a padding round to be able to shift pipes across mixers.
@@ -982,6 +961,32 @@
         return false;
 }
 
+bool isRotatorSupportedFormat(private_handle_t *hnd) {
+    // Following rotator src formats are supported by mdp driver
+    // TODO: Add more formats in future, if mdp driver adds support
+    switch(hnd->format) {
+        case HAL_PIXEL_FORMAT_RGBA_8888:
+        case HAL_PIXEL_FORMAT_RGB_565:
+        case HAL_PIXEL_FORMAT_RGB_888:
+        case HAL_PIXEL_FORMAT_BGRA_8888:
+            return true;
+        default:
+            return false;
+    }
+    return false;
+}
+
+bool isRotationDoable(hwc_context_t *ctx, private_handle_t *hnd) {
+    // Rotate layers, if it is YUV type or rendered by CPU and not
+    // for the MDP versions below MDP5
+    if((isCPURendered(hnd) && isRotatorSupportedFormat(hnd) &&
+        !ctx->mMDP.version < qdutils::MDSS_V5)
+                   || isYuvBuffer(hnd)) {
+        return true;
+    }
+    return false;
+}
+
 // returns true if Action safe dimensions are set and target supports Actionsafe
 bool isActionSafePresent(hwc_context_t *ctx, int dpy) {
     // if external supports underscan, do nothing
@@ -1081,11 +1086,39 @@
     return isValidRect(irect);
 }
 
+bool isSameRect(const hwc_rect& rect1, const hwc_rect& rect2)
+{
+   return ((rect1.left == rect2.left) && (rect1.top == rect2.top) &&
+           (rect1.right == rect2.right) && (rect1.bottom == rect2.bottom));
+}
+
 bool isValidRect(const hwc_rect& rect)
 {
    return ((rect.bottom > rect.top) && (rect.right > rect.left)) ;
 }
 
+bool operator ==(const hwc_rect_t& lhs, const hwc_rect_t& rhs) {
+    if(lhs.left == rhs.left && lhs.top == rhs.top &&
+       lhs.right == rhs.right &&  lhs.bottom == rhs.bottom )
+          return true ;
+    return false;
+}
+
+hwc_rect_t moveRect(const hwc_rect_t& rect, const int& x_off, const int& y_off)
+{
+    hwc_rect_t res;
+
+    if(!isValidRect(rect))
+        return (hwc_rect_t){0, 0, 0, 0};
+
+    res.left = rect.left + x_off;
+    res.top = rect.top + y_off;
+    res.right = rect.right + x_off;
+    res.bottom = rect.bottom + y_off;
+
+    return res;
+}
+
 /* computes the intersection of two rects */
 hwc_rect_t getIntersection(const hwc_rect_t& rect1, const hwc_rect_t& rect2)
 {
@@ -1150,7 +1183,7 @@
 }
 
 void optimizeLayerRects(const hwc_display_contents_1_t *list) {
-    int i=list->numHwLayers-2;
+    int i= (int)list->numHwLayers-2;
     while(i > 0) {
         //see if there is no blending required.
         //If it is opaque see if we can substract this region from below
@@ -1175,10 +1208,15 @@
                      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;
+                     layer->sourceCropf.left =(float)bottomCrop.left;
+                     layer->sourceCropf.top = (float)bottomCrop.top;
+                     layer->sourceCropf.right = (float)bottomCrop.right;
+                     layer->sourceCropf.bottom = (float)bottomCrop.bottom;
+#ifdef QCOM_BSP
+                     //Update layer dirtyRect
+                     layer->dirtyRect = getIntersection(bottomCrop,
+                                            layer->dirtyRect);
+#endif
                   }
                }
                j--;
@@ -1191,7 +1229,7 @@
 void getNonWormholeRegion(hwc_display_contents_1_t* list,
                               hwc_rect_t& nwr)
 {
-    uint32_t last = list->numHwLayers - 1;
+    size_t last = list->numHwLayers - 1;
     hwc_rect_t fbDisplayFrame = list->hwLayers[last].displayFrame;
     //Initiliaze nwr to first frame
     nwr.left =  list->hwLayers[0].displayFrame.left;
@@ -1199,7 +1237,7 @@
     nwr.right =  list->hwLayers[0].displayFrame.right;
     nwr.bottom =  list->hwLayers[0].displayFrame.bottom;
 
-    for (uint32_t i = 1; i < last; i++) {
+    for (size_t i = 1; i < last; i++) {
         hwc_rect_t displayFrame = list->hwLayers[i].displayFrame;
         nwr = getUnion(nwr, displayFrame);
     }
@@ -1273,11 +1311,15 @@
                 &currLayer->acquireFenceFd;
         rotData.rel_fen_fd = &rotReleaseFd; //driver to populate this
         rotData.session_id = currRot->getSessId();
+        if(currLayer->acquireFenceFd >= 0) {
+            rotData.acq_fen_fd_cnt = 1; //1 ioctl call per rot session
+        }
         int ret = 0;
         ret = ioctl(rotFd, MSMFB_BUFFER_SYNC, &rotData);
         if(ret < 0) {
             ALOGE("%s: ioctl MSMFB_BUFFER_SYNC failed for rot sync, err=%s",
                     __FUNCTION__, strerror(errno));
+            close(rotReleaseFd);
         } else {
             close(currLayer->acquireFenceFd);
             //For MDP to wait on.
@@ -1297,11 +1339,20 @@
     }
 
     for(uint32_t i = 0; i < list->numHwLayers; i++) {
-        if(list->hwLayers[i].compositionType == HWC_OVERLAY &&
+        if(((isAbcInUse(ctx)== true ) ||
+          (list->hwLayers[i].compositionType == HWC_OVERLAY)) &&
                         list->hwLayers[i].acquireFenceFd >= 0) {
             if(UNLIKELY(swapzero))
                 acquireFd[count++] = -1;
-            else
+            // if ABC is enabled for more than one layer.
+            // renderBufIndexforABC will work as FB.Hence
+            // set the acquireFD from fd - which is coming from copybit
+            else if(fd >= 0 && (isAbcInUse(ctx) == true)) {
+                if(ctx->listStats[dpy].renderBufIndexforABC ==(int32_t)i)
+                   acquireFd[count++] = fd;
+                else
+                   continue;
+            } else
                 acquireFd[count++] = list->hwLayers[i].acquireFenceFd;
         }
         if(list->hwLayers[i].compositionType == HWC_FRAMEBUFFER_TARGET) {
@@ -1318,28 +1369,36 @@
         }
     }
 
+    if ((fd >= 0) && !dpy && ctx->mPtorInfo.isActive()) {
+        // Acquire c2d fence of Overlap render buffer
+        acquireFd[count++] = fd;
+    }
+
     data.acq_fen_fd_cnt = count;
     fbFd = ctx->dpyAttr[dpy].fd;
 
     //Waits for acquire fences, returns a release fence
     if(LIKELY(!swapzero)) {
-        uint64_t start = systemTime();
         ret = ioctl(fbFd, MSMFB_BUFFER_SYNC, &data);
-        ALOGD_IF(HWC_UTILS_DEBUG, "%s: time taken for MSMFB_BUFFER_SYNC IOCTL = %d",
-                            __FUNCTION__, (size_t) ns2ms(systemTime() - start));
     }
 
     if(ret < 0) {
         ALOGE("%s: ioctl MSMFB_BUFFER_SYNC failed, err=%s",
                   __FUNCTION__, strerror(errno));
-        ALOGE("%s: acq_fen_fd_cnt=%d flags=%d fd=%d dpy=%d numHwLayers=%d",
+        ALOGE("%s: acq_fen_fd_cnt=%d flags=%d fd=%d dpy=%d numHwLayers=%zu",
               __FUNCTION__, data.acq_fen_fd_cnt, data.flags, fbFd,
               dpy, list->numHwLayers);
+        close(releaseFd);
+        releaseFd = -1;
+        close(retireFd);
+        retireFd = -1;
     }
 
-    LayerProp *layerProp = ctx->layerProp[dpy];
     for(uint32_t i = 0; i < list->numHwLayers; i++) {
         if(list->hwLayers[i].compositionType == HWC_OVERLAY ||
+#ifdef QCOM_BSP
+           list->hwLayers[i].compositionType == HWC_BLIT ||
+#endif
            list->hwLayers[i].compositionType == HWC_FRAMEBUFFER_TARGET) {
             //Populate releaseFenceFds.
             if(UNLIKELY(swapzero)) {
@@ -1349,8 +1408,24 @@
                 // if animation is in progress.
                 list->hwLayers[i].releaseFenceFd = -1;
             } else if(list->hwLayers[i].releaseFenceFd < 0 ) {
+#ifdef QCOM_BSP
                 //If rotator has not already populated this field
-                list->hwLayers[i].releaseFenceFd = dup(releaseFd);
+                // & if it's a not VPU layer
+
+                // if ABC is enabled for more than one layer
+                if(fd >= 0 && (isAbcInUse(ctx) == true) &&
+                  ctx->listStats[dpy].renderBufIndexforABC !=(int32_t)i){
+                    list->hwLayers[i].releaseFenceFd = dup(fd);
+                } else if((list->hwLayers[i].compositionType == HWC_BLIT)&&
+                                               (isAbcInUse(ctx) == false)){
+                    //For Blit, the app layers should be released when the Blit
+                    //is complete. This fd was passed from copybit->draw
+                    list->hwLayers[i].releaseFenceFd = dup(fd);
+                } else
+#endif
+                {
+                    list->hwLayers[i].releaseFenceFd = dup(releaseFd);
+                }
             }
         }
     }
@@ -1360,8 +1435,12 @@
         fd = -1;
     }
 
-    if (ctx->mCopyBit[dpy])
-        ctx->mCopyBit[dpy]->setReleaseFd(releaseFd);
+    if (!dpy && ctx->mCopyBit[dpy]) {
+        if (ctx->mPtorInfo.isActive())
+            ctx->mCopyBit[dpy]->setReleaseFdSync(releaseFd);
+        else
+            ctx->mCopyBit[dpy]->setReleaseFd(releaseFd);
+    }
 
     //Signals when MDP finishes reading rotator buffers.
     ctx->mLayerRotMap[dpy]->setReleaseFd(releaseFd);
@@ -1376,7 +1455,7 @@
     return ret;
 }
 
-void setMdpFlags(hwc_layer_1_t *layer,
+void setMdpFlags(hwc_context_t *ctx, hwc_layer_1_t *layer,
         ovutils::eMdpFlags &mdpFlags,
         int rotDownscale, int transform) {
     private_handle_t *hnd = (private_handle_t *)layer->handle;
@@ -1397,11 +1476,6 @@
             ovutils::setMdpFlags(mdpFlags,
                     ovutils::OV_MDP_DEINTERLACE);
         }
-        //Pre-rotation will be used using rotator.
-        if(transform & HWC_TRANSFORM_ROT_90) {
-            ovutils::setMdpFlags(mdpFlags,
-                    ovutils::OV_MDP_SOURCE_ROTATED_90);
-        }
     }
 
     if(isSecureDisplayBuffer(hnd)) {
@@ -1411,6 +1485,12 @@
         ovutils::setMdpFlags(mdpFlags,
                              ovutils::OV_MDP_SECURE_DISPLAY_OVERLAY_SESSION);
     }
+
+    //Pre-rotation will be used using rotator.
+    if(has90Transform(layer) && isRotationDoable(ctx, hnd)) {
+        ovutils::setMdpFlags(mdpFlags,
+                ovutils::OV_MDP_SOURCE_ROTATED_90);
+    }
     //No 90 component and no rot-downscale then flips done by MDP
     //If we use rot then it might as well do flips
     if(!(transform & HWC_TRANSFORM_ROT_90) && !rotDownscale) {
@@ -1445,18 +1525,8 @@
 
     if (qdutils::MDPVersion::getInstance().getMDPVersion() >=
         qdutils::MDSS_V5) {
-        uint32_t crop_w = (crop.right - crop.left);
-        uint32_t crop_h = (crop.bottom - crop.top);
-        if (ovutils::isYuv(whf.format)) {
-            ovutils::normalizeCrop((uint32_t&)crop.left, crop_w);
-            ovutils::normalizeCrop((uint32_t&)crop.top, crop_h);
-            // For interlaced, crop.h should be 4-aligned
-            if ((mdpFlags & ovutils::OV_MDP_DEINTERLACE) && (crop_h % 4))
-                crop_h = ovutils::aligndown(crop_h, 4);
-            crop.right = crop.left + crop_w;
-            crop.bottom = crop.top + crop_h;
-        }
-        Dim rotCrop(crop.left, crop.top, crop_w, crop_h);
+         Dim rotCrop(crop.left, crop.top, crop.right - crop.left,
+                crop.bottom - crop.top);
         rot->setCrop(rotCrop);
     }
 
@@ -1531,28 +1601,27 @@
 }
 
 void updateSource(eTransform& orient, Whf& whf,
-        hwc_rect_t& crop) {
-    Dim srcCrop(crop.left, crop.top,
+        hwc_rect_t& crop, Rotator *rot) {
+    Dim transformedCrop(crop.left, crop.top,
             crop.right - crop.left,
             crop.bottom - crop.top);
-    orient = static_cast<eTransform>(ovutils::getMdpOrient(orient));
-    preRotateSource(orient, whf, srcCrop);
     if (qdutils::MDPVersion::getInstance().getMDPVersion() >=
         qdutils::MDSS_V5) {
-        // Source for overlay will be the cropped (and rotated)
-        crop.left = 0;
-        crop.top = 0;
-        crop.right = srcCrop.w;
-        crop.bottom = srcCrop.h;
-        // Set width & height equal to sourceCrop w & h
-        whf.w = srcCrop.w;
-        whf.h = srcCrop.h;
+        //B-family rotator internally could modify destination dimensions if
+        //downscaling is supported
+        whf = rot->getDstWhf();
+        transformedCrop = rot->getDstDimensions();
     } else {
-        crop.left = srcCrop.x;
-        crop.top = srcCrop.y;
-        crop.right = srcCrop.x + srcCrop.w;
-        crop.bottom = srcCrop.y + srcCrop.h;
+        //A-family rotator rotates entire buffer irrespective of crop, forcing
+        //us to recompute the crop based on transform
+        orient = static_cast<eTransform>(ovutils::getMdpOrient(orient));
+        preRotateSource(orient, whf, transformedCrop);
     }
+
+    crop.left = transformedCrop.x;
+    crop.top = transformedCrop.y;
+    crop.right = transformedCrop.x + transformedCrop.w;
+    crop.bottom = transformedCrop.y + transformedCrop.h;
 }
 
 int configureNonSplit(hwc_context_t *ctx, hwc_layer_1_t *layer,
@@ -1579,7 +1648,7 @@
     int downscale = 0;
     int rotFlags = ovutils::ROT_FLAGS_NONE;
     uint32_t format = ovutils::getMdpFormat(hnd->format, isTileRendered(hnd));
-    Whf whf(getWidth(hnd), getHeight(hnd), format, hnd->size);
+    Whf whf(getWidth(hnd), getHeight(hnd), format, (uint32_t)hnd->size);
 
     // Handle R/B swap
     if (layer->flags & HWC_FORMAT_RB_SWAP) {
@@ -1603,22 +1672,22 @@
         }
     }
 
-    setMdpFlags(layer, mdpFlags, downscale, transform);
+    setMdpFlags(ctx, layer, mdpFlags, downscale, transform);
 
-    if(isYuvBuffer(hnd) && //if 90 component or downscale, use rot
-            ((transform & HWC_TRANSFORM_ROT_90) || downscale)) {
+    //if 90 component or downscale, use rot
+    if((has90Transform(layer) && isRotationDoable(ctx, hnd)) || downscale) {
         *rot = ctx->mRotMgr->getNext();
         if(*rot == NULL) return -1;
-        if(!dpy)
+        ctx->mLayerRotMap[dpy]->add(layer, *rot);
+        // BWC is not tested for other formats So enable it only for YUV format
+        if(!dpy && isYuvBuffer(hnd))
             BwcPM::setBwc(crop, dst, transform, mdpFlags);
         //Configure rotator for pre-rotation
         if(configRotator(*rot, whf, crop, mdpFlags, orient, downscale) < 0) {
             ALOGE("%s: configRotator failed!", __FUNCTION__);
             return -1;
         }
-        ctx->mLayerRotMap[dpy]->add(layer, *rot);
-        whf.format = (*rot)->getDstFormat();
-        updateSource(orient, whf, crop);
+        updateSource(orient, whf, crop, *rot);
         rotFlags |= ovutils::ROT_PREROTATED;
     }
 
@@ -1686,7 +1755,7 @@
     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);
+    Whf whf(getWidth(hnd), getHeight(hnd), format, (uint32_t)hnd->size);
 
     // Handle R/B swap
     if (layer->flags & HWC_FORMAT_RB_SWAP) {
@@ -1700,7 +1769,7 @@
        ActionSafe, and extorientation features. */
     calcExtDisplayPosition(ctx, hnd, dpy, crop, dst, transform, orient);
 
-    setMdpFlags(layer, mdpFlagsL, 0, transform);
+    setMdpFlags(ctx, layer, mdpFlagsL, 0, transform);
 
     if(lDest != OV_INVALID && rDest != OV_INVALID) {
         //Enable overfetch
@@ -1714,17 +1783,16 @@
         whf.format = wb->getOutputFormat();
     }
 
-    if(isYuvBuffer(hnd) && (transform & HWC_TRANSFORM_ROT_90)) {
+    if(has90Transform(layer) && isRotationDoable(ctx, hnd)) {
         (*rot) = ctx->mRotMgr->getNext();
         if((*rot) == NULL) return -1;
+        ctx->mLayerRotMap[dpy]->add(layer, *rot);
         //Configure rotator for pre-rotation
         if(configRotator(*rot, whf, crop, mdpFlagsL, orient, downscale) < 0) {
             ALOGE("%s: configRotator failed!", __FUNCTION__);
             return -1;
         }
-        ctx->mLayerRotMap[dpy]->add(layer, *rot);
-        whf.format = (*rot)->getDstFormat();
-        updateSource(orient, whf, crop);
+        updateSource(orient, whf, crop, *rot);
         rotFlags |= ROT_PREROTATED;
     }
 
@@ -1736,14 +1804,17 @@
 
     const int lSplit = getLeftSplit(ctx, dpy);
 
-    if(lDest != OV_INVALID) {
+    // Calculate Left rects
+    if(dst.left < lSplit) {
         tmp_cropL = crop;
         tmp_dstL = dst;
         hwc_rect_t scissor = {0, 0, lSplit, hw_h };
         scissor = getIntersection(ctx->mViewFrame[dpy], scissor);
         qhwc::calculate_crop_rects(tmp_cropL, tmp_dstL, scissor, 0);
     }
-    if(rDest != OV_INVALID) {
+
+    // Calculate Right rects
+    if(dst.right > lSplit) {
         tmp_cropR = crop;
         tmp_dstR = dst;
         hwc_rect_t scissor = {lSplit, 0, hw_w, hw_h };
@@ -1756,8 +1827,8 @@
     //When buffer is H-flipped, contents of mixer config also needs to swapped
     //Not needed if the layer is confined to one half of the screen.
     //If rotator has been used then it has also done the flips, so ignore them.
-    if((orient & OVERLAY_TRANSFORM_FLIP_H) && lDest != OV_INVALID
-            && rDest != OV_INVALID && (*rot) == NULL) {
+    if((orient & OVERLAY_TRANSFORM_FLIP_H) && (dst.left < lSplit) &&
+            (dst.right > lSplit) && (*rot) == NULL) {
         hwc_rect_t new_cropR;
         new_cropR.left = tmp_cropL.left;
         new_cropR.right = new_cropR.left + (tmp_cropR.right - tmp_cropR.left);
@@ -1833,28 +1904,28 @@
     eZorder rz = (eZorder)(z + 1);
 
     Whf whf(getWidth(hnd), getHeight(hnd),
-            getMdpFormat(hnd->format), hnd->size);
+            getMdpFormat(hnd->format), (uint32_t)hnd->size);
 
     /* Calculate the external display position based on MDP downscale,
        ActionSafe, and extorientation features. */
     calcExtDisplayPosition(ctx, hnd, dpy, crop, dst, transform, orient);
 
-    setMdpFlags(layer, mdpFlagsL, 0, transform);
+    setMdpFlags(ctx, layer, mdpFlagsL, 0, transform);
     trimLayer(ctx, dpy, transform, crop, dst);
 
-    if(isYuvBuffer(hnd) && (transform & HWC_TRANSFORM_ROT_90)) {
+    if(has90Transform(layer) && isRotationDoable(ctx, hnd)) {
         (*rot) = ctx->mRotMgr->getNext();
         if((*rot) == NULL) return -1;
-        if(!dpy)
+        ctx->mLayerRotMap[dpy]->add(layer, *rot);
+        // BWC is not tested for other formats So enable it only for YUV format
+        if(!dpy && isYuvBuffer(hnd))
             BwcPM::setBwc(crop, dst, transform, mdpFlagsL);
         //Configure rotator for pre-rotation
         if(configRotator(*rot, whf, crop, mdpFlagsL, orient, downscale) < 0) {
             ALOGE("%s: configRotator failed!", __FUNCTION__);
             return -1;
         }
-        ctx->mLayerRotMap[dpy]->add(layer, *rot);
-        whf.format = (*rot)->getDstFormat();
-        updateSource(orient, whf, crop);
+        updateSource(orient, whf, crop, *rot);
         rotFlags |= ROT_PREROTATED;
     }
 
@@ -1934,10 +2005,10 @@
 }
 
 bool canUseRotator(hwc_context_t *ctx, int dpy) {
-    if(qdutils::MDPVersion::getInstance().is8x26() &&
+    if(ctx->mOverlay->isDMAMultiplexingSupported() &&
             isSecondaryConnected(ctx) &&
             !ctx->dpyAttr[HWC_DISPLAY_VIRTUAL].isPause) {
-        /* 8x26 mdss driver supports multiplexing of DMA pipe
+        /* mdss driver on certain targets support multiplexing of DMA pipe
          * in LINE and BLOCK modes for writeback panels.
          */
         if(dpy == HWC_DISPLAY_PRIMARY)
@@ -1980,30 +2051,26 @@
     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) {
+bool isAbcInUse(hwc_context_t *ctx){
+  return (ctx->enableABC && ctx->listStats[0].renderBufIndexforABC == 0);
+}
 
-    /* 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;
+void dumpBuffer(private_handle_t *ohnd, char *bufferName) {
+    if (ohnd != NULL && ohnd->base) {
+        char dumpFilename[PATH_MAX];
+        bool bResult = false;
+        snprintf(dumpFilename, sizeof(dumpFilename), "/data/%s.%s.%dx%d.raw",
+            bufferName,
+            overlay::utils::getFormatString(utils::getMdpFormat(ohnd->format)),
+            getWidth(ohnd), getHeight(ohnd));
+        FILE* fp = fopen(dumpFilename, "w+");
+        if (NULL != fp) {
+            bResult = (bool) fwrite((void*)ohnd->base, ohnd->size, 1, fp);
+            fclose(fp);
+        }
+        ALOGD("Buffer[%s] Dump to %s: %s",
+        bufferName, dumpFilename, bResult ? "Success" : "Fail");
     }
-
-    return true;
 }
 
 bool isGLESComp(hwc_context_t *ctx,
@@ -2040,7 +2107,8 @@
         }
     }
     if(isGLESComp(ctx, list)) {
-        if(!gpuHint->mPrevCompositionGLES && !MDPComp::isIdleFallback()) {
+        if(gpuHint->mCompositionState != COMPOSITION_STATE_GPU
+            && !MDPComp::isIdleFallback()) {
             EGLint attr_list[] = {EGL_GPU_HINT_1,
                                   EGL_GPU_LEVEL_3,
                                   EGL_NONE };
@@ -2050,7 +2118,7 @@
                 ALOGW("eglGpuPerfHintQCOM failed for Built in display");
             } else {
                 gpuHint->mCurrGPUPerfMode = EGL_GPU_LEVEL_3;
-                gpuHint->mPrevCompositionGLES = true;
+                gpuHint->mCompositionState = COMPOSITION_STATE_GPU;
             }
         } else {
             EGLint attr_list[] = {EGL_GPU_HINT_1,
@@ -2063,6 +2131,9 @@
             } else {
                 gpuHint->mCurrGPUPerfMode = EGL_GPU_LEVEL_0;
             }
+            if(MDPComp::isIdleFallback()) {
+                gpuHint->mCompositionState = COMPOSITION_STATE_IDLE_FALLBACK;
+            }
         }
     } else {
         /* set the GPU hint flag to default for MDP composition */
@@ -2076,11 +2147,25 @@
         } else {
             gpuHint->mCurrGPUPerfMode = EGL_GPU_LEVEL_0;
         }
-        gpuHint->mPrevCompositionGLES = false;
+        gpuHint->mCompositionState = COMPOSITION_STATE_MDP;
     }
 #endif
 }
 
+bool isPeripheral(const hwc_rect_t& rect1, const hwc_rect_t& rect2) {
+    // To be peripheral, 3 boundaries should match.
+    uint8_t eqBounds = 0;
+    if (rect1.left == rect2.left)
+        eqBounds++;
+    if (rect1.top == rect2.top)
+        eqBounds++;
+    if (rect1.right == rect2.right)
+        eqBounds++;
+    if (rect1.bottom == rect2.bottom)
+        eqBounds++;
+    return (eqBounds == 3);
+}
+
 void BwcPM::setBwc(const hwc_rect_t& crop,
             const hwc_rect_t& dst, const int& transform,
             ovutils::eMdpFlags& mdpFlags) {
@@ -2088,30 +2173,23 @@
     if(!qdutils::MDPVersion::getInstance().supportsBWC()) {
         return;
     }
+    int src_w = crop.right - crop.left;
+    int src_h = crop.bottom - crop.top;
+    int dst_w = dst.right - dst.left;
+    int dst_h = dst.bottom - dst.top;
+    if(transform & HAL_TRANSFORM_ROT_90) {
+        swap(src_w, src_h);
+    }
     //src width > MAX mixer supported dim
-    if((crop.right - crop.left) > qdutils::MAX_DISPLAY_DIM) {
+    if(src_w > qdutils::MAX_DISPLAY_DIM) {
         return;
     }
     //Decimation necessary, cannot use BWC. H/W requirement.
     if(qdutils::MDPVersion::getInstance().supportsDecimation()) {
-        int src_w = crop.right - crop.left;
-        int src_h = crop.bottom - crop.top;
-        int dst_w = dst.right - dst.left;
-        int dst_h = dst.bottom - dst.top;
-        if(transform & HAL_TRANSFORM_ROT_90) {
-            swap(src_w, src_h);
-        }
-        float horDscale = 0.0f;
-        float verDscale = 0.0f;
-        int horzDeci = 0;
-        int vertDeci = 0;
-        ovutils::getDecimationFactor(src_w, src_h, dst_w, dst_h, horDscale,
-                verDscale);
-        //TODO Use log2f once math.h has it
-        if((int)horDscale)
-            horzDeci = (int)(log(horDscale) / log(2));
-        if((int)verDscale)
-            vertDeci = (int)(log(verDscale) / log(2));
+        uint8_t horzDeci = 0;
+        uint8_t vertDeci = 0;
+        ovutils::getDecimationFactor(src_w, src_h, dst_w, dst_h, horzDeci,
+                vertDeci);
         if(horzDeci || vertDeci) return;
     }
     //Property
@@ -2148,4 +2226,88 @@
     }
 }
 
+void resetROI(hwc_context_t *ctx, const int dpy) {
+    const int fbXRes = (int)ctx->dpyAttr[dpy].xres;
+    const int fbYRes = (int)ctx->dpyAttr[dpy].yres;
+    if(isDisplaySplit(ctx, dpy)) {
+        const int lSplit = getLeftSplit(ctx, dpy);
+        ctx->listStats[dpy].lRoi = (struct hwc_rect){0, 0, lSplit, fbYRes};
+        ctx->listStats[dpy].rRoi = (struct hwc_rect){lSplit, 0, fbXRes, fbYRes};
+    } else  {
+        ctx->listStats[dpy].lRoi = (struct hwc_rect){0, 0,fbXRes, fbYRes};
+        ctx->listStats[dpy].rRoi = (struct hwc_rect){0, 0, 0, 0};
+    }
+}
+
+hwc_rect_t getSanitizeROI(struct hwc_rect roi, hwc_rect boundary)
+{
+   if(!isValidRect(roi))
+      return roi;
+
+   struct hwc_rect t_roi = roi;
+
+   const int LEFT_ALIGN = qdutils::MDPVersion::getInstance().getLeftAlign();
+   const int WIDTH_ALIGN = qdutils::MDPVersion::getInstance().getWidthAlign();
+   const int TOP_ALIGN = qdutils::MDPVersion::getInstance().getTopAlign();
+   const int HEIGHT_ALIGN = qdutils::MDPVersion::getInstance().getHeightAlign();
+   const int MIN_WIDTH = qdutils::MDPVersion::getInstance().getMinROIWidth();
+   const int MIN_HEIGHT = qdutils::MDPVersion::getInstance().getMinROIHeight();
+
+   /* Align to minimum width recommended by the panel */
+   if((t_roi.right - t_roi.left) < MIN_WIDTH) {
+       if((t_roi.left + MIN_WIDTH) > boundary.right)
+           t_roi.left = t_roi.right - MIN_WIDTH;
+       else
+           t_roi.right = t_roi.left + MIN_WIDTH;
+   }
+
+  /* Align to minimum height recommended by the panel */
+   if((t_roi.bottom - t_roi.top) < MIN_HEIGHT) {
+       if((t_roi.top + MIN_HEIGHT) > boundary.bottom)
+           t_roi.top = t_roi.bottom - MIN_HEIGHT;
+       else
+           t_roi.bottom = t_roi.top + MIN_HEIGHT;
+   }
+
+   /* Align left and width to meet panel restrictions */
+   if(LEFT_ALIGN)
+       t_roi.left = t_roi.left - (t_roi.left % LEFT_ALIGN);
+
+   if(WIDTH_ALIGN) {
+       int width = t_roi.right - t_roi.left;
+       width = WIDTH_ALIGN * ((width + (WIDTH_ALIGN - 1)) / WIDTH_ALIGN);
+       t_roi.right = t_roi.left + width;
+
+       if(t_roi.right > boundary.right) {
+           t_roi.right = boundary.right;
+           t_roi.left = t_roi.right - width;
+
+           if(LEFT_ALIGN)
+               t_roi.left = t_roi.left - (t_roi.left % LEFT_ALIGN);
+       }
+   }
+
+
+   /* Align top and height to meet panel restrictions */
+   if(TOP_ALIGN)
+       t_roi.top = t_roi.top - (t_roi.top % TOP_ALIGN);
+
+   if(HEIGHT_ALIGN) {
+       int height = t_roi.bottom - t_roi.top;
+       height = HEIGHT_ALIGN *  ((height + (HEIGHT_ALIGN - 1)) / HEIGHT_ALIGN);
+       t_roi.bottom = t_roi.top  + height;
+
+       if(t_roi.bottom > boundary.bottom) {
+           t_roi.bottom = boundary.bottom;
+           t_roi.top = t_roi.bottom - height;
+
+           if(TOP_ALIGN)
+               t_roi.top = t_roi.top - (t_roi.top % TOP_ALIGN);
+       }
+   }
+
+
+   return t_roi;
+}
+
 };//namespace qhwc
diff --git a/msm8226/libhwcomposer/hwc_utils.h b/msm8226/libhwcomposer/hwc_utils.h
index ad023ad..dd55f8b 100644
--- a/msm8226/libhwcomposer/hwc_utils.h
+++ b/msm8226/libhwcomposer/hwc_utils.h
@@ -39,6 +39,10 @@
 #define MAX_NUM_APP_LAYERS 32
 #define MIN_DISPLAY_XRES 200
 #define MIN_DISPLAY_YRES 200
+#define HWC_WFDDISPSYNC_LOG 0
+#define STR(f) #f;
+// Max number of PTOR layers handled
+#define MAX_PTOR_LAYERS 2
 
 //Fwrd decls
 struct hwc_context_t;
@@ -102,8 +106,8 @@
     //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;
+    uint32_t xres_new;
+    uint32_t yres_new;
 
 };
 
@@ -121,9 +125,29 @@
     // Notifies hwcomposer about the start and end of animation
     // This will be set to true during animation, otherwise false.
     bool isDisplayAnimating;
-    ovutils::Dim roi;
     bool secureUI; // Secure display layer
     bool isSecurePresent;
+    hwc_rect_t lRoi;  //left ROI
+    hwc_rect_t rRoi;  //right ROI. Unused in single DSI panels.
+    //App Buffer Composition index
+    int  renderBufIndexforABC;
+};
+
+//PTOR Comp info
+struct PtorInfo {
+    int count;
+    int layerIndex[MAX_PTOR_LAYERS];
+    int mRenderBuffOffset[MAX_PTOR_LAYERS];
+    hwc_rect_t displayFrame[MAX_PTOR_LAYERS];
+    bool isActive() { return (count>0); }
+    int getPTORArrayIndex(int index) {
+        int idx = -1;
+        for(int i = 0; i < count; i++) {
+            if(index == layerIndex[i])
+                idx = i;
+        }
+        return idx;
+    }
 };
 
 struct LayerProp {
@@ -134,6 +158,7 @@
 struct VsyncState {
     bool enable;
     bool fakevsync;
+    bool debug;
 };
 
 struct BwcPM {
@@ -154,6 +179,15 @@
     HWC_FORMAT_RB_SWAP = 0x00000040,
 };
 
+/* External Display states */
+enum {
+    EXTERNAL_OFFLINE = 0,
+    EXTERNAL_ONLINE,
+    EXTERNAL_PAUSE,
+    EXTERNAL_RESUME,
+    EXTERNAL_MAXSTATES
+};
+
 class LayerRotMap {
 public:
     LayerRotMap() { reset(); }
@@ -189,7 +223,7 @@
 }
 
 inline hwc_rect_t integerizeSourceCrop(const hwc_frect_t& cropF) {
-    hwc_rect_t cropI = {0};
+    hwc_rect_t cropI = {0,0,0,0};
     cropI.left = int(ceilf(cropF.left));
     cropI.top = int(ceilf(cropF.top));
     cropI.right = int(floorf(cropF.right));
@@ -210,11 +244,6 @@
 // -----------------------------------------------------------------------------
 // Utility functions - implemented in hwc_utils.cpp
 void dumpLayer(hwc_layer_1_t const* l);
-
-// Calculate viewframe for external/primary display from primary resolution and
-// primary device orientation
-hwc_rect_t calculateDisplayViewFrame(hwc_context_t *ctx, int dpy);
-
 void setListStats(hwc_context_t *ctx, hwc_display_contents_1_t *list,
         int dpy);
 void initContext(hwc_context_t *ctx);
@@ -226,6 +255,10 @@
                               hwc_rect_t& nwr);
 bool isSecuring(hwc_context_t* ctx, hwc_layer_1_t const* layer);
 bool isSecureModePolicy(int mdpVersion);
+// Returns true, if the input layer format is supported by rotator
+bool isRotatorSupportedFormat(private_handle_t *hnd);
+//Returns true, if the layer is YUV or the layer has been rendered by CPU
+bool isRotationDoable(hwc_context_t *ctx, private_handle_t *hnd);
 bool isExternalActive(hwc_context_t* ctx);
 bool isAlphaScaled(hwc_layer_1_t const* layer);
 bool needsScaling(hwc_layer_1_t const* layer);
@@ -239,9 +272,9 @@
 int getBlending(int blending);
 bool isGLESOnlyComp(hwc_context_t *ctx, const int& dpy);
 void reset_layer_prop(hwc_context_t* ctx, int dpy, int numAppLayers);
+bool isAbcInUse(hwc_context_t *ctx);
 
-bool canUseMDPforVirtualDisplay(hwc_context_t* ctx,
-                                const hwc_display_contents_1_t *list);
+void dumpBuffer(private_handle_t *ohnd, char *bufferName);
 
 //Helper function to dump logs
 void dumpsys_log(android::String8& buf, const char* fmt, ...);
@@ -249,11 +282,14 @@
 int getExtOrientation(hwc_context_t* ctx);
 bool isValidRect(const hwc_rect_t& rect);
 hwc_rect_t deductRect(const hwc_rect_t& rect1, const hwc_rect_t& rect2);
+bool isSameRect(const hwc_rect& rect1, const hwc_rect& rect2);
+hwc_rect_t moveRect(const hwc_rect_t& rect, const int& x_off, const int& y_off);
 hwc_rect_t getIntersection(const hwc_rect_t& rect1, const hwc_rect_t& rect2);
 hwc_rect_t getUnion(const hwc_rect_t& rect1, const hwc_rect_t& rect2);
 void optimizeLayerRects(const hwc_display_contents_1_t *list);
 bool areLayersIntersecting(const hwc_layer_1_t* layer1,
         const hwc_layer_1_t* layer2);
+bool operator ==(const hwc_rect_t& lhs, const hwc_rect_t& rhs);
 
 // returns true if Action safe dimensions are set and target supports Actionsafe
 bool isActionSafePresent(hwc_context_t *ctx, int dpy);
@@ -280,6 +316,15 @@
 // BufferMirrirMode(Sidesync)
 int getMirrorModeOrientation(hwc_context_t *ctx);
 
+/* Get External State names */
+const char* getExternalDisplayState(uint32_t external_state);
+
+// Resets display ROI to full panel resoluion
+void resetROI(hwc_context_t *ctx, const int dpy);
+
+// Aligns updating ROI to panel restrictions
+hwc_rect_t getSanitizeROI(struct hwc_rect roi, hwc_rect boundary);
+
 // Handles wfd Pause and resume events
 void handle_pause(hwc_context_t *ctx, int dpy);
 void handle_resume(hwc_context_t *ctx, int dpy);
@@ -292,7 +337,7 @@
         int fd);
 
 //Sets appropriate mdp flags for a layer.
-void setMdpFlags(hwc_layer_1_t *layer,
+void setMdpFlags(hwc_context_t *ctx, hwc_layer_1_t *layer,
         ovutils::eMdpFlags &mdpFlags,
         int rotDownscale, int transform);
 
@@ -310,7 +355,7 @@
         ovutils::eIsFg& isFg, const ovutils::eDest& dest);
 
 void updateSource(ovutils::eTransform& orient, ovutils::Whf& whf,
-        hwc_rect_t& crop);
+        hwc_rect_t& crop, overlay::Rotator *rot);
 
 //Routine to configure low resolution panels (<= 2048 width)
 int configureNonSplit(hwc_context_t *ctx, hwc_layer_1_t *layer, const int& dpy,
@@ -349,6 +394,9 @@
 // due to idle fallback or MDP composition.
 void setGPUHint(hwc_context_t* ctx, hwc_display_contents_1_t* list);
 
+// Returns true if rect1 is peripheral to rect2, false otherwise.
+bool isPeripheral(const hwc_rect_t& rect1, const hwc_rect_t& rect2);
+
 // Inline utility functions
 static inline bool isSkipLayer(const hwc_layer_1_t* l) {
     return (UNLIKELY(l && (l->flags & HWC_SKIP_LAYER)));
@@ -374,6 +422,10 @@
     return (hnd && (private_handle_t::PRIV_FLAGS_TILE_RENDERED & hnd->flags));
 }
 
+static inline bool isCPURendered(const private_handle_t* hnd) {
+    return (hnd && (private_handle_t::PRIV_FLAGS_CPU_RENDERED & hnd->flags));
+}
+
 //Return true if buffer is marked locked
 static inline bool isBufferLocked(const private_handle_t* hnd) {
     return (hnd && (private_handle_t::PRIV_FLAGS_HWC_LOCK & hnd->flags));
@@ -447,14 +499,20 @@
     ANIMATION_STARTED,
 };
 
+enum eCompositionState {
+    COMPOSITION_STATE_MDP = 0,        // Set if composition type is MDP
+    COMPOSITION_STATE_GPU,            // Set if composition type is GPU or MIXED
+    COMPOSITION_STATE_IDLE_FALLBACK,  // Set if it is idlefallback
+};
+
 // Structure holds the information about the GPU hint.
 struct gpu_hint_info {
     // system level flag to enable gpu_perf_mode
     bool mGpuPerfModeEnable;
     // Stores the current GPU performance mode DEFAULT/HIGH
     bool mCurrGPUPerfMode;
-    // true if previous composition used GPU
-    bool mPrevCompositionGLES;
+    // Stores the compositon state GPU, MDP or IDLE_FALLBACK
+    bool mCompositionState;
     // Stores the EGLContext of current process
     EGLContext mEGLContext;
     // Stores the EGLDisplay of current process
@@ -516,15 +574,26 @@
     //Used for SideSync feature
     //which overrides the mExtOrientation
     bool mBufferMirrorMode;
+    // Used to synchronize between WFD and Display modules
+    mutable Locker mWfdSyncLock;
+
     qhwc::LayerRotMap *mLayerRotMap[HWC_NUM_DISPLAY_TYPES];
     // Panel reset flag will be set if BTA check fails
     bool mPanelResetStatus;
     // number of active Displays
     int numActiveDisplays;
-    // Downscale feature switch, set via system the property
+    // Downscale feature switch, set via system property
     // sys.hwc.mdp_downscale_enabled
     bool mMDPDownscaleEnabled;
+    // Is WFD enabled through VDS solution ?
+    // This can be set via system property
+    // persist.hwc.enable_vds
+    bool mVDSEnabled;
     struct gpu_hint_info mGPUHintInfo;
+    //App Buffer Composition
+    bool enableABC;
+    // PTOR Info
+    qhwc::PtorInfo mPtorInfo;
 };
 
 namespace qhwc {
@@ -536,7 +605,7 @@
     return  ctx->listStats[dpy].yuvCount;
 }
 
-static inline bool has90Transform(hwc_layer_1_t *layer) {
+static inline bool has90Transform(hwc_layer_1_t const* layer) {
     return ((layer->transform & HWC_TRANSFORM_ROT_90) &&
             !(layer->flags & HWC_COLOR_FILL));
 }
diff --git a/msm8226/libhwcomposer/hwc_virtual.cpp b/msm8226/libhwcomposer/hwc_virtual.cpp
index cc29d45..f8f3b45 100644
--- a/msm8226/libhwcomposer/hwc_virtual.cpp
+++ b/msm8226/libhwcomposer/hwc_virtual.cpp
@@ -29,25 +29,34 @@
 #include "hwc_dump_layers.h"
 #include "hwc_copybit.h"
 #include "hwc_virtual.h"
+#include "sync/sync.h"
 
 #define HWCVIRTUAL_LOG 0
 
 using namespace qhwc;
 using namespace overlay;
 
-HWCVirtualBase* HWCVirtualBase::getObject() {
-    char property[PROPERTY_VALUE_MAX];
+HWCVirtualBase* HWCVirtualBase::getObject(bool isVDSEnabled) {
 
-    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();
+    if(isVDSEnabled) {
+        ALOGD_IF(HWCVIRTUAL_LOG, "%s: VDS is enabled for Virtual display",
+                 __FUNCTION__);
+        return new HWCVirtualVDS();
+    } else {
+        ALOGD_IF(HWCVIRTUAL_LOG, "%s: V4L2 is enabled for Virtual display",
+                 __FUNCTION__);
+        return new HWCVirtualV4L2();
+    }
+}
+
+HWCVirtualVDS::HWCVirtualVDS() {
+    char value[PROPERTY_VALUE_MAX];
+    mVDSDumpEnabled = false;
+    if((property_get("debug.hwc.enable_vds_dump", value, NULL) > 0)) {
+        if(atoi(value) != 0) {
+            mVDSDumpEnabled = true;
         }
     }
-    ALOGD_IF(HWCVIRTUAL_LOG, "%s: V4L2 is enabled for Virtual display",
-            __FUNCTION__);
-    return new HWCVirtualV4L2();
 }
 
 void HWCVirtualVDS::init(hwc_context_t *ctx) {
@@ -69,6 +78,7 @@
     //Cleanup virtual display objs, since there is no explicit disconnect
     if(ctx->dpyAttr[dpy].connected && (displays[dpy] == NULL)) {
         ctx->dpyAttr[dpy].connected = false;
+        ctx->dpyAttr[dpy].isPause = false;
 
         if(ctx->mFBUpdate[dpy]) {
             delete ctx->mFBUpdate[dpy];
@@ -83,6 +93,9 @@
         if(!Writeback::getInstance()->setSecure(false)) {
             ALOGE("Failure while attempting to reset WB session.");
         }
+        ctx->mWfdSyncLock.lock();
+        ctx->mWfdSyncLock.signal();
+        ctx->mWfdSyncLock.unlock();
     }
 }
 
@@ -94,8 +107,8 @@
     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;
+        reset_layer_prop(ctx, dpy, (int)list->numHwLayers - 1);
+        uint32_t last = (uint32_t)list->numHwLayers - 1;
         hwc_layer_1_t *fbLayer = &list->hwLayers[last];
         int fbWidth = 0, fbHeight = 0;
         getLayerResolution(fbLayer, fbWidth, fbHeight);
@@ -104,6 +117,7 @@
 
         if(ctx->dpyAttr[dpy].connected == false) {
             ctx->dpyAttr[dpy].connected = true;
+            ctx->dpyAttr[dpy].isPause = false;
             // We set the vsync period to the primary refresh rate, leaving
             // it up to the consumer to decide how fast to consume frames.
             ctx->dpyAttr[dpy].vsync_period
@@ -113,16 +127,32 @@
             // allow one padding round to free up resources but this breaks
             // certain use cases.
         }
+        if(!ctx->dpyAttr[dpy].isPause) {
+            ctx->dpyAttr[dpy].isConfiguring = false;
+            ctx->dpyAttr[dpy].fd = Writeback::getInstance()->getFbFd();
+            private_handle_t *ohnd = (private_handle_t *)list->outbuf;
+            Writeback::getInstance()->configureDpyInfo(ohnd->width,
+                                                          ohnd->height);
+            setListStats(ctx, list, dpy);
 
-        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]->prepareAndValidate(ctx, list, fbZ);
+            if(ctx->mMDPComp[dpy]->prepare(ctx, list) < 0) {
+                const int fbZ = 0;
+                if(not ctx->mFBUpdate[dpy]->prepareAndValidate(ctx, list, fbZ))
+                {
+                    ctx->mOverlay->clear(dpy);
+                    ctx->mLayerRotMap[dpy]->clear();
+                }
+            }
+        } else {
+            /* Virtual Display is in Pause state.
+             * Mark all application layers as OVERLAY so that
+             * GPU will not compose.
+             */
+            Writeback::getInstance(); //Ensure that WB is active during pause
+            for(size_t i = 0 ;i < (size_t)(list->numHwLayers - 1); i++) {
+                hwc_layer_1_t *layer = &list->hwLayers[i];
+                layer->compositionType = HWC_OVERLAY;
+            }
         }
     }
     return 0;
@@ -134,10 +164,12 @@
     const int dpy = HWC_DISPLAY_VIRTUAL;
 
     if (list && list->outbuf && list->numHwLayers > 0) {
-        uint32_t last = list->numHwLayers - 1;
+        uint32_t last = (uint32_t)list->numHwLayers - 1;
         hwc_layer_1_t *fbLayer = &list->hwLayers[last];
 
-        if(ctx->dpyAttr[dpy].connected) {
+        if(ctx->dpyAttr[dpy].connected
+                && (!ctx->dpyAttr[dpy].isPause))
+        {
             private_handle_t *ohnd = (private_handle_t *)list->outbuf;
             int format = ohnd->format;
             if (format == HAL_PIXEL_FORMAT_RGBA_8888)
@@ -157,6 +189,10 @@
             int fd = -1; //FenceFD from the Copybit
             hwc_sync(ctx, list, dpy, fd);
 
+            // Dump the layers for virtual
+            if(ctx->mHwcDebug[dpy])
+                ctx->mHwcDebug[dpy]->dumpLayers(list);
+
             if (!ctx->mMDPComp[dpy]->draw(ctx, list)) {
                 ALOGE("%s: MDPComp draw failed", __FUNCTION__);
                 ret = -1;
@@ -173,12 +209,26 @@
                 ret = -1;
             }
 
-            Writeback::getInstance()->queueBuffer(ohnd->fd, ohnd->offset);
+            Writeback::getInstance()->queueBuffer(ohnd->fd,
+                                        (uint32_t)ohnd->offset);
             if(!Overlay::displayCommit(ctx->dpyAttr[dpy].fd)) {
                 ALOGE("%s: display commit fail!", __FUNCTION__);
                 ret = -1;
             }
 
+            if(mVDSDumpEnabled) {
+                char bufferName[128];
+                // Dumping frame buffer
+                sync_wait(fbLayer->acquireFenceFd, 1000);
+                snprintf(bufferName, sizeof(bufferName), "vds.fb");
+                dumpBuffer((private_handle_t *)fbLayer->handle, bufferName);
+                // Dumping WB output for non-secure session
+                if(!isSecureBuffer(ohnd)) {
+                    sync_wait(list->retireFenceFd, 1000);
+                    snprintf(bufferName, sizeof(bufferName), "vds.wb");
+                    dumpBuffer(ohnd, bufferName);
+                }
+            }
         } else if(list->outbufAcquireFenceFd >= 0) {
             //If we dont handle the frame, set retireFenceFd to outbufFenceFd,
             //which will make sure, the framework waits on it and closes it.
@@ -194,6 +244,47 @@
     return ret;
 }
 
+void HWCVirtualVDS::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);
+        }
+        ctx->proc->invalidate(ctx->proc);
+    }
+    return;
+}
+
+void HWCVirtualVDS::resume(hwc_context_t* ctx, int dpy) {
+    {
+        Locker::Autolock _l(ctx->mDrawLock);
+        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;
+}
+
 /* Implementation for HWCVirtualV4L2 class */
 
 int HWCVirtualV4L2::prepare(hwc_composer_device_1 *dev,
@@ -205,15 +296,18 @@
 
     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);
+            ctx->dpyAttr[dpy].connected) {
+        reset_layer_prop(ctx, dpy, (int)list->numHwLayers - 1);
         if(!ctx->dpyAttr[dpy].isPause) {
             ctx->dpyAttr[dpy].isConfiguring = false;
             setListStats(ctx, list, dpy);
             if(ctx->mMDPComp[dpy]->prepare(ctx, list) < 0) {
                 const int fbZ = 0;
-                ctx->mFBUpdate[dpy]->prepareAndValidate(ctx, list, fbZ);
+                if(not ctx->mFBUpdate[dpy]->prepareAndValidate(ctx, list, fbZ))
+                {
+                    ctx->mOverlay->clear(dpy);
+                    ctx->mLayerRotMap[dpy]->clear();
+                }
             }
         } else {
             /* Virtual Display is in Pause state.
@@ -237,9 +331,8 @@
 
     if (LIKELY(list) && ctx->dpyAttr[dpy].isActive &&
             ctx->dpyAttr[dpy].connected &&
-            (!ctx->dpyAttr[dpy].isPause) &&
-            canUseMDPforVirtualDisplay(ctx,list)) {
-        uint32_t last = list->numHwLayers - 1;
+            !ctx->dpyAttr[dpy].isPause) {
+        uint32_t last = (uint32_t)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;
@@ -294,3 +387,56 @@
 
     return ret;
 }
+
+void HWCVirtualV4L2::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 HWCVirtualV4L2::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.
+        //TODO: clean up
+        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;
+}
diff --git a/msm8226/libhwcomposer/hwc_virtual.h b/msm8226/libhwcomposer/hwc_virtual.h
index 26f401f..26d89c9 100644
--- a/msm8226/libhwcomposer/hwc_virtual.h
+++ b/msm8226/libhwcomposer/hwc_virtual.h
@@ -22,6 +22,7 @@
 #define HWC_VIRTUAL
 
 #include <hwc_utils.h>
+#include <virtual.h>
 
 namespace qhwc {
 namespace ovutils = overlay::utils;
@@ -32,18 +33,20 @@
     explicit HWCVirtualBase(){};
     virtual ~HWCVirtualBase(){};
     // instantiates and returns the pointer to VDS or V4L2 object.
-    static HWCVirtualBase* getObject();
+    static HWCVirtualBase* getObject(bool isVDSEnabled);
     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;
+    virtual void pause(hwc_context_t* ctx, int dpy) = 0;
+    virtual void resume(hwc_context_t* ctx, int dpy) = 0;
 };
 
 class HWCVirtualVDS : public HWCVirtualBase {
 public:
-    explicit HWCVirtualVDS(){};
+    explicit HWCVirtualVDS();
     virtual ~HWCVirtualVDS(){};
     // Chooses composition type and configures pipe for each layer in virtual
     // display list
@@ -59,6 +62,14 @@
     // during virtual display disconnect.
     virtual void destroy(hwc_context_t *ctx, size_t numDisplays,
                        hwc_display_contents_1_t** displays);
+    virtual void pause(hwc_context_t* ctx, int dpy);
+    virtual void resume(hwc_context_t* ctx, int dpy);
+private:
+    // If WFD is enabled through VDS solution
+    // we can dump the frame buffer and WB
+    // output buffer by setting the property
+    // debug.hwc.enable_vds_dump
+    bool mVDSDumpEnabled;
 };
 
 class HWCVirtualV4L2 : public HWCVirtualBase {
@@ -80,6 +91,8 @@
     // during virtual display disconnect. This function is no-op for V4L2 design
     virtual void destroy(hwc_context_t *, size_t ,
                        hwc_display_contents_1_t** ) {};
+    virtual void pause(hwc_context_t* ctx, int dpy);
+    virtual void resume(hwc_context_t* ctx, int dpy);
 };
 
 }; //namespace
diff --git a/msm8226/libhwcomposer/hwc_vsync.cpp b/msm8226/libhwcomposer/hwc_vsync.cpp
index 7fb89c5..d902e55 100644
--- a/msm8226/libhwcomposer/hwc_vsync.cpp
+++ b/msm8226/libhwcomposer/hwc_vsync.cpp
@@ -40,7 +40,6 @@
 #define PANEL_ON_STR "panel_power_on ="
 #define ARRAY_LENGTH(array) (sizeof((array))/sizeof((array)[0]))
 const int MAX_DATA = 64;
-bool logvsync = false;
 
 int hwc_vsync_control(hwc_context_t* ctx, int dpy, int enable)
 {
@@ -63,7 +62,7 @@
         timestamp = strtoull(data + strlen("VSYNC="), NULL, 0);
     }
     // send timestamp to SurfaceFlinger
-    ALOGD_IF (logvsync, "%s: timestamp %"PRIu64" sent to SF for dpy=%d",
+    ALOGD_IF (ctx->vstate.debug, "%s: timestamp %"PRIu64" sent to SF for dpy=%d",
             __FUNCTION__, timestamp, dpy);
     ctx->proc->vsync(ctx->proc, dpy, timestamp);
 }
@@ -71,8 +70,8 @@
 static void handle_blank_event(hwc_context_t* ctx, int dpy, char *data)
 {
     if (!strncmp(data, PANEL_ON_STR, strlen(PANEL_ON_STR))) {
-        uint32_t poweron = strtoul(data + strlen(PANEL_ON_STR), NULL, 0);
-        ALOGI("%s: dpy:%d panel power state: %d", __FUNCTION__, dpy, poweron);
+        unsigned long int poweron = strtoul(data + strlen(PANEL_ON_STR), NULL, 0);
+        ALOGI("%s: dpy:%d panel power state: %ld", __FUNCTION__, dpy, poweron);
         ctx->dpyAttr[dpy].isActive = poweron ? true: false;
     }
 }
@@ -111,11 +110,6 @@
             ctx->vstate.fakevsync = true;
     }
 
-    if(property_get("debug.hwc.logvsync", property, 0) > 0) {
-        if(atoi(property) == 1)
-            logvsync = true;
-    }
-
     char node_path[MAX_SYSFS_FILE_PATH];
 #ifdef VSYNC_FAILURE_FALLBACK
     int fake_vsync_switch_cnt = 0;
@@ -155,13 +149,13 @@
 
     if (LIKELY(!ctx->vstate.fakevsync)) {
         do {
-            int err = poll(*pfd, num_displays * num_events, -1);
+            int err = poll(*pfd, (int)(num_displays * num_events), -1);
             if(err > 0) {
                 for (int dpy = HWC_DISPLAY_PRIMARY; dpy < num_displays; dpy++) {
                     for(size_t ev = 0; ev < num_events; ev++) {
                         if (pfd[dpy][ev].revents & POLLPRI) {
-                            err = pread(pfd[dpy][ev].fd, vdata, MAX_DATA, 0);
-                            if (UNLIKELY(err < 0)) {
+                            ssize_t len = pread(pfd[dpy][ev].fd, vdata, MAX_DATA, 0);
+                            if (UNLIKELY(len < 0)) {
                                 // If the read was just interrupted - it is not
                                 // a fatal error. Just continue in this case
                                 ALOGE ("%s: Unable to read event:%zu for \
diff --git a/msm8226/liblight/Android.mk b/msm8226/liblight/Android.mk
index 40115d5..977fc55 100644
--- a/msm8226/liblight/Android.mk
+++ b/msm8226/liblight/Android.mk
@@ -18,7 +18,7 @@
 include $(CLEAR_VARS)
 
 LOCAL_SRC_FILES := lights.c
-LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw
+LOCAL_MODULE_RELATIVE_PATH := hw
 LOCAL_SHARED_LIBRARIES := liblog
 LOCAL_CFLAGS := $(common_flags) -DLOG_TAG=\"qdlights\"
 LOCAL_MODULE := lights.$(TARGET_BOARD_PLATFORM)
diff --git a/msm8226/liblight/lights.c b/msm8226/liblight/lights.c
index 1aa0b58..615ddd8 100644
--- a/msm8226/liblight/lights.c
+++ b/msm8226/liblight/lights.c
@@ -83,7 +83,7 @@
     fd = open(path, O_RDWR);
     if (fd >= 0) {
         char buffer[20];
-        int bytes = sprintf(buffer, "%d\n", value);
+        int bytes = snprintf(buffer, sizeof(buffer), "%d\n", value);
         ssize_t amt = write(fd, buffer, (size_t)bytes);
         close(fd);
         return amt == -1 ? -errno : 0;
@@ -168,12 +168,18 @@
     }
 
     if (blink) {
-        if (red)
-            write_int(RED_BLINK_FILE, blink);
-        if (green)
-            write_int(GREEN_BLINK_FILE, blink);
-        if (blue)
-            write_int(BLUE_BLINK_FILE, blink);
+        if (red) {
+            if (write_int(RED_BLINK_FILE, blink))
+                write_int(RED_LED_FILE, 0);
+	}
+        if (green) {
+            if (write_int(GREEN_BLINK_FILE, blink))
+                write_int(GREEN_LED_FILE, 0);
+	}
+        if (blue) {
+            if (write_int(BLUE_BLINK_FILE, blink))
+                write_int(BLUE_LED_FILE, 0);
+	}
     } else {
         write_int(RED_LED_FILE, red);
         write_int(GREEN_LED_FILE, green);
@@ -194,6 +200,17 @@
 }
 
 static int
+set_light_battery(struct light_device_t* dev,
+        struct light_state_t const* state)
+{
+    pthread_mutex_lock(&g_lock);
+    g_battery = *state;
+    handle_speaker_battery_locked(dev);
+    pthread_mutex_unlock(&g_lock);
+    return 0;
+}
+
+static int
 set_light_notifications(struct light_device_t* dev,
         struct light_state_t const* state)
 {
@@ -259,6 +276,8 @@
 
     if (0 == strcmp(LIGHT_ID_BACKLIGHT, name))
         set_light = set_light_backlight;
+    else if (0 == strcmp(LIGHT_ID_BATTERY, name))
+        set_light = set_light_battery;
     else if (0 == strcmp(LIGHT_ID_NOTIFICATIONS, name))
         set_light = set_light_notifications;
     else if (0 == strcmp(LIGHT_ID_BUTTONS, name))
@@ -271,6 +290,10 @@
     pthread_once(&g_init, init_globals);
 
     struct light_device_t *dev = malloc(sizeof(struct light_device_t));
+
+    if(!dev)
+        return -ENOMEM;
+
     memset(dev, 0, sizeof(*dev));
 
     dev->common.tag = HARDWARE_DEVICE_TAG;
diff --git a/msm8226/libmemtrack/Android.mk b/msm8226/libmemtrack/Android.mk
index 306eb07..2fda0b7 100644
--- a/msm8226/libmemtrack/Android.mk
+++ b/msm8226/libmemtrack/Android.mk
@@ -18,7 +18,7 @@
 # hw/<POWERS_HARDWARE_MODULE_ID>.<ro.hardware>.so
 include $(CLEAR_VARS)
 
-LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw
+LOCAL_MODULE_RELATIVE_PATH := hw
 LOCAL_C_INCLUDES += hardware/libhardware/include
 LOCAL_SHARED_LIBRARIES := liblog
 LOCAL_SRC_FILES := memtrack_msm.c kgsl.c
diff --git a/msm8226/libmemtrack/kgsl.c b/msm8226/libmemtrack/kgsl.c
index 974f3e6..e4943e8 100644
--- a/msm8226/libmemtrack/kgsl.c
+++ b/msm8226/libmemtrack/kgsl.c
@@ -47,7 +47,6 @@
     size_t allocated_records = min(*num_records, ARRAY_SIZE(record_templates));
     int i;
     FILE *fp;
-    FILE *smaps_fp = NULL;
     char line[1024];
     char tmp[128];
     bool is_surfaceflinger = false;
@@ -81,20 +80,15 @@
         return -errno;
     }
 
-    if (type == MEMTRACK_TYPE_GL) {
-        snprintf(tmp, sizeof(tmp), "/proc/%d/smaps", pid);
-        smaps_fp = fopen(tmp, "r");
-        if (smaps_fp == NULL) {
-            fclose(fp);
-            return -errno;
-        }
-    }
-
+    /* Go through each line of <pid>/mem file and for every entry of type "gpumem"
+     * check if the gpubuffer entry is usermapped or not. If the entry is usermapped
+     * count the entry as accounted else count the entry as unaccounted.
+     */
     while (1) {
-        unsigned long uaddr;
         unsigned long size;
         char line_type[7];
         char line_usage[19];
+        char flags[7];
         int ret;
 
         if (fgets(line, sizeof(line), fp) == NULL) {
@@ -103,49 +97,21 @@
 
         /* Format:
          *  gpuaddr useraddr     size    id flags       type            usage sglen
-         * 545ba000 545ba000     4096     1 ----p     gpumem      arraybuffer     1
+         * 545ba000 545ba000     4096     1 ----pY     gpumem      arraybuffer     1
          */
-        ret = sscanf(line, "%*x %lx %lu %*d %*s %6s %18s %*d\n",
-                     &uaddr, &size, line_type, line_usage);
+        ret = sscanf(line, "%*x %*x %lu %*d %6s %6s %*s %*d\n",
+                     &size, flags, line_type);
         if (ret != 4) {
             continue;
         }
 
         if (type == MEMTRACK_TYPE_GL && strcmp(line_type, "gpumem") == 0) {
-            bool accounted = false;
-            /*
-             * We need to cross reference the user address against smaps,
-             *  luckily both are sorted.
-             */
-            while (smaps_addr <= uaddr) {
-                unsigned long start;
-                unsigned long end;
-                unsigned long smaps_size;
 
-                if (fgets(line, sizeof(line), smaps_fp) == NULL) {
-                    break;
-                }
-
-                if (sscanf(line, "%8lx-%8lx", &start, &end) == 2) {
-                    smaps_addr = start;
-                    continue;
-                }
-
-                if (smaps_addr != uaddr) {
-                    continue;
-                }
-
-                if (sscanf(line, "Rss: %lu kB", &smaps_size) == 1) {
-                    if (smaps_size) {
-                        accounted = true;
-                        accounted_size += size;
-                        break;
-                    }
-                }
-            }
-            if (!accounted) {
+            if (flags[6] == 'Y')
+                accounted_size += size;
+            else
                 unaccounted_size += size;
-            }
+
         } else if (type == MEMTRACK_TYPE_GRAPHICS && strcmp(line_type, "ion") == 0) {
             if (!is_surfaceflinger || strcmp(line_usage, "egl_image") != 0) {
                 unaccounted_size += size;
@@ -160,8 +126,6 @@
         records[1].size_in_bytes = unaccounted_size;
     }
 
-    if (smaps_fp)
-        fclose(smaps_fp);
     fclose(fp);
 
     return 0;
diff --git a/msm8226/liboverlay/Android.mk b/msm8226/liboverlay/Android.mk
index d8c2ab5..aa1ea24 100644
--- a/msm8226/liboverlay/Android.mk
+++ b/msm8226/liboverlay/Android.mk
@@ -3,15 +3,11 @@
 include $(CLEAR_VARS)
 
 LOCAL_MODULE                  := liboverlay
-LOCAL_MODULE_PATH             := $(TARGET_OUT_SHARED_LIBRARIES)
 LOCAL_MODULE_TAGS             := optional
 LOCAL_C_INCLUDES              := $(common_includes) $(kernel_includes)
 LOCAL_SHARED_LIBRARIES        := $(common_libs) libqdutils libmemalloc \
                                  libsync libdl
 LOCAL_CFLAGS                  := $(common_flags) -DLOG_TAG=\"qdoverlay\"
-ifeq ($(TARGET_USES_QSEED_SCALAR),true)
-    LOCAL_CFLAGS += -DUSES_QSEED_SCALAR
-endif
 LOCAL_ADDITIONAL_DEPENDENCIES := $(common_deps)
 LOCAL_SRC_FILES := \
       overlay.cpp \
diff --git a/msm8226/liboverlay/mdpWrapper.h b/msm8226/liboverlay/mdpWrapper.h
index 1bfa058..e24ad6a 100644
--- a/msm8226/liboverlay/mdpWrapper.h
+++ b/msm8226/liboverlay/mdpWrapper.h
@@ -30,6 +30,8 @@
 #ifndef MDP_WRAPPER_H
 #define MDP_WRAPPER_H
 
+#define ATRACE_TAG (ATRACE_TAG_GRAPHICS | ATRACE_TAG_HAL)
+
 /*
 * In order to make overlay::mdp_wrapper shorter, please do something like:
 * namespace mdpwrap = overlay::mdp_wrapper;
@@ -39,6 +41,7 @@
 #include <linux/msm_rotator.h>
 #include <sys/ioctl.h>
 #include <utils/Log.h>
+#include <utils/Trace.h>
 #include <errno.h>
 #include "overlayUtils.h"
 
@@ -80,9 +83,6 @@
 /* MSMFB_OVERLAY_PLAY */
 bool play(int fd, msmfb_overlay_data& od);
 
-/* MSMFB_OVERLAY_3D */
-bool set3D(int fd, msmfb_overlay_3d& ov);
-
 /* MSMFB_DISPLAY_COMMIT */
 bool displayCommit(int fd);
 
@@ -119,6 +119,7 @@
 //---------------Inlines -------------------------------------
 
 inline bool getFScreenInfo(int fd, fb_fix_screeninfo& finfo) {
+    ATRACE_CALL();
     if (ioctl(fd, FBIOGET_FSCREENINFO, &finfo) < 0) {
         ALOGE("Failed to call ioctl FBIOGET_FSCREENINFO err=%s",
                 strerror(errno));
@@ -128,6 +129,7 @@
 }
 
 inline bool getVScreenInfo(int fd, fb_var_screeninfo& vinfo) {
+    ATRACE_CALL();
     if (ioctl(fd, FBIOGET_VSCREENINFO, &vinfo) < 0) {
         ALOGE("Failed to call ioctl FBIOGET_VSCREENINFO err=%s",
                 strerror(errno));
@@ -137,6 +139,7 @@
 }
 
 inline bool setVScreenInfo(int fd, fb_var_screeninfo& vinfo) {
+    ATRACE_CALL();
     if (ioctl(fd, FBIOPUT_VSCREENINFO, &vinfo) < 0) {
         ALOGE("Failed to call ioctl FBIOPUT_VSCREENINFO err=%s",
                 strerror(errno));
@@ -146,6 +149,7 @@
 }
 
 inline bool startRotator(int fd, msm_rotator_img_info& rot) {
+    ATRACE_CALL();
     if (ioctl(fd, MSM_ROTATOR_IOCTL_START, &rot) < 0){
         ALOGE("Failed to call ioctl MSM_ROTATOR_IOCTL_START err=%s",
                 strerror(errno));
@@ -155,6 +159,7 @@
 }
 
 inline bool rotate(int fd, msm_rotator_data_info& rot) {
+    ATRACE_CALL();
     if (ioctl(fd, MSM_ROTATOR_IOCTL_ROTATE, &rot) < 0) {
         ALOGE("Failed to call ioctl MSM_ROTATOR_IOCTL_ROTATE err=%s",
                 strerror(errno));
@@ -164,6 +169,7 @@
 }
 
 inline bool setOverlay(int fd, mdp_overlay& ov) {
+    ATRACE_CALL();
     if (ioctl(fd, MSMFB_OVERLAY_SET, &ov) < 0) {
         ALOGE("Failed to call ioctl MSMFB_OVERLAY_SET err=%s",
                 strerror(errno));
@@ -173,6 +179,7 @@
 }
 
 inline bool validateAndSet(const int& fd, mdp_overlay_list& list) {
+    ATRACE_CALL();
     if (ioctl(fd, MSMFB_OVERLAY_PREPARE, &list) < 0) {
         ALOGD_IF(IOCTL_DEBUG, "Failed to call ioctl MSMFB_OVERLAY_PREPARE "
                 "err=%s", strerror(errno));
@@ -182,6 +189,7 @@
 }
 
 inline bool endRotator(int fd, uint32_t sessionId) {
+    ATRACE_CALL();
     if (ioctl(fd, MSM_ROTATOR_IOCTL_FINISH, &sessionId) < 0) {
         ALOGE("Failed to call ioctl MSM_ROTATOR_IOCTL_FINISH err=%s",
                 strerror(errno));
@@ -191,6 +199,7 @@
 }
 
 inline bool unsetOverlay(int fd, int ovId) {
+    ATRACE_CALL();
     if (ioctl(fd, MSMFB_OVERLAY_UNSET, &ovId) < 0) {
         ALOGE("Failed to call ioctl MSMFB_OVERLAY_UNSET err=%s",
                 strerror(errno));
@@ -200,6 +209,7 @@
 }
 
 inline bool getOverlay(int fd, mdp_overlay& ov) {
+    ATRACE_CALL();
     if (ioctl(fd, MSMFB_OVERLAY_GET, &ov) < 0) {
         ALOGE("Failed to call ioctl MSMFB_OVERLAY_GET err=%s",
                 strerror(errno));
@@ -209,6 +219,7 @@
 }
 
 inline bool play(int fd, msmfb_overlay_data& od) {
+    ATRACE_CALL();
     if (ioctl(fd, MSMFB_OVERLAY_PLAY, &od) < 0) {
         ALOGE("Failed to call ioctl MSMFB_OVERLAY_PLAY err=%s",
                 strerror(errno));
@@ -217,16 +228,8 @@
     return true;
 }
 
-inline bool set3D(int fd, msmfb_overlay_3d& ov) {
-    if (ioctl(fd, MSMFB_OVERLAY_3D, &ov) < 0) {
-        ALOGE("Failed to call ioctl MSMFB_OVERLAY_3D err=%s",
-                strerror(errno));
-        return false;
-    }
-    return true;
-}
-
 inline bool displayCommit(int fd, mdp_display_commit& info) {
+    ATRACE_CALL();
     if(ioctl(fd, MSMFB_DISPLAY_COMMIT, &info) == -1) {
         ALOGE("Failed to call ioctl MSMFB_DISPLAY_COMMIT err=%s",
                 strerror(errno));
@@ -236,6 +239,7 @@
 }
 
 inline bool wbInitStart(int fbfd) {
+    ATRACE_CALL();
     if(ioctl(fbfd, MSMFB_WRITEBACK_INIT, NULL) < 0) {
         ALOGE("Failed to call ioctl MSMFB_WRITEBACK_INIT err=%s",
                 strerror(errno));
@@ -250,6 +254,7 @@
 }
 
 inline bool wbStopTerminate(int fbfd) {
+    ATRACE_CALL();
     if(ioctl(fbfd, MSMFB_WRITEBACK_STOP, NULL) < 0) {
         ALOGE("Failed to call ioctl MSMFB_WRITEBACK_STOP err=%s",
                 strerror(errno));
@@ -264,6 +269,7 @@
 }
 
 inline bool wbQueueBuffer(int fbfd, struct msmfb_data& fbData) {
+    ATRACE_CALL();
     if(ioctl(fbfd, MSMFB_WRITEBACK_QUEUE_BUFFER, &fbData) < 0) {
         ALOGE("Failed to call ioctl MSMFB_WRITEBACK_QUEUE_BUFFER err=%s",
                 strerror(errno));
@@ -273,6 +279,7 @@
 }
 
 inline bool wbDequeueBuffer(int fbfd, struct msmfb_data& fbData) {
+    ATRACE_CALL();
     if(ioctl(fbfd, MSMFB_WRITEBACK_DEQUEUE_BUFFER, &fbData) < 0) {
         ALOGE("Failed to call ioctl MSMFB_WRITEBACK_DEQUEUE_BUFFER err=%s",
                 strerror(errno));
diff --git a/msm8226/liboverlay/overlay.cpp b/msm8226/liboverlay/overlay.cpp
index 265aa9f..de880c6 100644
--- a/msm8226/liboverlay/overlay.cpp
+++ b/msm8226/liboverlay/overlay.cpp
@@ -33,16 +33,11 @@
 #include "mdp_version.h"
 #include "qdMetaData.h"
 
-#ifdef USES_QSEED_SCALAR
-#include <scale/scale.h>
-using namespace scale;
-#endif
-
 #define PIPE_DEBUG 0
 
 namespace overlay {
 using namespace utils;
-
+using namespace qdutils;
 
 Overlay::Overlay() {
     int numPipes = qdutils::MDPVersion::getInstance().getTotalPipes();
@@ -158,6 +153,107 @@
     return dest;
 }
 
+utils::eDest Overlay::getPipe(const PipeSpecs& pipeSpecs) {
+    if(MDPVersion::getInstance().is8x26()) {
+        return getPipe_8x26(pipeSpecs);
+    } else if(MDPVersion::getInstance().is8x16()) {
+        return getPipe_8x16(pipeSpecs);
+    } else if(MDPVersion::getInstance().is8x39()) {
+        return getPipe_8x39(pipeSpecs);
+    }
+
+    eDest dest = OV_INVALID;
+
+    //The default behavior is to assume RGB and VG pipes have scalars
+    if(pipeSpecs.formatClass == FORMAT_YUV) {
+        return nextPipe(OV_MDP_PIPE_VG, pipeSpecs.dpy, pipeSpecs.mixer);
+    } else if(pipeSpecs.fb == false) { //RGB App layers
+        if(not pipeSpecs.needsScaling) {
+            dest = nextPipe(OV_MDP_PIPE_DMA, pipeSpecs.dpy, pipeSpecs.mixer);
+        }
+        if(dest == OV_INVALID) {
+            dest = nextPipe(OV_MDP_PIPE_RGB, pipeSpecs.dpy, pipeSpecs.mixer);
+        }
+        if(dest == OV_INVALID) {
+            dest = nextPipe(OV_MDP_PIPE_VG, pipeSpecs.dpy, pipeSpecs.mixer);
+        }
+    } else { //FB layer
+        dest = nextPipe(OV_MDP_PIPE_RGB, pipeSpecs.dpy, pipeSpecs.mixer);
+        if(dest == OV_INVALID) {
+            dest = nextPipe(OV_MDP_PIPE_VG, pipeSpecs.dpy, pipeSpecs.mixer);
+        }
+        //Some features can cause FB to have scaling as well.
+        //If we ever come to this block with FB needing scaling,
+        //the screen will be black for a frame, since the FB won't get a pipe
+        //but atleast this will prevent a hang
+        if(dest == OV_INVALID and (not pipeSpecs.needsScaling)) {
+            dest = nextPipe(OV_MDP_PIPE_DMA, pipeSpecs.dpy, pipeSpecs.mixer);
+        }
+    }
+    return dest;
+}
+
+utils::eDest Overlay::getPipe_8x26(const PipeSpecs& pipeSpecs) {
+    //Use this to hide all the 8x26 requirements that cannot be humanly
+    //described in a generic way
+    eDest dest = OV_INVALID;
+    if(pipeSpecs.formatClass == FORMAT_YUV) { //video
+        return nextPipe(OV_MDP_PIPE_VG, pipeSpecs.dpy, pipeSpecs.mixer);
+    } else if(pipeSpecs.fb == false) { //RGB app layers
+        if((not pipeSpecs.needsScaling) and
+          (not (pipeSpecs.numActiveDisplays > 1 &&
+                pipeSpecs.dpy == DPY_PRIMARY))) {
+            dest = nextPipe(OV_MDP_PIPE_DMA, pipeSpecs.dpy, pipeSpecs.mixer);
+        }
+        if(dest == OV_INVALID) {
+            dest = nextPipe(OV_MDP_PIPE_RGB, pipeSpecs.dpy, pipeSpecs.mixer);
+        }
+        if(dest == OV_INVALID) {
+            dest = nextPipe(OV_MDP_PIPE_VG, pipeSpecs.dpy, pipeSpecs.mixer);
+        }
+    } else { //FB layer
+        //For 8x26 Secondary we use DMA always for FB for inline rotation
+        if(pipeSpecs.dpy == DPY_PRIMARY) {
+            dest = nextPipe(OV_MDP_PIPE_RGB, pipeSpecs.dpy, pipeSpecs.mixer);
+            if(dest == OV_INVALID) {
+                dest = nextPipe(OV_MDP_PIPE_VG, pipeSpecs.dpy, pipeSpecs.mixer);
+            }
+        }
+        if(dest == OV_INVALID and (not pipeSpecs.needsScaling) and
+          (not (pipeSpecs.numActiveDisplays > 1 &&
+                pipeSpecs.dpy == DPY_PRIMARY))) {
+            dest = nextPipe(OV_MDP_PIPE_DMA, pipeSpecs.dpy, pipeSpecs.mixer);
+        }
+    }
+    return dest;
+}
+
+utils::eDest Overlay::getPipe_8x16(const PipeSpecs& pipeSpecs) {
+    //Having such functions help keeping the interface generic but code specific
+    //and rife with assumptions
+    eDest dest = OV_INVALID;
+    if(pipeSpecs.formatClass == FORMAT_YUV or pipeSpecs.needsScaling) {
+        return nextPipe(OV_MDP_PIPE_VG, pipeSpecs.dpy, pipeSpecs.mixer);
+    } else {
+        //Since this is a specific func, we can assume stuff like RGB pipe not
+        //having scalar blocks
+        dest = nextPipe(OV_MDP_PIPE_RGB, pipeSpecs.dpy, pipeSpecs.mixer);
+        if(dest == OV_INVALID) {
+            dest = nextPipe(OV_MDP_PIPE_DMA, pipeSpecs.dpy, pipeSpecs.mixer);
+        }
+        if(dest == OV_INVALID) {
+            dest = nextPipe(OV_MDP_PIPE_VG, pipeSpecs.dpy, pipeSpecs.mixer);
+        }
+    }
+    return dest;
+}
+
+utils::eDest Overlay::getPipe_8x39(const PipeSpecs& pipeSpecs) {
+    //8x16 & 8x36 has same number of pipes, pipe-types & scaling capabilities.
+    //Rely on 8x16 until we see a need to change.
+    return getPipe_8x16(pipeSpecs);
+}
+
 void Overlay::endAllSessions() {
     for(int i = 0; i < PipeBook::NUM_PIPES; i++) {
         if(mPipeBook[i].valid() && mPipeBook[i].mSession==PipeBook::START)
@@ -175,16 +271,28 @@
     return false;
 }
 
+int Overlay::comparePipePriority(utils::eDest pipe1Index,
+        utils::eDest pipe2Index) {
+    validate((int)pipe1Index);
+    validate((int)pipe2Index);
+    uint8_t pipe1Prio = mPipeBook[(int)pipe1Index].mPipe->getPriority();
+    uint8_t pipe2Prio = mPipeBook[(int)pipe2Index].mPipe->getPriority();
+    if(pipe1Prio > pipe2Prio)
+        return -1;
+    if(pipe1Prio < pipe2Prio)
+        return 1;
+    return 0;
+}
+
 bool Overlay::commit(utils::eDest dest) {
     bool ret = false;
-    int index = (int)dest;
-    validate(index);
+    validate((int)dest);
 
-    if(mPipeBook[index].mPipe->commit()) {
+    if(mPipeBook[dest].mPipe->commit()) {
         ret = true;
         PipeBook::setUse((int)dest);
     } else {
-        int dpy = mPipeBook[index].mDisplay;
+        int dpy = mPipeBook[dest].mDisplay;
         for(int i = 0; i < PipeBook::NUM_PIPES; i++) {
             if (mPipeBook[i].mDisplay == dpy) {
                 PipeBook::resetAllocation(i);
@@ -197,73 +305,59 @@
 
 bool Overlay::queueBuffer(int fd, uint32_t offset,
         utils::eDest dest) {
-    int index = (int)dest;
     bool ret = false;
-    validate(index);
+    validate((int)dest);
     //Queue only if commit() has succeeded (and the bit set)
     if(PipeBook::isUsed((int)dest)) {
-        ret = mPipeBook[index].mPipe->queueBuffer(fd, offset);
+        ret = mPipeBook[dest].mPipe->queueBuffer(fd, offset);
     }
     return ret;
 }
 
 void Overlay::setCrop(const utils::Dim& d,
         utils::eDest dest) {
-    int index = (int)dest;
-    validate(index);
-    mPipeBook[index].mPipe->setCrop(d);
+    validate((int)dest);
+    mPipeBook[dest].mPipe->setCrop(d);
 }
 
 void Overlay::setColor(const uint32_t color,
         utils::eDest dest) {
-    int index = (int)dest;
-    validate(index);
-    mPipeBook[index].mPipe->setColor(color);
+    validate((int)dest);
+    mPipeBook[dest].mPipe->setColor(color);
 }
 
 void Overlay::setPosition(const utils::Dim& d,
         utils::eDest dest) {
-    int index = (int)dest;
-    validate(index);
-    mPipeBook[index].mPipe->setPosition(d);
+    validate((int)dest);
+    mPipeBook[dest].mPipe->setPosition(d);
 }
 
 void Overlay::setTransform(const int orient,
         utils::eDest dest) {
-    int index = (int)dest;
-    validate(index);
+    validate((int)dest);
 
     utils::eTransform transform =
             static_cast<utils::eTransform>(orient);
-    mPipeBook[index].mPipe->setTransform(transform);
+    mPipeBook[dest].mPipe->setTransform(transform);
 
 }
 
 void Overlay::setSource(const utils::PipeArgs args,
         utils::eDest dest) {
-    int index = (int)dest;
-    validate(index);
+    validate((int)dest);
 
-    PipeArgs newArgs(args);
-    if(PipeBook::getPipeType(dest) == OV_MDP_PIPE_VG) {
-        setMdpFlags(newArgs.mdpFlags, OV_MDP_PIPE_SHARE);
-    } else {
-        clearMdpFlags(newArgs.mdpFlags, OV_MDP_PIPE_SHARE);
-    }
-
-    if(PipeBook::getPipeType(dest) == OV_MDP_PIPE_DMA) {
-        setMdpFlags(newArgs.mdpFlags, OV_MDP_PIPE_FORCE_DMA);
-    } else {
-        clearMdpFlags(newArgs.mdpFlags, OV_MDP_PIPE_FORCE_DMA);
-    }
-
-    mPipeBook[index].mPipe->setSource(newArgs);
+    setPipeType(dest, PipeBook::getPipeType(dest));
+    mPipeBook[dest].mPipe->setSource(args);
 }
 
 void Overlay::setVisualParams(const MetaData_t& metadata, utils::eDest dest) {
-    int index = (int)dest;
-    validate(index);
-    mPipeBook[index].mPipe->setVisualParams(metadata);
+    validate((int)dest);
+    mPipeBook[dest].mPipe->setVisualParams(metadata);
+}
+
+void Overlay::setPipeType(utils::eDest pipeIndex,
+        const utils::eMdpPipeType pType) {
+    mPipeBook[pipeIndex].mPipe->setPipeType(pType);
 }
 
 Overlay* Overlay::getInstance() {
@@ -365,19 +459,24 @@
 }
 
 bool Overlay::displayCommit(const int& fd) {
-    utils::Dim roi;
-    return displayCommit(fd, roi);
+    utils::Dim lRoi, rRoi;
+    return displayCommit(fd, lRoi, rRoi);
 }
 
-bool Overlay::displayCommit(const int& fd, const utils::Dim& roi) {
+bool Overlay::displayCommit(const int& fd, const utils::Dim& lRoi,
+        const utils::Dim& rRoi) {
     //Commit
     struct mdp_display_commit info;
     memset(&info, 0, sizeof(struct mdp_display_commit));
     info.flags = MDP_DISPLAY_COMMIT_OVERLAY;
-    info.roi.x = roi.x;
-    info.roi.y = roi.y;
-    info.roi.w = roi.w;
-    info.roi.h = roi.h;
+    info.l_roi.x = lRoi.x;
+    info.l_roi.y = lRoi.y;
+    info.l_roi.w = lRoi.w;
+    info.l_roi.h = lRoi.h;
+    info.r_roi.x = rRoi.x;
+    info.r_roi.y = rRoi.y;
+    info.r_roi.w = rRoi.w;
+    info.r_roi.h = rRoi.h;
 
     if(!mdp_wrapper::displayCommit(fd, info)) {
         ALOGE("%s: commit failed", __func__);
@@ -424,7 +523,7 @@
 
 bool Overlay::validateAndSet(const int& dpy, const int& fbFd) {
     GenericPipe* pipeArray[PipeBook::NUM_PIPES];
-    memset(&pipeArray, 0, sizeof(pipeArray));
+    memset(pipeArray, 0, sizeof(GenericPipe*)*(PipeBook::NUM_PIPES));
 
     int num = 0;
     for(int i = 0; i < PipeBook::NUM_PIPES; i++) {
@@ -439,39 +538,20 @@
 }
 
 void Overlay::initScalar() {
-#ifdef USES_QSEED_SCALAR
     if(sLibScaleHandle == NULL) {
         sLibScaleHandle = dlopen("libscale.so", RTLD_NOW);
-    }
-
-    if(sLibScaleHandle) {
-        if(sScale == NULL) {
-            Scale* (*getInstance)();
-            *(void **) &getInstance = dlsym(sLibScaleHandle, "getInstance");
-            if(getInstance) {
-                sScale = getInstance();
-            }
+        if(sLibScaleHandle) {
+            *(void **) &sFnProgramScale =
+                    dlsym(sLibScaleHandle, "programScale");
         }
     }
-#endif
 }
 
 void Overlay::destroyScalar() {
-#ifdef USES_QSEED_SCALAR
     if(sLibScaleHandle) {
-        if(sScale) {
-            void (*destroyInstance)(Scale*);
-            *(void **) &destroyInstance = dlsym(sLibScaleHandle,
-                    "destroyInstance");
-            if(destroyInstance) {
-                destroyInstance(sScale);
-                sScale = NULL;
-            }
-        }
         dlclose(sLibScaleHandle);
         sLibScaleHandle = NULL;
     }
-#endif
 }
 
 void Overlay::PipeBook::init() {
@@ -501,6 +581,6 @@
 utils::eMdpPipeType Overlay::PipeBook::pipeTypeLUT[utils::OV_MAX] =
     {utils::OV_MDP_PIPE_ANY};
 void *Overlay::sLibScaleHandle = NULL;
-scale::Scale *Overlay::sScale = NULL;
+int (*Overlay::sFnProgramScale)(struct mdp_overlay_list *) = NULL;
 
 }; // namespace overlay
diff --git a/msm8226/liboverlay/overlay.h b/msm8226/liboverlay/overlay.h
index d8615cd..c8f68b0 100644
--- a/msm8226/liboverlay/overlay.h
+++ b/msm8226/liboverlay/overlay.h
@@ -35,9 +35,6 @@
 #include "utils/threads.h"
 
 struct MetaData_t;
-namespace scale {
-class Scale;
-};
 
 namespace overlay {
 class GenericPipe;
@@ -53,6 +50,18 @@
     enum { MIXER_LEFT, MIXER_RIGHT, MIXER_UNUSED };
     enum { MIXER_DEFAULT = MIXER_LEFT, MIXER_MAX = MIXER_UNUSED };
     enum { MAX_FB_DEVICES = DPY_MAX };
+    enum { FORMAT_YUV, FORMAT_RGB };
+
+    struct PipeSpecs {
+        PipeSpecs() : formatClass(FORMAT_RGB), needsScaling(false), fb(false),
+                dpy(DPY_PRIMARY), mixer(MIXER_DEFAULT), numActiveDisplays(1) {}
+        int formatClass;
+        bool needsScaling;
+        bool fb;
+        int dpy;
+        int mixer;
+        int numActiveDisplays;
+    };
 
     /* dtor close */
     ~Overlay();
@@ -69,14 +78,10 @@
      */
     void configDone();
 
-    /* Returns an available pipe based on the type of pipe requested. When ANY
-     * is requested, the first available VG or RGB is returned. If no pipe is
-     * available for the display "dpy" then INV is returned. Note: If a pipe is
-     * assigned to a certain display, then it cannot be assigned to another
-     * display without being garbage-collected once. To add if a pipe is
-     * asisgned to a mixer within a display it cannot be reused for another
-     * mixer without being UNSET once*/
-    utils::eDest nextPipe(utils::eMdpPipeType, int dpy, int mixer);
+    /* Get a pipe that supported the specified format class (yuv, rgb) and has
+     * scaling capabilities.
+     */
+    utils::eDest getPipe(const PipeSpecs& pipeSpecs);
     /* Returns the eDest corresponding to an already allocated pipeid.
      * Useful for the reservation case, when libvpu reserves the pipe at its
      * end, and expect the overlay to allocate a given pipe for a layer.
@@ -114,9 +119,19 @@
      * displays
      */
     bool isPipeTypeAttached(utils::eMdpPipeType type);
+    /* Compare pipe priorities and return
+     * 1 if 1st pipe has a higher priority
+     * 0 if both have the same priority
+     *-1 if 2nd pipe has a higher priority
+     */
+    int comparePipePriority(utils::eDest pipe1Index, utils::eDest pipe2Index);
     /* Returns pipe dump. Expects a NULL terminated buffer of big enough size
      * to populate.
      */
+    /* Returns if DMA pipe multiplexing is supported by the mdss driver */
+    static bool isDMAMultiplexingSupported();
+    /* Returns if UI scaling on external is supported on the targets */
+    static bool isUIScalingOnExternalSupported();
     void getDump(char *buf, size_t len);
     /* Reset usage and allocation bits on all pipes for given display */
     void clear(int dpy);
@@ -131,8 +146,12 @@
     static int getDMAMode();
     /* Returns the framebuffer node backing up the display */
     static int getFbForDpy(const int& dpy);
-    static bool displayCommit(const int& fd, const utils::Dim& roi);
+
     static bool displayCommit(const int& fd);
+    /* Overloads display commit with ROI's of each halves.
+     * Single interface panels will only update left ROI. */
+    static bool displayCommit(const int& fd, const utils::Dim& lRoi,
+                              const utils::Dim& rRoi);
 
 private:
     /* Ctor setup */
@@ -141,12 +160,27 @@
     void validate(int index);
     static void setDMAMultiplexingSupported();
     void dump() const;
-    /* Returns the scalar object */
-    static scale::Scale *getScalar();
+    /* Returns an available pipe based on the type of pipe requested. When ANY
+     * is requested, the first available VG or RGB is returned. If no pipe is
+     * available for the display "dpy" then INV is returned. Note: If a pipe is
+     * assigned to a certain display, then it cannot be assigned to another
+     * display without being garbage-collected once. To add if a pipe is
+     * asisgned to a mixer within a display it cannot be reused for another
+     * mixer without being UNSET once*/
+    utils::eDest nextPipe(utils::eMdpPipeType, int dpy, int mixer);
+    /* Helpers that enfore target specific policies while returning pipes */
+    utils::eDest getPipe_8x26(const PipeSpecs& pipeSpecs);
+    utils::eDest getPipe_8x16(const PipeSpecs& pipeSpecs);
+    utils::eDest getPipe_8x39(const PipeSpecs& pipeSpecs);
+
+    /* Returns the handle to libscale.so's programScale function */
+    static int (*getFnProgramScale())(struct mdp_overlay_list *);
     /* Creates a scalar object using libscale.so */
     static void initScalar();
     /* Destroys the scalar object using libscale.so */
     static void destroyScalar();
+    /* Sets the pipe type RGB/VG/DMA*/
+    void setPipeType(utils::eDest pipeIndex, const utils::eMdpPipeType pType);
 
     /* Just like a Facebook for pipes, but much less profile info */
     struct PipeBook {
@@ -213,7 +247,7 @@
     static int sDMAMode;
     static bool sDMAMultiplexingSupported;
     static void *sLibScaleHandle;
-    static scale::Scale *sScale;
+    static int (*sFnProgramScale)(struct mdp_overlay_list *);
 
     friend class MdpCtrl;
 };
@@ -281,6 +315,19 @@
         sDMAMultiplexingSupported = true;
 }
 
+inline bool Overlay::isDMAMultiplexingSupported() {
+    return sDMAMultiplexingSupported;
+}
+
+inline bool Overlay::isUIScalingOnExternalSupported() {
+    if(qdutils::MDPVersion::getInstance().is8x26() or
+       qdutils::MDPVersion::getInstance().is8x16() or
+       qdutils::MDPVersion::getInstance().is8x39()) {
+        return false;
+    }
+    return true;
+}
+
 inline int Overlay::getDMAMode() {
     return sDMAMode;
 }
@@ -290,8 +337,8 @@
     return sDpyFbMap[dpy];
 }
 
-inline scale::Scale *Overlay::getScalar() {
-    return sScale;
+inline int (*Overlay::getFnProgramScale())(struct mdp_overlay_list *) {
+    return sFnProgramScale;
 }
 
 inline bool Overlay::PipeBook::valid() {
diff --git a/msm8226/liboverlay/overlayCtrlData.h b/msm8226/liboverlay/overlayCtrlData.h
index 26202ec..2eec98c 100644
--- a/msm8226/liboverlay/overlayCtrlData.h
+++ b/msm8226/liboverlay/overlayCtrlData.h
@@ -65,6 +65,8 @@
     void setPosition(const utils::Dim& dim);
     /* set mdp visual params using metadata */
     bool setVisualParams(const MetaData_t &metadata);
+    /* set pipe type RGB/DMA/VG */
+    void setPipeType(const utils::eMdpPipeType& pType);
     /* mdp set overlay/commit changes */
     bool commit();
 
@@ -75,10 +77,10 @@
     /* retrieve crop data */
     utils::Dim getCrop() const;
     utils::Dim getPosition() const;
-    /* Set downscale */
-    void setDownscale(int dscale_factor);
     /* Update the src format based on rotator's dest */
     void updateSrcFormat(const uint32_t& rotDstFormat);
+    /* return pipe priority */
+    uint8_t getPriority() const;
     /* dump the state of the object */
     void dump() const;
     /* Return the dump in the specified buffer */
@@ -157,6 +159,11 @@
     return true;
 }
 
+inline void Ctrl::setPipeType(const utils::eMdpPipeType& pType)
+{
+    mMdp->setPipeType(pType);
+}
+
 inline void Ctrl::dump() const {
     ALOGE("== Dump Ctrl start ==");
     mMdp->dump();
@@ -204,8 +211,8 @@
     return mMdp->getDstRectDim();
 }
 
-inline void Ctrl::setDownscale(int dscale_factor) {
-    mMdp->setDownscale(dscale_factor);
+inline uint8_t Ctrl::getPriority() const {
+    return mMdp->getPriority();
 }
 
 inline void Ctrl::getDump(char *buf, size_t len) {
diff --git a/msm8226/liboverlay/overlayMdp.cpp b/msm8226/liboverlay/overlayMdp.cpp
index 3e26cdf..7f9f136 100644
--- a/msm8226/liboverlay/overlayMdp.cpp
+++ b/msm8226/liboverlay/overlayMdp.cpp
@@ -22,11 +22,6 @@
 #include "mdp_version.h"
 #include <overlay.h>
 
-#ifdef USES_QSEED_SCALAR
-#include <scale/scale.h>
-using namespace scale;
-#endif
-
 #define HSIC_SETTINGS_DEBUG 0
 
 using namespace qdutils;
@@ -59,7 +54,6 @@
     utils::memset0(mOVInfo);
     mOVInfo.id = MSMFB_NEW_REQUEST;
     mOrientation = utils::OVERLAY_TRANSFORM_0;
-    mDownscale = 0;
     mDpy = 0;
 #ifdef USES_POST_PROCESSING
     memset(&mParams, 0, sizeof(struct compute_params));
@@ -125,6 +119,23 @@
     mOrientation = static_cast<utils::eTransform>(rot);
 }
 
+void MdpCtrl::setPipeType(const utils::eMdpPipeType& pType){
+    switch((int) pType){
+        case utils::OV_MDP_PIPE_RGB:
+            mOVInfo.pipe_type = PIPE_TYPE_RGB;
+            break;
+        case utils::OV_MDP_PIPE_VG:
+            mOVInfo.pipe_type = PIPE_TYPE_VIG;
+            break;
+        case utils::OV_MDP_PIPE_DMA:
+            mOVInfo.pipe_type = PIPE_TYPE_DMA;
+            break;
+        default:
+            mOVInfo.pipe_type = PIPE_TYPE_AUTO;
+            break;
+    }
+}
+
 void MdpCtrl::doTransform() {
     setRotationFlags();
     utils::Whf whf = getSrcWhf();
@@ -135,39 +146,10 @@
 }
 
 void MdpCtrl::doDownscale() {
-    int mdpVersion = MDPVersion::getInstance().getMDPVersion();
-    if(mdpVersion < MDSS_V5) {
-        mOVInfo.src_rect.x >>= mDownscale;
-        mOVInfo.src_rect.y >>= mDownscale;
-        mOVInfo.src_rect.w >>= mDownscale;
-        mOVInfo.src_rect.h >>= mDownscale;
-    } else if(MDPVersion::getInstance().supportsDecimation()) {
-        //Decimation + MDP Downscale
-        mOVInfo.horz_deci = 0;
-        mOVInfo.vert_deci = 0;
-        int minHorDeci = 0;
-        if(mOVInfo.src_rect.w > 2048) {
-            //If the client sends us something > what a layer mixer supports
-            //then it means it doesn't want to use split-pipe but wants us to
-            //decimate. A minimum decimation of 2 will ensure that the width is
-            //always within layer mixer limits.
-            minHorDeci = 2;
-        }
-
-        float horDscale = 0.0f;
-        float verDscale = 0.0f;
-
+    if(MDPVersion::getInstance().supportsDecimation()) {
         utils::getDecimationFactor(mOVInfo.src_rect.w, mOVInfo.src_rect.h,
-                mOVInfo.dst_rect.w, mOVInfo.dst_rect.h, horDscale, verDscale);
-
-        if(horDscale < minHorDeci)
-            horDscale = minHorDeci;
-
-        if((int)horDscale)
-            mOVInfo.horz_deci = (int)log2f(horDscale);
-
-        if((int)verDscale)
-            mOVInfo.vert_deci = (int)log2f(verDscale);
+                mOVInfo.dst_rect.w, mOVInfo.dst_rect.h, mOVInfo.horz_deci,
+                mOVInfo.vert_deci);
     }
 }
 
@@ -187,6 +169,10 @@
             if (!(mOVInfo.flags & MDP_SOURCE_ROTATED_90) &&
                 (mOVInfo.src_rect.h % 4))
                 mOVInfo.src_rect.h = utils::aligndown(mOVInfo.src_rect.h, 4);
+            // For interlaced, width must be multiple of 4 when rotated 90deg.
+            else if ((mOVInfo.flags & MDP_SOURCE_ROTATED_90) &&
+                (mOVInfo.src_rect.w % 4))
+                mOVInfo.src_rect.w = utils::aligndown(mOVInfo.src_rect.w, 4);
         }
     } else {
         if (mdpVersion >= MDSS_V5) {
@@ -231,12 +217,6 @@
     ovutils::getDump(buf, len, "Data", mOvData);
 }
 
-void MdpCtrl3D::dump() const {
-    ALOGE("== Dump MdpCtrl start ==");
-    mFd.dump();
-    ALOGE("== Dump MdpCtrl end ==");
-}
-
 bool MdpCtrl::setVisualParams(const MetaData_t& data) {
     ALOGD_IF(0, "In %s: data.operation = %d", __FUNCTION__, data.operation);
 #ifdef USES_POST_PROCESSING
@@ -367,15 +347,15 @@
     list.num_overlays = count;
     list.overlay_list = ovArray;
 
-#ifdef USES_QSEED_SCALAR
-    Scale *scalar = Overlay::getScalar();
-    if(scalar) {
-        scalar->applyScale(&list);
+   int (*fnProgramScale)(struct mdp_overlay_list *) =
+        Overlay::getFnProgramScale();
+    if(fnProgramScale) {
+        fnProgramScale(&list);
     }
-#endif
 
     if(!mdp_wrapper::validateAndSet(fbFd, list)) {
-        if(list.processed_overlays < list.num_overlays) {
+        /* No dump for failure due to insufficient resource */
+        if(errno != E2BIG) {
             mdp_wrapper::dump("Bad ov dump: ",
                 *list.overlay_list[list.processed_overlays]);
         }
diff --git a/msm8226/liboverlay/overlayMdp.h b/msm8226/liboverlay/overlayMdp.h
index 843556b..cb8e057 100644
--- a/msm8226/liboverlay/overlayMdp.h
+++ b/msm8226/liboverlay/overlayMdp.h
@@ -64,8 +64,6 @@
     void setPosition(const utils::Dim& dim);
     /* using user_data, sets/unsets roationvalue in mdp flags */
     void setRotationFlags();
-    /* Performs downscale calculations */
-    void setDownscale(int dscale_factor);
     /* Update the src format with rotator's dest*/
     void updateSrcFormat(const uint32_t& rotDstFormat);
     /* dump state of the object */
@@ -80,8 +78,12 @@
     utils::Dim getDstRectDim() const;
     /* returns a copy to src rect dim */
     utils::Dim getSrcRectDim() const;
+    /* return pipe priority */
+    uint8_t getPriority() const;
     /* setVisualParam */
     bool setVisualParams(const MetaData_t& data);
+    /* sets pipe type RGB/DMA/VG */
+    void setPipeType(const utils::eMdpPipeType& pType);
 
     static bool validateAndSet(MdpCtrl* mdpCtrlArray[], const int& count,
             const int& fbFd);
@@ -121,7 +123,6 @@
     mdp_overlay   mOVInfo;
     /* FD for the mdp fbnum */
     OvFD          mFd;
-    int mDownscale;
     int mDpy;
 
 #ifdef USES_POST_PROCESSING
@@ -130,31 +131,6 @@
 #endif
 };
 
-
-/* MDP 3D related ctrl */
-class MdpCtrl3D {
-public:
-    /* ctor reset data */
-    MdpCtrl3D();
-    /* calls MSMFB_OVERLAY_3D */
-    bool close();
-    /* set w/h. format is ignored*/
-    void setWh(const utils::Whf& whf);
-    /* set is_3d calls MSMFB_OVERLAY_3D */
-    bool useVirtualFB();
-    /* set fd to be used in ioctl */
-    void setFd(int fd);
-    /* dump */
-    void dump() const;
-private:
-    /* reset */
-    void reset();
-    /* actual MSM 3D info */
-    msmfb_overlay_3d m3DOVInfo;
-    /* FD for the mdp 3D */
-    OvFD mFd;
-};
-
 /* MDP data */
 class MdpData {
 public:
@@ -232,10 +208,6 @@
     mOVInfo.is_fg = isFg;
 }
 
-inline void MdpCtrl::setDownscale(int dscale) {
-    mDownscale = dscale;
-}
-
 inline void MdpCtrl::setPlaneAlpha(int planeAlpha) {
     mOVInfo.alpha = planeAlpha;
 }
@@ -304,44 +276,8 @@
         mOVInfo.flags |= MDP_SOURCE_ROTATED_90;
 }
 
-///////    MdpCtrl3D //////
-
-inline MdpCtrl3D::MdpCtrl3D() { reset(); }
-inline bool MdpCtrl3D::close() {
-    if (m3DOVInfo.is_3d) {
-        m3DOVInfo.is_3d = 0;
-        if(!mdp_wrapper::set3D(mFd.getFD(), m3DOVInfo)) {
-            ALOGE("MdpCtrl3D close failed set3D with 0");
-            return false;
-        }
-    }
-    reset();
-    return true;
-}
-inline void MdpCtrl3D::reset() {
-    utils::memset0(m3DOVInfo);
-}
-
-inline void MdpCtrl3D::setFd(int fd) {
-    mFd.copy(fd);
-    OVASSERT(mFd.valid(), "MdpCtrl3D setFd, FD should be valid");
-}
-
-inline void MdpCtrl3D::setWh(const utils::Whf& whf) {
-    // ignore fmt. Needed for useVirtualFB callflow
-    m3DOVInfo.width = whf.w;
-    m3DOVInfo.height = whf.h;
-}
-
-inline bool MdpCtrl3D::useVirtualFB() {
-    if(!m3DOVInfo.is_3d) {
-        m3DOVInfo.is_3d = 1;
-        if(!mdp_wrapper::set3D(mFd.getFD(), m3DOVInfo)) {
-            ALOGE("MdpCtrl3D close failed set3D with 0");
-            return false;
-        }
-    }
-    return true;
+inline uint8_t MdpCtrl::getPriority() const {
+    return mOVInfo.priority;
 }
 
 ///////    MdpData   //////
diff --git a/msm8226/liboverlay/overlayMdpRot.cpp b/msm8226/liboverlay/overlayMdpRot.cpp
index 38b0a92..bb985d7 100755
--- a/msm8226/liboverlay/overlayMdpRot.cpp
+++ b/msm8226/liboverlay/overlayMdpRot.cpp
@@ -19,6 +19,7 @@
 
 #include "overlayUtils.h"
 #include "overlayRotator.h"
+#include "gr.h"
 
 namespace ovutils = overlay::utils;
 
@@ -33,7 +34,7 @@
 
 bool MdpRot::enabled() const { return mRotImgInfo.enable; }
 
-void MdpRot::setRotations(uint32_t r) { mRotImgInfo.rotations = r; }
+void MdpRot::setRotations(uint32_t r) { mRotImgInfo.rotations = (uint8_t)r; }
 
 int MdpRot::getDstMemId() const {
     return mRotDataInfo.dst.memory_id;
@@ -47,6 +48,24 @@
     return mRotImgInfo.dst.format;
 }
 
+//Added for completeness. Not expected to be called.
+utils::Whf MdpRot::getDstWhf() const {
+    int alW = 0, alH = 0;
+    int halFormat = ovutils::getHALFormat(mRotImgInfo.dst.format);
+    getBufferSizeAndDimensions(mRotImgInfo.dst.width, mRotImgInfo.dst.height,
+            halFormat, alW, alH);
+    return utils::Whf(alW, alH, mRotImgInfo.dst.format);
+}
+
+//Added for completeness. Not expected to be called.
+utils::Dim MdpRot::getDstDimensions() const {
+    int alW = 0, alH = 0;
+    int halFormat = ovutils::getHALFormat(mRotImgInfo.dst.format);
+    getBufferSizeAndDimensions(mRotImgInfo.dst.width, mRotImgInfo.dst.height,
+            halFormat, alW, alH);
+    return utils::Dim(0, 0, alW, alH);
+}
+
 uint32_t MdpRot::getSessId() const { return mRotImgInfo.session_id; }
 
 void MdpRot::setDownscale(int ds) {
diff --git a/msm8226/liboverlay/overlayMdssRot.cpp b/msm8226/liboverlay/overlayMdssRot.cpp
index ce9d9d5..5783dcb 100644
--- a/msm8226/liboverlay/overlayMdssRot.cpp
+++ b/msm8226/liboverlay/overlayMdssRot.cpp
@@ -37,6 +37,8 @@
 namespace ovutils = overlay::utils;
 
 namespace overlay {
+using namespace utils;
+
 MdssRot::MdssRot() {
     reset();
     init();
@@ -61,6 +63,21 @@
     return mRotInfo.src.format;
 }
 
+utils::Whf MdssRot::getDstWhf() const {
+    //For Mdss dst_rect itself represents buffer dimensions. We ignore actual
+    //aligned values during buffer allocation. Also the driver overwrites the
+    //src.format field if destination format is different.
+    //This implementation detail makes it possible to retrieve w,h even before
+    //buffer allocation, which happens in queueBuffer.
+    return utils::Whf(mRotInfo.dst_rect.w, mRotInfo.dst_rect.h,
+            mRotInfo.src.format);
+}
+
+utils::Dim MdssRot::getDstDimensions() const {
+    return utils::Dim(mRotInfo.dst_rect.x, mRotInfo.dst_rect.y,
+            mRotInfo.dst_rect.w, mRotInfo.dst_rect.h);
+}
+
 uint32_t MdssRot::getSessId() const { return mRotInfo.id; }
 
 bool MdssRot::init() {
@@ -80,16 +97,10 @@
 }
 
 void MdssRot::setCrop(const utils::Dim& crop) {
-
     mRotInfo.src_rect.x = crop.x;
     mRotInfo.src_rect.y = crop.y;
     mRotInfo.src_rect.w = crop.w;
     mRotInfo.src_rect.h = crop.h;
-
-    mRotInfo.dst_rect.x = 0;
-    mRotInfo.dst_rect.y = 0;
-    mRotInfo.dst_rect.w = crop.w;
-    mRotInfo.dst_rect.h = crop.h;
 }
 
 void MdssRot::setDownscale(int /*ds*/) {
@@ -117,7 +128,22 @@
 }
 
 bool MdssRot::commit() {
+    if (utils::isYuv(mRotInfo.src.format)) {
+        utils::normalizeCrop(mRotInfo.src_rect.x, mRotInfo.src_rect.w);
+        utils::normalizeCrop(mRotInfo.src_rect.y, mRotInfo.src_rect.h);
+        // For interlaced, crop.h should be 4-aligned
+        if ((mRotInfo.flags & utils::OV_MDP_DEINTERLACE) and
+                (mRotInfo.src_rect.h % 4))
+            mRotInfo.src_rect.h = utils::aligndown(mRotInfo.src_rect.h, 4);
+    }
+
+    mRotInfo.dst_rect.x = 0;
+    mRotInfo.dst_rect.y = 0;
+    mRotInfo.dst_rect.w = mRotInfo.src_rect.w;
+    mRotInfo.dst_rect.h = mRotInfo.src_rect.h;
+
     doTransform();
+
     mRotInfo.flags |= MDSS_MDP_ROT_ONLY;
     mEnabled = true;
     if(!overlay::mdp_wrapper::setOverlay(mFd.getFD(), mRotInfo)) {
@@ -265,19 +291,52 @@
 // Calculate the compressed o/p buffer size for BWC
 uint32_t MdssRot::calcCompressedBufSize(const ovutils::Whf& destWhf) {
     uint32_t bufSize = 0;
+    //Worst case alignments
     int aWidth = ovutils::align(destWhf.w, 64);
     int aHeight = ovutils::align(destWhf.h, 4);
-    int rau_cnt = aWidth/64;
-    int stride0 = (64 * 4 * rau_cnt) + rau_cnt/8;
-    int stride1 = ((64 * 2 * rau_cnt) + rau_cnt/8) * 2;
-    int stride0_off = (aHeight/4);
-    int stride1_off = (aHeight/2);
+    /*
+       Format           |   RAU size (width x height)
+       ----------------------------------------------
+       ARGB             |       32 pixel x 4 line
+       RGB888           |       32 pixel x 4 line
+       Y (Luma)         |       64 pixel x 4 line
+       CRCB 420         |       32 pixel x 2 line
+       CRCB 422 H2V1    |       32 pixel x 4 line
+       CRCB 422 H1V2    |       64 pixel x 2 line
 
-    //New o/p size for BWC
-    bufSize = (stride0 * stride0_off + stride1 * stride1_off) +
-                (rau_cnt * 2 * (stride0_off + stride1_off));
-    ALOGD_IF(DEBUG_MDSS_ROT, "%s: width = %d, height = %d raucount = %d"
-         "opBufSize = %d ", __FUNCTION__, aWidth, aHeight, rau_cnt, bufSize);
+       Metadata requirements:-
+       1 byte meta data for every 8 RAUs
+       2 byte meta data per RAU
+     */
+
+    //These blocks attempt to allocate for the worst case in each of the
+    //respective format classes, yuv/rgb. The table above is for reference
+    if(utils::isYuv(destWhf.format)) {
+        int yRauCount = aWidth / 64; //Y
+        int cRauCount = aWidth / 32; //C
+        int yStride = (64 * 4 * yRauCount) + alignup(yRauCount, 8) / 8;
+        int cStride = ((32 * 2 * cRauCount) + alignup(cRauCount, 8) / 8) * 2;
+        int yStrideOffset = (aHeight / 4);
+        int cStrideOffset = (aHeight / 2);
+        bufSize = (yStride * yStrideOffset + cStride * cStrideOffset) +
+                (yRauCount * yStrideOffset * 2) +
+                (cRauCount * cStrideOffset * 2) * 2;
+        ALOGD_IF(DEBUG_MDSS_ROT, "%s:YUV Y RAU Count = %d C RAU Count = %d",
+                __FUNCTION__, yRauCount, cRauCount);
+    } else {
+        int rauCount = aWidth / 32;
+        //Single plane
+        int stride = (32 * 4 * rauCount) + alignup(rauCount, 8) / 8;
+        int strideOffset = (aHeight / 4);
+        bufSize = (stride * strideOffset * 4 /*bpp*/) +
+            (rauCount * strideOffset * 2);
+        ALOGD_IF(DEBUG_MDSS_ROT, "%s:RGB RAU count = %d", __FUNCTION__,
+                rauCount);
+    }
+
+    ALOGD_IF(DEBUG_MDSS_ROT, "%s: aligned width = %d, aligned height = %d "
+            "Buf Size = %d", __FUNCTION__, aWidth, aHeight, bufSize);
+
     return bufSize;
 }
 
diff --git a/msm8226/liboverlay/overlayRotator.cpp b/msm8226/liboverlay/overlayRotator.cpp
index 43b2877..99efc5d 100644
--- a/msm8226/liboverlay/overlayRotator.cpp
+++ b/msm8226/liboverlay/overlayRotator.cpp
@@ -146,7 +146,7 @@
     //Return a rot object, creating one if necessary
     overlay::Rotator *rot = NULL;
     if(mUseCount >= MAX_ROT_SESS) {
-        ALOGE("%s, MAX rotator sessions reached", __func__);
+        ALOGW("%s, MAX rotator sessions reached, request rejected", __func__);
     } else {
         if(mRot[mUseCount] == NULL)
             mRot[mUseCount] = overlay::Rotator::getRotator();
diff --git a/msm8226/liboverlay/overlayRotator.h b/msm8226/liboverlay/overlayRotator.h
index 53c54e6..64387cd 100644
--- a/msm8226/liboverlay/overlayRotator.h
+++ b/msm8226/liboverlay/overlayRotator.h
@@ -74,9 +74,14 @@
     virtual void setTransform(const utils::eTransform& rot) = 0;
     virtual bool commit() = 0;
     virtual void setDownscale(int ds) = 0;
+    //Mem id and offset should be retrieved only after rotator kickoff
     virtual int getDstMemId() const = 0;
     virtual uint32_t getDstOffset() const = 0;
+    //Destination width, height, format, position should be retrieved only after
+    //rotator configuration is committed via commit API
     virtual uint32_t getDstFormat() const = 0;
+    virtual utils::Whf getDstWhf() const = 0;
+    virtual utils::Dim getDstDimensions() const = 0;
     virtual uint32_t getSessId() const = 0;
     virtual bool queueBuffer(int fd, uint32_t offset) = 0;
     virtual void dump() const = 0;
@@ -112,6 +117,8 @@
     virtual int getDstMemId() const;
     virtual uint32_t getDstOffset() const;
     virtual uint32_t getDstFormat() const;
+    virtual utils::Whf getDstWhf() const;
+    virtual utils::Dim getDstDimensions() const;
     virtual uint32_t getSessId() const;
     virtual bool queueBuffer(int fd, uint32_t offset);
     virtual void dump() const;
@@ -169,6 +176,8 @@
     virtual int getDstMemId() const;
     virtual uint32_t getDstOffset() const;
     virtual uint32_t getDstFormat() const;
+    virtual utils::Whf getDstWhf() const;
+    virtual utils::Dim getDstDimensions() const;
     virtual uint32_t getSessId() const;
     virtual bool queueBuffer(int fd, uint32_t offset);
     virtual void dump() const;
@@ -210,9 +219,10 @@
 // Holder of rotator objects. Manages lifetimes
 class RotMgr {
 public:
-    //Maximum sessions based on VG pipes, since rotator is used only for videos.
-    //Even though we can have 4 mixer stages, that much may be unnecessary.
-    enum { MAX_ROT_SESS = 3 };
+    //Virtually we can support as many rotator sessions as possible, However
+    // more number of rotator sessions leads to performance issues, so
+    // restricting the max rotator session to 4
+    enum { MAX_ROT_SESS = 4 };
 
     ~RotMgr();
     void configBegin();
diff --git a/msm8226/liboverlay/overlayUtils.cpp b/msm8226/liboverlay/overlayUtils.cpp
index ddba868..0e063ab 100644
--- a/msm8226/liboverlay/overlayUtils.cpp
+++ b/msm8226/liboverlay/overlayUtils.cpp
@@ -74,12 +74,6 @@
 //----------From class Res ------------------------------
 const char* const Res::fbPath = "/dev/graphics/fb%u";
 const char* const Res::rotPath = "/dev/msm_rotator";
-const char* const Res::format3DFile =
-        "/sys/class/graphics/fb1/format_3d";
-const char* const Res::edid3dInfoFile =
-        "/sys/class/graphics/fb1/3d_present";
-const char* const Res::barrierFile =
-        "/sys/devices/platform/mipi_novatek.0/enable_3d_barrier";
 //--------------------------------------------------------
 
 
@@ -284,16 +278,13 @@
     return dscale_factor;
 }
 
-//Since this is unavailable on Android, defining it in terms of base 10
-static inline float log2f(const float& x) {
-    return log(x) / log(2);
-}
-
 void getDecimationFactor(const int& src_w, const int& src_h,
-        const int& dst_w, const int& dst_h, float& horDscale,
-        float& verDscale) {
-    horDscale = ceilf((float)src_w / (float)dst_w);
-    verDscale = ceilf((float)src_h / (float)dst_h);
+        const int& dst_w, const int& dst_h, uint8_t& horzDeci,
+        uint8_t& vertDeci) {
+    horzDeci = 0;
+    vertDeci = 0;
+    float horDscale = ceilf((float)src_w / (float)dst_w);
+    float verDscale = ceilf((float)src_h / (float)dst_h);
 
     //Next power of 2, if not already
     horDscale = powf(2.0f, ceilf(log2f(horDscale)));
@@ -303,6 +294,21 @@
     //between decimator and MDP downscale
     horDscale /= 4.0f;
     verDscale /= 4.0f;
+
+    if((int)horDscale)
+        horzDeci = (uint8_t)log2f(horDscale);
+
+    if((int)verDscale)
+        vertDeci = (uint8_t)log2f(verDscale);
+
+    if(src_w > 2048) {
+        //If the client sends us something > what a layer mixer supports
+        //then it means it doesn't want to use split-pipe but wants us to
+        //decimate. A minimum decimation of 2 will ensure that the width is
+        //always within layer mixer limits.
+        if(horzDeci < 2)
+            horzDeci = 2;
+    }
 }
 
 static inline int compute(const uint32_t& x, const uint32_t& y,
@@ -328,86 +334,6 @@
     }
 }
 
-bool is3DTV() {
-    char is3DTV = '0';
-    IOFile fp(Res::edid3dInfoFile, "r");
-    (void)fp.read(is3DTV, 1);
-    ALOGI("3DTV EDID flag: %d", is3DTV);
-    return (is3DTV == '0') ? false : true;
-}
-
-bool isPanel3D() {
-    OvFD fd;
-    if(!overlay::open(fd, 0 /*fb*/, Res::fbPath)){
-        ALOGE("isPanel3D Can't open framebuffer 0");
-        return false;
-    }
-    fb_fix_screeninfo finfo;
-    if(!mdp_wrapper::getFScreenInfo(fd.getFD(), finfo)) {
-        ALOGE("isPanel3D read fb0 failed");
-    }
-    fd.close();
-    return (FB_TYPE_3D_PANEL == finfo.type) ? true : false;
-}
-
-bool usePanel3D() {
-    if(!isPanel3D())
-        return false;
-    char value[PROPERTY_VALUE_MAX];
-    property_get("persist.user.panel3D", value, "0");
-    int usePanel3D = atoi(value);
-    return usePanel3D ? true : false;
-}
-
-bool send3DInfoPacket (uint32_t format3D) {
-    IOFile fp(Res::format3DFile, "wb");
-    (void)fp.write("%d", format3D);
-    if(!fp.valid()) {
-        ALOGE("send3DInfoPacket: no sysfs entry for setting 3d mode");
-        return false;
-    }
-    return true;
-}
-
-bool enableBarrier (uint32_t orientation) {
-    IOFile fp(Res::barrierFile, "wb");
-    (void)fp.write("%d", orientation);
-    if(!fp.valid()) {
-        ALOGE("enableBarrier no sysfs entry for "
-                "enabling barriers on 3D panel");
-        return false;
-    }
-    return true;
-}
-
-uint32_t getS3DFormat(uint32_t fmt) {
-    // The S3D is part of the HAL_PIXEL_FORMAT_YV12 value. Add
-    // an explicit check for the format
-    if (fmt == HAL_PIXEL_FORMAT_YV12) {
-        return 0;
-    }
-    uint32_t fmt3D = format3D(fmt);
-    uint32_t fIn3D = format3DInput(fmt3D); // MSB 2 bytes - inp
-    uint32_t fOut3D = format3DOutput(fmt3D); // LSB 2 bytes - out
-    fmt3D = fIn3D | fOut3D;
-    if (!fIn3D) {
-        fmt3D |= fOut3D << SHIFT_TOT_3D; //Set the input format
-    }
-    if (!fOut3D) {
-        switch (fIn3D) {
-            case HAL_3D_IN_SIDE_BY_SIDE_L_R:
-            case HAL_3D_IN_SIDE_BY_SIDE_R_L:
-                // For all side by side formats, set the output
-                // format as Side-by-Side i.e 0x1
-                fmt3D |= HAL_3D_IN_SIDE_BY_SIDE_L_R >> SHIFT_TOT_3D;
-                break;
-            default:
-                fmt3D |= fIn3D >> SHIFT_TOT_3D; //Set the output format
-        }
-    }
-    return fmt3D;
-}
-
 void getDump(char *buf, size_t len, const char *prefix,
         const mdp_overlay& ov) {
     char str[256] = {'\0'};
diff --git a/msm8226/liboverlay/overlayUtils.h b/msm8226/liboverlay/overlayUtils.h
index c2649f3..530377b 100644
--- a/msm8226/liboverlay/overlayUtils.h
+++ b/msm8226/liboverlay/overlayUtils.h
@@ -120,40 +120,9 @@
     const NoCopy& operator=(const NoCopy&);
 };
 
-
-/* 3D related utils, defines etc...
- * The compound format passed to the overlay is
- * ABCCC where A is the input 3D format
- * B is the output 3D format
- * CCC is the color format e.g YCbCr420SP YCrCb420SP etc */
-enum { SHIFT_OUT_3D = 12,
-    SHIFT_TOT_3D = 16 };
-enum { INPUT_3D_MASK = 0xFFFF0000,
-    OUTPUT_3D_MASK = 0x0000FFFF };
-enum { BARRIER_LAND = 1,
-    BARRIER_PORT = 2 };
-
-inline uint32_t format3D(uint32_t x) { return x & 0xFF000; }
-inline uint32_t format3DOutput(uint32_t x) {
-    return (x & 0xF000) >> SHIFT_OUT_3D; }
-inline uint32_t format3DInput(uint32_t x) { return x & 0xF0000; }
-
-bool isHDMIConnected ();
-bool is3DTV();
-bool isPanel3D();
-bool usePanel3D();
-bool send3DInfoPacket (uint32_t fmt);
-bool enableBarrier (uint32_t orientation);
-uint32_t getS3DFormat(uint32_t fmt);
 bool isMdssRotator();
 void normalizeCrop(uint32_t& xy, uint32_t& wh);
 
-template <int CHAN>
-bool getPositionS3D(const Whf& whf, Dim& out);
-
-template <int CHAN>
-bool getCropS3D(const Dim& in, Dim& out, uint32_t fmt);
-
 template <class Type>
 void swapWidthHeight(Type& width, Type& height);
 
@@ -413,8 +382,8 @@
 int getDownscaleFactor(const int& src_w, const int& src_h,
         const int& dst_w, const int& dst_h);
 void getDecimationFactor(const int& src_w, const int& src_h,
-        const int& dst_w, const int& dst_h, float& horDscale,
-        float& verDscale);
+        const int& dst_w, const int& dst_h, uint8_t& horzDeci,
+        uint8_t& vertDeci);
 
 /* flip is upside down and such. V, H flip
  * rotation is 90, 180 etc
@@ -446,39 +415,6 @@
     return a ? ((value + (a-1)) & ~(a-1)) : value;
 }
 
-enum eRotOutFmt {
-    ROT_OUT_FMT_DEFAULT,
-    ROT_OUT_FMT_Y_CRCB_H2V2
-};
-
-template <int ROT_OUT_FMT> struct RotOutFmt;
-
-// FIXME, taken from gralloc_priv.h. Need to
-// put it back as soon as overlay takes place of the old one
-/* possible formats for 3D content*/
-enum {
-    HAL_NO_3D                         = 0x0000,
-    HAL_3D_IN_SIDE_BY_SIDE_L_R        = 0x10000,
-    HAL_3D_IN_TOP_BOTTOM              = 0x20000,
-    HAL_3D_IN_INTERLEAVE              = 0x40000,
-    HAL_3D_IN_SIDE_BY_SIDE_R_L        = 0x80000,
-    HAL_3D_OUT_SIDE_BY_SIDE           = 0x1000,
-    HAL_3D_OUT_TOP_BOTTOM             = 0x2000,
-    HAL_3D_OUT_INTERLEAVE             = 0x4000,
-    HAL_3D_OUT_MONOSCOPIC             = 0x8000
-};
-
-enum { HAL_3D_OUT_SBS_MASK =
-    HAL_3D_OUT_SIDE_BY_SIDE >> overlay::utils::SHIFT_OUT_3D,
-    HAL_3D_OUT_TOP_BOT_MASK =
-            HAL_3D_OUT_TOP_BOTTOM >> overlay::utils::SHIFT_OUT_3D,
-    HAL_3D_OUT_INTERL_MASK =
-            HAL_3D_OUT_INTERLEAVE >> overlay::utils::SHIFT_OUT_3D,
-    HAL_3D_OUT_MONOS_MASK =
-            HAL_3D_OUT_MONOSCOPIC >> overlay::utils::SHIFT_OUT_3D
-};
-
-
 inline bool isYuv(uint32_t format) {
     switch(format){
         case MDP_Y_CBCR_H2V1:
@@ -577,105 +513,6 @@
     ALOGE("== Dump Dim x=%d y=%d w=%d h=%d start/end ==", x, y, w, h);
 }
 
-// FB0
-template <int CHAN>
-inline Dim getPositionS3DImpl(const Whf& whf)
-{
-    switch (whf.format & OUTPUT_3D_MASK)
-    {
-        case HAL_3D_OUT_SBS_MASK:
-            // x, y, w, h
-            return Dim(0, 0, whf.w/2, whf.h);
-        case HAL_3D_OUT_TOP_BOT_MASK:
-            return Dim(0, 0, whf.w, whf.h/2);
-        case HAL_3D_OUT_MONOS_MASK:
-            return Dim();
-        case HAL_3D_OUT_INTERL_MASK:
-            // FIXME error?
-            ALOGE("%s HAL_3D_OUT_INTERLEAVE_MASK", __FUNCTION__);
-            return Dim();
-        default:
-            ALOGE("%s Unsupported 3D output format %d", __FUNCTION__,
-                    whf.format);
-    }
-    return Dim();
-}
-
-template <>
-inline Dim getPositionS3DImpl<utils::OV_RIGHT_SPLIT>(const Whf& whf)
-{
-    switch (whf.format & OUTPUT_3D_MASK)
-    {
-        case HAL_3D_OUT_SBS_MASK:
-            return Dim(whf.w/2, 0, whf.w/2, whf.h);
-        case HAL_3D_OUT_TOP_BOT_MASK:
-            return Dim(0, whf.h/2, whf.w, whf.h/2);
-        case HAL_3D_OUT_MONOS_MASK:
-            return Dim(0, 0, whf.w, whf.h);
-        case HAL_3D_OUT_INTERL_MASK:
-            // FIXME error?
-            ALOGE("%s HAL_3D_OUT_INTERLEAVE_MASK", __FUNCTION__);
-            return Dim();
-        default:
-            ALOGE("%s Unsupported 3D output format %d", __FUNCTION__,
-                    whf.format);
-    }
-    return Dim();
-}
-
-template <int CHAN>
-inline bool getPositionS3D(const Whf& whf, Dim& out) {
-    out = getPositionS3DImpl<CHAN>(whf);
-    return (out != Dim());
-}
-
-template <int CHAN>
-inline Dim getCropS3DImpl(const Dim& in, uint32_t fmt) {
-    switch (fmt & INPUT_3D_MASK)
-    {
-        case HAL_3D_IN_SIDE_BY_SIDE_L_R:
-            return Dim(0, 0, in.w/2, in.h);
-        case HAL_3D_IN_SIDE_BY_SIDE_R_L:
-            return Dim(in.w/2, 0, in.w/2, in.h);
-        case HAL_3D_IN_TOP_BOTTOM:
-            return Dim(0, 0, in.w, in.h/2);
-        case HAL_3D_IN_INTERLEAVE:
-            ALOGE("%s HAL_3D_IN_INTERLEAVE", __FUNCTION__);
-            break;
-        default:
-            ALOGE("%s Unsupported 3D format %d", __FUNCTION__, fmt);
-            break;
-    }
-    return Dim();
-}
-
-template <>
-inline Dim getCropS3DImpl<utils::OV_RIGHT_SPLIT>(const Dim& in, uint32_t fmt) {
-    switch (fmt & INPUT_3D_MASK)
-    {
-        case HAL_3D_IN_SIDE_BY_SIDE_L_R:
-            return Dim(in.w/2, 0, in.w/2, in.h);
-        case HAL_3D_IN_SIDE_BY_SIDE_R_L:
-            return Dim(0, 0, in.w/2, in.h);
-        case HAL_3D_IN_TOP_BOTTOM:
-            return Dim(0, in.h/2, in.w, in.h/2);
-        case HAL_3D_IN_INTERLEAVE:
-            ALOGE("%s HAL_3D_IN_INTERLEAVE", __FUNCTION__);
-            break;
-        default:
-            ALOGE("%s Unsupported 3D format %d", __FUNCTION__, fmt);
-            break;
-    }
-    return Dim();
-}
-
-template <int CHAN>
-inline bool getCropS3D(const Dim& in, Dim& out, uint32_t fmt)
-{
-    out = getCropS3DImpl<CHAN>(in, fmt);
-    return (out != Dim());
-}
-
 template <class Type>
 void swapWidthHeight(Type& width, Type& height) {
     Type tmp = width;
@@ -706,6 +543,14 @@
         value--;
 }
 
+/* Prerotation adjusts crop co-ordinates to the new transformed values within
+ * destination buffer. This is necessary only when the entire buffer is rotated
+ * irrespective of crop (A-family). If only the crop portion of the buffer is
+ * rotated into a destination buffer matching the size of crop, we don't need to
+ * use this helper (B-family).
+ * @Deprecated as of now, retained for the case where a full buffer needs
+ * transform and also as a reference.
+ */
 void preRotateSource(const eTransform& tr, Whf& whf, Dim& srcCrop);
 void getDump(char *buf, size_t len, const char *prefix, const mdp_overlay& ov);
 void getDump(char *buf, size_t len, const char *prefix, const msmfb_img& ov);
@@ -728,12 +573,6 @@
     static const char* const fbPath;
     // /dev/msm_rotator
     static const char* const rotPath;
-    // /sys/class/graphics/fb1/format_3d
-    static const char* const format3DFile;
-    // /sys/class/graphics/fb1/3d_present
-    static const char* const edid3dInfoFile;
-    // /sys/devices/platform/mipi_novatek.0/enable_3d_barrier
-    static const char* const barrierFile;
 };
 
 
diff --git a/msm8226/liboverlay/pipes/overlay3DPipe.h b/msm8226/liboverlay/pipes/overlay3DPipe.h
deleted file mode 100644
index 4e5630e..0000000
--- a/msm8226/liboverlay/pipes/overlay3DPipe.h
+++ /dev/null
@@ -1,465 +0,0 @@
-/*
-* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted provided that the following conditions are
-* met:
-*    * Redistributions of source code must retain the above copyright
-*      notice, this list of conditions and the following disclaimer.
-*    * Redistributions in binary form must reproduce the above
-*      copyright notice, this list of conditions and the following
-*      disclaimer in the documentation and/or other materials provided
-*      with the distribution.
-*    * Neither the name of The Linux Foundation nor the names of its
-*      contributors may be used to endorse or promote products derived
-*      from this software without specific prior written permission.
-*
-* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
-* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
-* ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
-* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
-* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
-* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
-* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
-
-#ifndef OVERLAY_M3D_EXT_PIPE_H
-#define OVERLAY_M3D_EXT_PIPE_H
-
-#include "overlayGenPipe.h"
-#include "overlayUtils.h"
-
-namespace overlay {
-
-/////////////  M3DExt Pipe ////////////////////////////
-/**
-* A specific impl of GenericPipe for 3D.
-* Whenever needed to have a pass through - we do it.
-* If there is a special need for special/diff behavior
-* do it here
-* PANEL is always EXTERNAL for this pipe.
-* CHAN = 0,1 it's either Channel 1 or channel 2 needed for
-* 3D crop and position */
-template <int CHAN>
-class M3DExtPipe : utils::NoCopy {
-public:
-    /* Please look at overlayGenPipe.h for info */
-    explicit M3DExtPipe();
-    ~M3DExtPipe();
-    bool init(RotatorBase* rot);
-    bool close();
-    bool commit();
-    bool queueBuffer(int fd, uint32_t offset);
-    bool setCrop(const utils::Dim& d);
-    bool setPosition(const utils::Dim& dim);
-    bool setTransform(const utils::eTransform& param);
-    bool setSource(const utils::PipeArgs& args);
-    void dump() const;
-private:
-    overlay::GenericPipe<utils::EXTERNAL> mM3d;
-    // Cache the M3D format
-    uint32_t mM3Dfmt;
-};
-
-/////////////  M3DPrimary Pipe ////////////////////////////
-/**
-* A specific impl of GenericPipe for 3D.
-* Whenever needed to have a pass through - we do it.
-* If there is a special need for special/diff behavior
-* do it here
-* PANEL is always PRIMARY for this pipe.
-* CHAN = 0,1 it's either Channel 1 or channel 2 needed for
-* 3D crop and position */
-template <int CHAN>
-class M3DPrimaryPipe : utils::NoCopy {
-public:
-    /* Please look at overlayGenPipe.h for info */
-    explicit M3DPrimaryPipe();
-    ~M3DPrimaryPipe();
-    bool init(RotatorBase* rot);
-    bool close();
-    bool commit();
-    bool queueBuffer(int fd, uint32_t offset);
-    bool setCrop(const utils::Dim& d);
-    bool setPosition(const utils::Dim& dim);
-    bool setTransform(const utils::eTransform& param);
-    bool setSource(const utils::PipeArgs& args);
-    void dump() const;
-private:
-    overlay::GenericPipe<utils::PRIMARY> mM3d;
-    // Cache the M3D format
-    uint32_t mM3Dfmt;
-};
-
-/////////////  S3DExt Pipe ////////////////////////////////
-/**
-* A specific impl of GenericPipe for 3D.
-* Whenever needed to have a pass through - we do it.
-* If there is a special need for special/diff behavior
-* do it here.
-* PANEL is always EXTERNAL for this pipe.
-* CHAN = 0,1 it's either Channel 1 or channel 2 needed for
-* 3D crop and position */
-template <int CHAN>
-class S3DExtPipe : utils::NoCopy {
-public:
-    /* Please look at overlayGenPipe.h for info */
-    explicit S3DExtPipe();
-    ~S3DExtPipe();
-    bool init(RotatorBase* rot);
-    bool close();
-    bool commit();
-    bool queueBuffer(int fd, uint32_t offset);
-    bool setCrop(const utils::Dim& d);
-    bool setPosition(const utils::Dim& dim);
-    bool setTransform(const utils::eTransform& param);
-    bool setSource(const utils::PipeArgs& args);
-    void dump() const;
-private:
-    overlay::GenericPipe<utils::EXTERNAL> mS3d;
-    // Cache the 3D format
-    uint32_t mS3Dfmt;
-};
-
-/////////////  S3DPrimary Pipe ////////////////////////////
-/**
-* A specific impl of GenericPipe for 3D.
-* Whenever needed to have a pass through - we do it.
-* If there is a special need for special/diff behavior
-* do it here
-* PANEL is always PRIMARY for this pipe.
-* CHAN = 0,1 it's either Channel 1 or channel 2 needed for
-* 3D crop and position */
-template <int CHAN>
-class S3DPrimaryPipe : utils::NoCopy {
-public:
-    /* Please look at overlayGenPipe.h for info */
-    explicit S3DPrimaryPipe();
-    ~S3DPrimaryPipe();
-    bool init(RotatorBase* rot);
-    bool close();
-    bool commit();
-    bool queueBuffer(int fd, uint32_t offset);
-    bool setCrop(const utils::Dim& d);
-    bool setPosition(const utils::Dim& dim);
-    bool setTransform(const utils::eTransform& param);
-    bool setSource(const utils::PipeArgs& args);
-    void dump() const;
-private:
-    /* needed for 3D related IOCTL */
-    MdpCtrl3D mCtrl3D;
-    overlay::GenericPipe<utils::PRIMARY> mS3d;
-    // Cache the 3D format
-    uint32_t mS3Dfmt;
-};
-
-
-
-
-//------------------------Inlines and Templates--------------------------
-
-
-/////////////  M3DExt Pipe ////////////////////////////
-template <int CHAN>
-inline M3DExtPipe<CHAN>::M3DExtPipe() : mM3Dfmt(0) {}
-template <int CHAN>
-inline M3DExtPipe<CHAN>::~M3DExtPipe() { close(); }
-template <int CHAN>
-inline bool M3DExtPipe<CHAN>::init(RotatorBase* rot) {
-    ALOGE_IF(DEBUG_OVERLAY, "M3DExtPipe init");
-    if(!mM3d.init(rot)) {
-        ALOGE("3Dpipe failed to init");
-        return false;
-    }
-    return true;
-}
-template <int CHAN>
-inline bool M3DExtPipe<CHAN>::close() {
-    return mM3d.close();
-}
-template <int CHAN>
-inline bool M3DExtPipe<CHAN>::commit() { return mM3d.commit(); }
-template <int CHAN>
-inline bool M3DExtPipe<CHAN>::queueBuffer(int fd, uint32_t offset) {
-    return mM3d.queueBuffer(fd, offset);
-}
-template <int CHAN>
-inline bool M3DExtPipe<CHAN>::setCrop(const utils::Dim& d) {
-    utils::Dim _dim;
-    if(!utils::getCropS3D<CHAN>(d, _dim, mM3Dfmt)){
-        ALOGE("M3DExtPipe setCrop failed to getCropS3D");
-        _dim = d;
-    }
-    return mM3d.setCrop(_dim);
-}
-
-template <int CHAN>
-inline bool M3DExtPipe<CHAN>::setPosition(const utils::Dim& d) {
-    utils::Dim _dim;
-    // original setPositionHandleState has getPositionS3D(...,true)
-    // which means format is HAL_3D_OUT_SBS_MASK
-    // HAL_3D_OUT_SBS_MASK is 0x1000 >> 12 == 0x1 as the orig
-    // code suggets
-    utils::Whf _whf(mM3d.getScreenInfo().mFBWidth,
-            mM3d.getScreenInfo().mFBHeight,
-            mM3Dfmt);
-    if(!utils::getPositionS3D<CHAN>(_whf, _dim)) {
-        ALOGE("S3DPrimaryPipe setPosition err in getPositionS3D");
-        _dim = d;
-    }
-    return mM3d.setPosition(_dim);
-}
-template <int CHAN>
-inline bool M3DExtPipe<CHAN>::setTransform(const utils::eTransform& param) {
-    return mM3d.setTransform(param);
-}
-template <int CHAN>
-inline bool M3DExtPipe<CHAN>::setSource(const utils::PipeArgs& args)
-{
-    // extract 3D fmt
-    mM3Dfmt = utils::format3DInput(utils::getS3DFormat(args.whf.format)) |
-            utils::HAL_3D_OUT_MONOS_MASK;
-    return mM3d.setSource(args);
-}
-template <int CHAN>
-inline void M3DExtPipe<CHAN>::dump() const {
-    ALOGE("M3DExtPipe Pipe fmt=%d", mM3Dfmt);
-    mM3d.dump();
-}
-
-
-/////////////  M3DPrimary Pipe ////////////////////////////
-template <int CHAN>
-inline M3DPrimaryPipe<CHAN>::M3DPrimaryPipe() : mM3Dfmt(0) {}
-template <int CHAN>
-inline M3DPrimaryPipe<CHAN>::~M3DPrimaryPipe() { close(); }
-template <int CHAN>
-inline bool M3DPrimaryPipe<CHAN>::init(RotatorBase* rot) {
-    ALOGE_IF(DEBUG_OVERLAY, "M3DPrimaryPipe init");
-    if(!mM3d.init(rot)) {
-        ALOGE("3Dpipe failed to init");
-        return false;
-    }
-    return true;
-}
-template <int CHAN>
-inline bool M3DPrimaryPipe<CHAN>::close() {
-    return mM3d.close();
-}
-template <int CHAN>
-inline bool M3DPrimaryPipe<CHAN>::commit() { return mM3d.commit(); }
-template <int CHAN>
-inline bool M3DPrimaryPipe<CHAN>::queueBuffer(int fd, uint32_t offset) {
-    return mM3d.queueBuffer(fd, offset);
-}
-template <int CHAN>
-inline bool M3DPrimaryPipe<CHAN>::setCrop(const utils::Dim& d) {
-    utils::Dim _dim;
-    if(!utils::getCropS3D<CHAN>(d, _dim, mM3Dfmt)){
-        ALOGE("M3DPrimaryPipe setCrop failed to getCropS3D");
-        _dim = d;
-    }
-    return mM3d.setCrop(_dim);
-}
-template <int CHAN>
-inline bool M3DPrimaryPipe<CHAN>::setPosition(const utils::Dim& d) {
-    return mM3d.setPosition(d);
-}
-template <int CHAN>
-inline bool M3DPrimaryPipe<CHAN>::setTransform(const utils::eTransform& param) {
-    return mM3d.setTransform(param);
-}
-template <int CHAN>
-inline bool M3DPrimaryPipe<CHAN>::setSource(const utils::PipeArgs& args)
-{
-    // extract 3D fmt
-    mM3Dfmt = utils::format3DInput(utils::getS3DFormat(args.whf.format)) |
-            utils::HAL_3D_OUT_MONOS_MASK;
-    return mM3d.setSource(args);
-}
-template <int CHAN>
-inline void M3DPrimaryPipe<CHAN>::dump() const {
-    ALOGE("M3DPrimaryPipe Pipe fmt=%d", mM3Dfmt);
-    mM3d.dump();
-}
-
-/////////////  S3DExt Pipe ////////////////////////////////
-template <int CHAN>
-inline S3DExtPipe<CHAN>::S3DExtPipe() : mS3Dfmt(0) {}
-template <int CHAN>
-inline S3DExtPipe<CHAN>::~S3DExtPipe() { close(); }
-template <int CHAN>
-inline bool S3DExtPipe<CHAN>::init(RotatorBase* rot) {
-    ALOGE_IF(DEBUG_OVERLAY, "S3DExtPipe init");
-    if(!mS3d.init(rot)) {
-        ALOGE("3Dpipe failed to init");
-        return false;
-    }
-    return true;
-}
-template <int CHAN>
-inline bool S3DExtPipe<CHAN>::close() {
-    if(!utils::send3DInfoPacket(0)) {
-        ALOGE("S3DExtPipe close failed send3D info packet");
-    }
-    return mS3d.close();
-}
-template <int CHAN>
-inline bool S3DExtPipe<CHAN>::commit() { return mS3d.commit(); }
-template <int CHAN>
-inline bool S3DExtPipe<CHAN>::queueBuffer(int fd, uint32_t offset) {
-    return mS3d.queueBuffer(fd, offset);
-}
-template <int CHAN>
-inline bool S3DExtPipe<CHAN>::setCrop(const utils::Dim& d) {
-    utils::Dim _dim;
-    if(!utils::getCropS3D<CHAN>(d, _dim, mS3Dfmt)){
-        ALOGE("S3DExtPipe setCrop failed to getCropS3D");
-        _dim = d;
-    }
-    return mS3d.setCrop(_dim);
-}
-template <int CHAN>
-inline bool S3DExtPipe<CHAN>::setPosition(const utils::Dim& d)
-{
-    utils::Dim _dim;
-    utils::Whf _whf(mS3d.getScreenInfo().mFBWidth,
-            mS3d.getScreenInfo().mFBHeight,
-            mS3Dfmt);
-    if(!utils::getPositionS3D<CHAN>(_whf, _dim)) {
-        ALOGE("S3DExtPipe setPosition err in getPositionS3D");
-        _dim = d;
-    }
-    return mS3d.setPosition(_dim);
-}
-template <int CHAN>
-inline bool S3DExtPipe<CHAN>::setTransform(const utils::eTransform& param) {
-    return mS3d.setTransform(param);
-}
-template <int CHAN>
-inline bool S3DExtPipe<CHAN>::setSource(const utils::PipeArgs& args) {
-    mS3Dfmt = utils::getS3DFormat(args.whf.format);
-    return mS3d.setSource(args);
-}
-template <int CHAN>
-inline void S3DExtPipe<CHAN>::dump() const {
-    ALOGE("S3DExtPipe Pipe fmt=%d", mS3Dfmt);
-    mS3d.dump();
-}
-
-/////////////  S3DPrimary Pipe ////////////////////////////
-template <int CHAN>
-inline S3DPrimaryPipe<CHAN>::S3DPrimaryPipe() : mS3Dfmt(0) {}
-template <int CHAN>
-inline S3DPrimaryPipe<CHAN>::~S3DPrimaryPipe() { close(); }
-template <int CHAN>
-inline bool S3DPrimaryPipe<CHAN>::init(RotatorBase* rot) {
-    ALOGE_IF(DEBUG_OVERLAY, "S3DPrimaryPipe init");
-    if(!mS3d.init(rot)) {
-        ALOGE("3Dpipe failed to init");
-        return false;
-    }
-    // set the ctrl fd
-    mCtrl3D.setFd(mS3d.getCtrlFd());
-    return true;
-}
-template <int CHAN>
-inline bool S3DPrimaryPipe<CHAN>::close() {
-    if(!utils::enableBarrier(0)) {
-        ALOGE("S3DExtPipe close failed enable barrier");
-    }
-    mCtrl3D.close();
-    return mS3d.close();
-}
-
-template <int CHAN>
-inline bool S3DPrimaryPipe<CHAN>::commit() {
-    uint32_t fmt = mS3Dfmt & utils::OUTPUT_3D_MASK;
-    if(!utils::send3DInfoPacket(fmt)){
-        ALOGE("Error S3DExtPipe start error send3DInfoPacket %d", fmt);
-        return false;
-    }
-    return mS3d.commit();
-}
-template <int CHAN>
-inline bool S3DPrimaryPipe<CHAN>::queueBuffer(int fd, uint32_t offset) {
-    return mS3d.queueBuffer(fd, offset);
-}
-template <int CHAN>
-inline bool S3DPrimaryPipe<CHAN>::setCrop(const utils::Dim& d) {
-    utils::Dim _dim;
-    if(!utils::getCropS3D<CHAN>(d, _dim, mS3Dfmt)){
-        ALOGE("S3DPrimaryPipe setCrop failed to getCropS3D");
-        _dim = d;
-    }
-    return mS3d.setCrop(_dim);
-}
-template <int CHAN>
-inline bool S3DPrimaryPipe<CHAN>::setPosition(const utils::Dim& d)
-{
-    utils::Whf fbwhf(mS3d.getScreenInfo().mFBWidth,
-            mS3d.getScreenInfo().mFBHeight,
-            0 /* fmt dont care*/);
-    mCtrl3D.setWh(fbwhf);
-    if(!mCtrl3D.useVirtualFB()) {
-        ALOGE("Failed to use VFB on %d (non fatal)", utils::FB0);
-        return false;
-    }
-    utils::Dim _dim;
-    // original setPositionHandleState has getPositionS3D(...,true)
-    // which means format is HAL_3D_OUT_SBS_MASK
-    // HAL_3D_OUT_SBS_MASK is 0x1000 >> 12 == 0x1 as the orig
-    // code suggets
-    utils::Whf _whf(d.w, d.h, utils::HAL_3D_OUT_SBS_MASK);
-    if(!utils::getPositionS3D<CHAN>(_whf, _dim)) {
-        ALOGE("S3DPrimaryPipe setPosition err in getPositionS3D");
-        _dim = d;
-    }
-    return mS3d.setPosition(_dim);
-}
-
-/* for S3DPrimaryPipe, we need to have barriers once
-* So the easiest way to achieve it, is to make sure FB0 is having it before
-* setParam is running */
-template <>
-inline bool S3DPrimaryPipe<utils::OV_PIPE0>::setTransform(
-        const utils::eTransform& param) {
-    uint32_t barrier=0;
-    switch(param) {
-        case utils::OVERLAY_TRANSFORM_ROT_90:
-        case utils::OVERLAY_TRANSFORM_ROT_270:
-            barrier = utils::BARRIER_LAND;
-            break;
-        default:
-            barrier = utils::BARRIER_PORT;
-            break;
-    }
-    if(!utils::enableBarrier(barrier)) {
-        ALOGE("S3DPrimaryPipe setTransform failed to enable barrier");
-    }
-    return mS3d.setTransform(param);
-}
-
-template <int CHAN>
-inline bool S3DPrimaryPipe<CHAN>::setTransform(const utils::eTransform& param) {
-    return mS3d.setTransform(param);
-}
-template <int CHAN>
-inline bool S3DPrimaryPipe<CHAN>::setSource(const utils::PipeArgs& args)
-{
-    mS3Dfmt = utils::getS3DFormat(args.whf.format);
-    return mS3d.setSource(args);
-}
-template <int CHAN>
-inline void S3DPrimaryPipe<CHAN>::dump() const {
-    ALOGE("S3DPrimaryPipe Pipe fmt=%d", mS3Dfmt);
-    mS3d.dump();
-}
-
-} // overlay
-
-#endif // OVERLAY_M3D_EXT_PIPE_H
diff --git a/msm8226/liboverlay/pipes/overlayGenPipe.cpp b/msm8226/liboverlay/pipes/overlayGenPipe.cpp
index 9e57223..aebaebf 100644
--- a/msm8226/liboverlay/pipes/overlayGenPipe.cpp
+++ b/msm8226/liboverlay/pipes/overlayGenPipe.cpp
@@ -32,18 +32,16 @@
 
 namespace overlay {
 
-GenericPipe::GenericPipe(const int& dpy) : mDpy(dpy), mRotDownscaleOpt(false),
-    pipeState(CLOSED), mCtrl(new Ctrl(dpy)), mData(new Data(dpy)) {
+GenericPipe::GenericPipe(const int& dpy) : mDpy(dpy),
+    mCtrl(new Ctrl(dpy)), mData(new Data(dpy)) {
 }
 
 GenericPipe::~GenericPipe() {
     delete mCtrl;
     delete mData;
-    setClosed();
 }
 
 void GenericPipe::setSource(const utils::PipeArgs& args) {
-    mRotDownscaleOpt = args.rotFlags & utils::ROT_DOWNSCALE_ENABLED;
     mCtrl->setSource(args);
 }
 
@@ -68,27 +66,15 @@
         return mCtrl->setVisualParams(metadata);
 }
 
+void GenericPipe::setPipeType(const utils::eMdpPipeType& pType) {
+    mCtrl->setPipeType(pType);
+}
+
 bool GenericPipe::commit() {
-    bool ret = false;
-    int downscale_factor = utils::ROT_DS_NONE;
-
-    if(mRotDownscaleOpt) {
-        ovutils::Dim src(mCtrl->getCrop());
-        ovutils::Dim dst(mCtrl->getPosition());
-        downscale_factor = ovutils::getDownscaleFactor(
-                src.w, src.h, dst.w, dst.h);
-    }
-
-    mCtrl->setDownscale(downscale_factor);
-    ret = mCtrl->commit();
-
-    pipeState = ret ? OPEN : CLOSED;
-    return ret;
+    return mCtrl->commit();
 }
 
 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 = mCtrl->getPipeId();
     OVASSERT(-1 != pipeId, "Ctrl ID should not be -1");
     // set pipe id from ctrl to data
@@ -97,19 +83,18 @@
     return mData->queueBuffer(fd, offset);
 }
 
-int GenericPipe::getCtrlFd() const {
-    return mCtrl->getFd();
-}
-
 utils::Dim GenericPipe::getCrop() const
 {
     return mCtrl->getCrop();
 }
 
+uint8_t GenericPipe::getPriority() const {
+    return mCtrl->getPriority();
+}
+
 void GenericPipe::dump() const
 {
     ALOGE("== Dump Generic pipe start ==");
-    ALOGE("pipe state = %d", (int)pipeState);
     mCtrl->dump();
     mData->dump();
     ALOGE("== Dump Generic pipe end ==");
@@ -120,19 +105,6 @@
     mData->getDump(buf, len);
 }
 
-bool GenericPipe::isClosed() const  {
-    return (pipeState == CLOSED);
-}
-
-bool GenericPipe::isOpen() const  {
-    return (pipeState == OPEN);
-}
-
-bool GenericPipe::setClosed() {
-    pipeState = CLOSED;
-    return true;
-}
-
 int GenericPipe::getPipeId() {
     return mCtrl->getPipeId();
 }
diff --git a/msm8226/liboverlay/pipes/overlayGenPipe.h b/msm8226/liboverlay/pipes/overlayGenPipe.h
index 813a2b3..0a2639a 100644
--- a/msm8226/liboverlay/pipes/overlayGenPipe.h
+++ b/msm8226/liboverlay/pipes/overlayGenPipe.h
@@ -54,6 +54,8 @@
     void setPosition(const utils::Dim& dim);
     /* set visual param */
     bool setVisualParams(const MetaData_t &metadata);
+    /* set pipe type RGB/DMA/VG */
+    void setPipeType(const utils::eMdpPipeType& pType);
     /* commit changes to the overlay "set"*/
     bool commit();
     /* Data APIs */
@@ -63,12 +65,8 @@
     const utils::PipeArgs& getArgs() const;
     /* retrieve cached crop data */
     utils::Dim getCrop() const;
-    /* is closed */
-    bool isClosed() const;
-    /* is open */
-    bool isOpen() const;
-    /* return Ctrl fd. Used for S3D */
-    int getCtrlFd() const;
+    /* return pipe priority */
+    uint8_t getPriority() const;
     /* dump the state of the object */
     void dump() const;
     /* Return the dump in the specified buffer */
@@ -78,19 +76,7 @@
     static bool validateAndSet(GenericPipe* pipeArray[], const int& count,
             const int& fbFd);
 private:
-    /* set Closed pipe */
-    bool setClosed();
-
     int mDpy;
-    //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;
-    /* Pipe open or closed */
-    enum ePipeState {
-        CLOSED,
-        OPEN
-    };
-    ePipeState pipeState;
     Ctrl *mCtrl;
     Data *mData;
 };
diff --git a/msm8226/libqdutils/Android.mk b/msm8226/libqdutils/Android.mk
index 2907ccf..212c8d8 100644
--- a/msm8226/libqdutils/Android.mk
+++ b/msm8226/libqdutils/Android.mk
@@ -21,7 +21,6 @@
 
 LOCAL_COPY_HEADERS_TO           := $(common_header_export_path)
 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)
diff --git a/msm8226/libqdutils/display_config.cpp b/msm8226/libqdutils/display_config.cpp
index 60f1f68..7ff106f 100644
--- a/msm8226/libqdutils/display_config.cpp
+++ b/msm8226/libqdutils/display_config.cpp
@@ -113,4 +113,25 @@
     return err;
 }
 
+int setViewFrame(int dpy, int l, int t, int r, int b) {
+    status_t err = (status_t) FAILED_TRANSACTION;
+    sp<IQService> binder = getBinder();
+    Parcel inParcel, outParcel;
+    inParcel.writeInt32(dpy);
+    inParcel.writeInt32(l);
+    inParcel.writeInt32(t);
+    inParcel.writeInt32(r);
+    inParcel.writeInt32(b);
+
+    if(binder != NULL) {
+        err = binder->dispatch(IQService::SET_VIEW_FRAME,
+                &inParcel, &outParcel);
+    }
+    if(err)
+        ALOGE("%s: Failed to set view frame for dpy %d err=%d",
+                            __FUNCTION__, dpy, err);
+
+    return err;
+}
+
 }; //namespace
diff --git a/msm8226/libqdutils/display_config.h b/msm8226/libqdutils/display_config.h
index 29edbef..a69265b 100644
--- a/msm8226/libqdutils/display_config.h
+++ b/msm8226/libqdutils/display_config.h
@@ -73,4 +73,7 @@
 // get the active visible region for the display
 // Returns 0 on success, negative values on errors
 int getDisplayVisibleRegion(int dpy, hwc_rect_t &rect);
+
+// set the view frame information in hwc context from surfaceflinger
+int setViewFrame(int dpy, int l, int t, int r, int b);
 }; //namespace
diff --git a/msm8226/libqdutils/idle_invalidator.cpp b/msm8226/libqdutils/idle_invalidator.cpp
index d30375e..86191e9 100644
--- a/msm8226/libqdutils/idle_invalidator.cpp
+++ b/msm8226/libqdutils/idle_invalidator.cpp
@@ -103,7 +103,7 @@
             char data[64];
             // Consume the node by reading it
             ssize_t len = pread(pFd.fd, data, 64, 0);
-            ALOGD_IF(II_DEBUG, "IdleInvalidator::%s Idle Timeout fired len %zu",
+            ALOGD_IF(II_DEBUG, "IdleInvalidator::%s Idle Timeout fired len %zd",
                 __FUNCTION__, len);
             mHandler((void*)mHwcContext);
         }
diff --git a/msm8226/libqdutils/mdp_version.cpp b/msm8226/libqdutils/mdp_version.cpp
index a757e69..6b53522 100644
--- a/msm8226/libqdutils/mdp_version.cpp
+++ b/msm8226/libqdutils/mdp_version.cpp
@@ -37,24 +37,41 @@
 
 #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_106 = 0x10060000, //8x16
-    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
-    MDSS_MDP_HW_REV_107 = 0x10070000, //Next version
-};
+#ifndef MDSS_MDP_HW_REV_100
+#define MDSS_MDP_HW_REV_100 0x10000000 //8974 v1
+#endif
+#ifndef MDSS_MDP_HW_REV_101
+#define MDSS_MDP_HW_REV_101 0x10010000 //8x26
+#endif
+#ifndef MDSS_MDP_HW_REV_102
+#define MDSS_MDP_HW_REV_102 0x10020000 //8974 v2
+#endif
+#ifndef MDSS_MDP_HW_REV_103
+#define MDSS_MDP_HW_REV_103 0x10030000 //8084
+#endif
+#ifndef MDSS_MDP_HW_REV_104
+#define MDSS_MDP_HW_REV_104 0x10040000 //Next version
+#endif
+#ifndef MDSS_MDP_HW_REV_105
+#define MDSS_MDP_HW_REV_105 0x10050000 //8994
+#endif
+#ifndef MDSS_MDP_HW_REV_106
+#define MDSS_MDP_HW_REV_106 0x10060000 //8x16
+#endif
+#ifndef MDSS_MDP_HW_REV_107
+#define MDSS_MDP_HW_REV_107 0x10070000 //Next version
+#endif
+#ifndef MDSS_MDP_HW_REV_108
+#define MDSS_MDP_HW_REV_108 0x10080000 //8x39 & 8x36
+#endif
+#ifndef MDSS_MDP_HW_REV_109
+#define MDSS_MDP_HW_REV_109 0x10090000 //Next version
+#endif
+#ifndef MDSS_MDP_HW_REV_200
+#define MDSS_MDP_HW_REV_200 0x20000000 //8092
+#endif
+#ifndef MDSS_MDP_HW_REV_206
+#define MDSS_MDP_HW_REV_206 0x20060000 //Future
 #endif
 
 MDPVersion::MDPVersion()
@@ -71,7 +88,9 @@
     mLowBw = 0;
     mHighBw = 0;
     mSourceSplit = false;
+    mSourceSplitAlways = false;
     mRGBHasNoScalar = false;
+    mRotDownscale = false;
 
     updatePanelInfo();
 
@@ -119,7 +138,6 @@
     FILE *panelInfoNodeFP = NULL;
     const int MAX_FRAME_BUFFER_NAME_SIZE = 128;
     char fbType[MAX_FRAME_BUFFER_NAME_SIZE];
-    char panelInfo[MAX_FRAME_BUFFER_NAME_SIZE];
     const char *strCmdPanel = "mipi dsi cmd panel";
     const char *strVideoPanel = "mipi dsi video panel";
     const char *strLVDSPanel = "lvds panel";
@@ -165,7 +183,7 @@
                           mPanelInfo.mPartialUpdateEnable? "Enabled" :
                           "Disabled");
                 }
-                if(!strncmp(tokens[0], "xalign", strlen("xalign"))) {
+                if(!strncmp(tokens[0], "xstart", strlen("xstart"))) {
                     mPanelInfo.mLeftAlign = atoi(tokens[1]);
                     ALOGI("Left Align: %d", mPanelInfo.mLeftAlign);
                 }
@@ -181,6 +199,18 @@
                     mPanelInfo.mHeightAlign = atoi(tokens[1]);
                     ALOGI("Height Align: %d", mPanelInfo.mHeightAlign);
                 }
+                if(!strncmp(tokens[0], "min_w", strlen("min_w"))) {
+                    mPanelInfo.mMinROIWidth = atoi(tokens[1]);
+                    ALOGI("Min ROI Width: %d", mPanelInfo.mMinROIWidth);
+                }
+                if(!strncmp(tokens[0], "min_h", strlen("min_h"))) {
+                    mPanelInfo.mMinROIHeight = atoi(tokens[1]);
+                    ALOGI("Min ROI Height: %d", mPanelInfo.mMinROIHeight);
+                }
+                if(!strncmp(tokens[0], "roi_merge", strlen("roi_merge"))) {
+                    mPanelInfo.mNeedsROIMerge = atoi(tokens[1]);
+                    ALOGI("Needs ROI Merge: %d", mPanelInfo.mNeedsROIMerge);
+                }
             }
         }
         fclose(panelInfoNodeFP);
@@ -253,22 +283,22 @@
                     for(int i=1; i<index;i++) {
                         if(!strncmp(tokens[i], "bwc", strlen("bwc"))) {
                            mFeatures |= MDP_BWC_EN;
-                        }
-                        else if(!strncmp(tokens[i], "decimation",
+                        } else if(!strncmp(tokens[i], "decimation",
                                     strlen("decimation"))) {
                            mFeatures |= MDP_DECIMATION_EN;
-                        }
-                        else if(!strncmp(tokens[i], "tile_format",
+                        } else if(!strncmp(tokens[i], "tile_format",
                                     strlen("tile_format"))) {
                            if(enableMacroTile)
                                mMacroTileEnabled = true;
                         } else if(!strncmp(tokens[i], "src_split",
                                     strlen("src_split"))) {
                             mSourceSplit = true;
-                        }
-                        else if(!strncmp(tokens[i], "non_scalar_rgb",
+                        } else if(!strncmp(tokens[i], "non_scalar_rgb",
                                     strlen("non_scalar_rgb"))) {
                             mRGBHasNoScalar = true;
+                        } else if(!strncmp(tokens[i], "rotator_downscale",
+                                    strlen("rotator_downscale"))) {
+                            mRotDownscale = true;
                         }
                     }
                 }
@@ -277,6 +307,30 @@
         free(line);
         fclose(sysfsFd);
     }
+
+    if(mSourceSplit) {
+        memset(sysfsPath, 0, sizeof(sysfsPath));
+        snprintf(sysfsPath , sizeof(sysfsPath),
+                "/sys/class/graphics/fb0/msm_fb_src_split_info");
+
+        sysfsFd = fopen(sysfsPath, "rb");
+        if (sysfsFd == NULL) {
+            ALOGE("%s: Opening file %s failed with error %s", __FUNCTION__,
+                    sysfsPath, strerror(errno));
+            return false;
+        } else {
+            line = (char *) malloc(len);
+            if((read = getline(&line, &len, sysfsFd)) != -1) {
+                if(!strncmp(line, "src_split_always",
+                        strlen("src_split_always"))) {
+                    mSourceSplitAlways = true;
+                }
+            }
+            free(line);
+            fclose(sysfsFd);
+        }
+    }
+
     ALOGD_IF(DEBUG, "%s: mMDPVersion: %d mMdpRev: %x mRGBPipes:%d,"
                     "mVGPipes:%d", __FUNCTION__, mMDPVersion, mMdpRev,
                     mRGBPipes, mVGPipes);
@@ -342,6 +396,10 @@
     return mSourceSplit;
 }
 
+bool MDPVersion::isSrcSplitAlways() const {
+    return mSourceSplitAlways;
+}
+
 bool MDPVersion::isRGBScalarSupported() const {
     return (!mRGBHasNoScalar);
 }
@@ -366,10 +424,21 @@
             mMdpRev < MDSS_MDP_HW_REV_206);
 }
 
+bool MDPVersion::is8994() {
+    return (mMdpRev >= MDSS_MDP_HW_REV_105 and
+            mMdpRev < MDSS_MDP_HW_REV_106);
+}
+
 bool MDPVersion::is8x16() {
     return (mMdpRev >= MDSS_MDP_HW_REV_106 and
             mMdpRev < MDSS_MDP_HW_REV_107);
 }
 
+bool MDPVersion::is8x39() {
+    return (mMdpRev >= MDSS_MDP_HW_REV_108 and
+            mMdpRev < MDSS_MDP_HW_REV_109);
+}
+
+
 }; //namespace qdutils
 
diff --git a/msm8226/libqdutils/mdp_version.h b/msm8226/libqdutils/mdp_version.h
index aab8643..6c4a3f4 100644
--- a/msm8226/libqdutils/mdp_version.h
+++ b/msm8226/libqdutils/mdp_version.h
@@ -99,8 +99,12 @@
     int mWidthAlign;             // ROI width alignment restriction
     int mTopAlign;               // ROI top alignment restriction
     int mHeightAlign;            // ROI height alignment restriction
+    int mMinROIWidth;            // Min width needed for ROI
+    int mMinROIHeight;           // Min height needed for ROI
+    bool mNeedsROIMerge;         // Merge ROI's of both the DSI's
     PanelInfo() : mType(NO_PANEL), mPartialUpdateEnable(0),
-    mLeftAlign(0), mWidthAlign(0), mTopAlign(0), mHeightAlign(0){}
+    mLeftAlign(0), mWidthAlign(0), mTopAlign(0), mHeightAlign(0),
+    mMinROIWidth(0), mMinROIHeight(0), mNeedsROIMerge(false){}
     friend class MDPVersion;
 };
 
@@ -125,20 +129,27 @@
     bool supportsMacroTile();
     int getLeftSplit() { return mSplit.left(); }
     int getRightSplit() { return mSplit.right(); }
-    int isPartialUpdateEnabled() { return mPanelInfo.mPartialUpdateEnable; }
+    bool isPartialUpdateEnabled() { return mPanelInfo.mPartialUpdateEnable; }
     int getLeftAlign() { return mPanelInfo.mLeftAlign; }
     int getWidthAlign() { return mPanelInfo.mWidthAlign; }
     int getTopAlign() { return mPanelInfo.mTopAlign; }
     int getHeightAlign() { return mPanelInfo.mHeightAlign; }
+    int getMinROIWidth() { return mPanelInfo.mMinROIWidth; }
+    int getMinROIHeight() { return mPanelInfo.mMinROIHeight; }
+    bool needsROIMerge() { return mPanelInfo.mNeedsROIMerge; }
     unsigned long getLowBw() { return mLowBw; }
     unsigned long getHighBw() { return mHighBw; }
+    bool isRotDownscaleEnabled() { return mRotDownscale; }
     bool isSrcSplit() const;
+    bool isSrcSplitAlways() const;
     bool isRGBScalarSupported() const;
     bool is8x26();
     bool is8x74v2();
     bool is8084();
     bool is8092();
+    bool is8994();
     bool is8x16();
+    bool is8x39();
 
 private:
     bool updateSysFsInfo();
@@ -162,7 +173,10 @@
     unsigned long mLowBw; //kbps
     unsigned long mHighBw; //kbps
     bool mSourceSplit;
+    //Additional property on top of source split
+    bool mSourceSplitAlways;
     bool mRGBHasNoScalar;
+    bool mRotDownscale;
 };
 }; //namespace qdutils
 #endif //INCLUDE_LIBQCOMUTILS_MDPVER
diff --git a/msm8226/libqdutils/qdMetaData.cpp b/msm8226/libqdutils/qdMetaData.cpp
index 0390599..dbd6f10 100644
--- a/msm8226/libqdutils/qdMetaData.cpp
+++ b/msm8226/libqdutils/qdMetaData.cpp
@@ -27,6 +27,7 @@
  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
+#include <errno.h>
 #include <string.h>
 #include <sys/mman.h>
 #include <cutils/log.h>
@@ -52,8 +53,8 @@
     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__);
+    if (base == reinterpret_cast<void*>(MAP_FAILED)) {
+        ALOGE("%s: mmap() failed: error is %s!", __func__, strerror(errno));
         return -1;
     }
     MetaData_t *data = reinterpret_cast <MetaData_t *>(base);
diff --git a/msm8226/libqservice/Android.mk b/msm8226/libqservice/Android.mk
index 0c6123b..78b1d77 100644
--- a/msm8226/libqservice/Android.mk
+++ b/msm8226/libqservice/Android.mk
@@ -3,7 +3,6 @@
 include $(CLEAR_VARS)
 
 LOCAL_MODULE                  := libqservice
-LOCAL_MODULE_PATH             := $(TARGET_OUT_SHARED_LIBRARIES)
 LOCAL_MODULE_TAGS             := optional
 LOCAL_C_INCLUDES              := $(common_includes) $(kernel_includes)
 LOCAL_SHARED_LIBRARIES        := $(common_libs) libbinder
diff --git a/msm8226/libqservice/IQService.h b/msm8226/libqservice/IQService.h
index 6c1bba6..c222eb9 100644
--- a/msm8226/libqservice/IQService.h
+++ b/msm8226/libqservice/IQService.h
@@ -50,6 +50,9 @@
         SET_HSIC_DATA,           // Set HSIC on dspp
         GET_DISPLAY_VISIBLE_REGION,  // Get the visibleRegion for dpy
         PAUSE_WFD,               // Pause/Resume WFD
+        SET_WFD_STATUS,          // Set if wfd connection is on/off
+        SET_VIEW_FRAME,          // Set view frame of display
+        DYNAMIC_DEBUG,           // Enable more logging on the fly
         COMMAND_LIST_END = 400,
     };
 
@@ -58,6 +61,12 @@
         START,
     };
 
+    enum {
+        DEBUG_ALL,
+        DEBUG_MDPCOMP,
+        DEBUG_VSYNC,
+    };
+
     // Register a client that can be notified
     virtual void connect(const android::sp<qClient::IQClient>& client) = 0;
     // Generic function to dispatch binder commands
diff --git a/msm8226/libqservice/QService.cpp b/msm8226/libqservice/QService.cpp
index e4af422..12dd995 100644
--- a/msm8226/libqservice/QService.cpp
+++ b/msm8226/libqservice/QService.cpp
@@ -28,6 +28,8 @@
  */
 
 #include <QService.h>
+#include <binder/Parcel.h>
+#include <binder/IPCThreadState.h>
 
 #define QSERVICE_DEBUG 0
 
@@ -55,6 +57,10 @@
 status_t QService::dispatch(uint32_t command, const Parcel* inParcel,
         Parcel* outParcel) {
     status_t err = (status_t) FAILED_TRANSACTION;
+    IPCThreadState* ipc = IPCThreadState::self();
+    //Rewind parcel in case we're calling from the same process
+    if (ipc->getCallingPid() == getpid())
+        inParcel->setDataPosition(0);
     if (mClient.get()) {
         ALOGD_IF(QSERVICE_DEBUG, "Dispatching command: %d", command);
         err = mClient->notifyCallback(command, inParcel, outParcel);
diff --git a/msm8226/libqservice/QServiceUtils.h b/msm8226/libqservice/QServiceUtils.h
index 699164d..08cab31 100644
--- a/msm8226/libqservice/QServiceUtils.h
+++ b/msm8226/libqservice/QServiceUtils.h
@@ -87,4 +87,7 @@
     return sendSingleParam(qService::IQService::PAUSE_WFD, pause);
 }
 
+inline android::status_t setWfdStatus(uint32_t wfdStatus) {
+    return sendSingleParam(qService::IQService::SET_WFD_STATUS, wfdStatus);
+}
 #endif /* end of include guard: QSERVICEUTILS_H */
diff --git a/msm8226/libvirtual/Android.mk b/msm8226/libvirtual/Android.mk
index beeef25..a41ef33 100644
--- a/msm8226/libvirtual/Android.mk
+++ b/msm8226/libvirtual/Android.mk
@@ -3,7 +3,6 @@
 include $(CLEAR_VARS)
 
 LOCAL_MODULE                  := libvirtual
-LOCAL_MODULE_PATH             := $(TARGET_OUT_SHARED_LIBRARIES)
 LOCAL_MODULE_TAGS             := optional
 LOCAL_C_INCLUDES              := $(common_includes) $(kernel_includes)
 LOCAL_SHARED_LIBRARIES        := $(common_libs) liboverlay libqdutils
diff --git a/msm8226/libvirtual/virtual.cpp b/msm8226/libvirtual/virtual.cpp
index 5453e3a..264d045 100644
--- a/msm8226/libvirtual/virtual.cpp
+++ b/msm8226/libvirtual/virtual.cpp
@@ -47,7 +47,6 @@
 #include "virtual.h"
 #include "overlayUtils.h"
 #include "overlay.h"
-#include "mdp_version.h"
 #include "qd_utils.h"
 
 using namespace android;
@@ -177,14 +176,14 @@
         uint32_t priW = mHwcContext->dpyAttr[HWC_DISPLAY_PRIMARY].xres;
         uint32_t priH = mHwcContext->dpyAttr[HWC_DISPLAY_PRIMARY].yres;
 
-        initResolution(extW, extH);
-
         // Dynamic Resolution Change depends on MDP downscaling.
         // MDP downscale property will be ignored to exercise DRC use case.
         // If DRC is in progress, ext WxH will have non-zero values.
-        bool isDRC = (extW > 0) && (extH > 0);
+        bool isDRC = (extW > mVInfo.xres) && (extH > mVInfo.yres);
 
-        if(!qdutils::MDPVersion::getInstance().is8x26()
+        initResolution(extW, extH);
+
+        if(mHwcContext->mOverlay->isUIScalingOnExternalSupported()
                 && (mHwcContext->mMDPDownscaleEnabled || isDRC)) {
 
             // maxArea represents the maximum resolution between
@@ -195,6 +194,13 @@
 
             setDownScaleMode(maxArea);
         }
+        //Initialize the display viewFrame info
+        mHwcContext->mViewFrame[HWC_DISPLAY_VIRTUAL].left = 0;
+        mHwcContext->mViewFrame[HWC_DISPLAY_VIRTUAL].top = 0;
+        mHwcContext->mViewFrame[HWC_DISPLAY_VIRTUAL].right =
+            (int)mHwcContext->dpyAttr[HWC_DISPLAY_VIRTUAL].xres;
+        mHwcContext->mViewFrame[HWC_DISPLAY_VIRTUAL].bottom =
+            (int)mHwcContext->dpyAttr[HWC_DISPLAY_VIRTUAL].yres;
         mHwcContext->dpyAttr[HWC_DISPLAY_VIRTUAL].vsync_period =
                 1000000000l /60;
         ALOGD_IF(DEBUG,"%s: Setting Virtual Attr: res(%d x %d)",__FUNCTION__,
diff --git a/msm8960/libgralloc/alloc_controller.cpp b/msm8960/libgralloc/alloc_controller.cpp
index eadc5b8..32f3b38 100644
--- a/msm8960/libgralloc/alloc_controller.cpp
+++ b/msm8960/libgralloc/alloc_controller.cpp
@@ -284,9 +284,16 @@
             // The chroma plane is subsampled,
             // but the pitch in bytes is unchanged
             // The GPU needs 4K alignment, but the video decoder needs 8K
+            alignedw = ALIGN(alignedw, 128);
             size  = ALIGN( alignedw * alignedh, 8192);
             size += ALIGN( alignedw * ALIGN(height/2, 32), 8192);
             break;
+        case HAL_PIXEL_FORMAT_NV12:
+            alignedw = ALIGN(width, 16);
+            alignedh = height;
+            size  = ALIGN( ALIGN(width, 128) * ALIGN(height, 32), 8192);
+            size += ALIGN( ALIGN(width, 128) * ALIGN(height/2, 32), 8192);
+            break;
         case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:
         case HAL_PIXEL_FORMAT_YV12:
             if ((format == HAL_PIXEL_FORMAT_YV12) && ((width&1) || (height&1))) {
diff --git a/msm8960/libgralloc/gralloc_priv.h b/msm8960/libgralloc/gralloc_priv.h
index 80141ae..d9f4f4f 100644
--- a/msm8960/libgralloc/gralloc_priv.h
+++ b/msm8960/libgralloc/gralloc_priv.h
@@ -92,6 +92,7 @@
 /*****************************************************************************/
 enum {
     /* OEM specific HAL formats */
+    HAL_PIXEL_FORMAT_NV12                   = 0x15, /*OMX_COLOR_FormatYUV420SemiPlanar*/
     HAL_PIXEL_FORMAT_NV12_ENCODEABLE        = 0x102,
     HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS     = 0x7FA30C04,
     HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED     = 0x7FA30C03,
diff --git a/msm8960/libgralloc/mapper.cpp b/msm8960/libgralloc/mapper.cpp
index 99beffd..ee16576 100644
--- a/msm8960/libgralloc/mapper.cpp
+++ b/msm8960/libgralloc/mapper.cpp
@@ -265,6 +265,17 @@
                 ycbcr->chroma_step = 2;
                 memset(ycbcr->reserved, 0, sizeof(ycbcr->reserved));
                 break;
+            // YCbCr_420_SP
+            case HAL_PIXEL_FORMAT_NV12:
+                ystride = ALIGN(hnd->width, 16);
+                ycbcr->y  = (void*)hnd->base;
+                ycbcr->cb = (void*)(hnd->base + ystride * hnd->height);
+                ycbcr->cr = (void*)(hnd->base + ystride * hnd->height + 1);
+                ycbcr->ystride = ystride;
+                ycbcr->cstride = ystride;
+                ycbcr->chroma_step = 2;
+                memset(ycbcr->reserved, 0, sizeof(ycbcr->reserved));
+                break;
             default:
                 ALOGD("%s: Invalid format passed: 0x%x", __FUNCTION__,
                       hnd->format);
diff --git a/msm8974/libgralloc/mapper.cpp b/msm8974/libgralloc/mapper.cpp
index 5b3a9d7..fec7301 100644
--- a/msm8974/libgralloc/mapper.cpp
+++ b/msm8974/libgralloc/mapper.cpp
@@ -251,10 +251,11 @@
 {
     private_handle_t* hnd = (private_handle_t*)handle;
     int err = gralloc_map_and_invalidate(module, handle, usage, l, t, w, h);
-    int ystride;
+    int ystride, cstride;
+
+    memset(ycbcr->reserved, 0, sizeof(ycbcr->reserved));
     if(!err) {
         //hnd->format holds our implementation defined format
-        //HAL_PIXEL_FORMAT_YCrCb_420_SP is the only one set right now.
         switch (hnd->format) {
             case HAL_PIXEL_FORMAT_YCrCb_420_SP:
                 ystride = ALIGN(hnd->width, 16);
@@ -264,7 +265,15 @@
                 ycbcr->ystride = ystride;
                 ycbcr->cstride = ystride;
                 ycbcr->chroma_step = 2;
-                memset(ycbcr->reserved, 0, sizeof(ycbcr->reserved));
+                break;
+            case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS:
+                ystride = cstride = hnd->width;
+                ycbcr->y  = (void*)hnd->base;
+                ycbcr->cb = (void*)(hnd->base + ystride * hnd->height);
+                ycbcr->cr = (void*)(hnd->base + ystride * hnd->height + 1);
+                ycbcr->ystride = ystride;
+                ycbcr->cstride = cstride;
+                ycbcr->chroma_step = 2;
                 break;
             default:
                 ALOGD("%s: Invalid format passed: 0x%x", __FUNCTION__,