Merge "liboverlay: remove the unused rotator object"
diff --git a/common.mk b/common.mk
index 3fb003b..74d6032 100644
--- a/common.mk
+++ b/common.mk
@@ -27,7 +27,7 @@
     common_flags += -D__ARM_HAVE_NEON
 endif
 
-ifeq ($(call is-board-platform-in-list, msm8974 msm8226 msm8610), true)
+ifeq ($(call is-board-platform-in-list, msm8974 msm8226 msm8610 apq8084), true)
     common_flags += -DVENUS_COLOR_FORMAT
     common_flags += -DMDSS_TARGET
 endif
diff --git a/libcopybit/copybit.cpp b/libcopybit/copybit.cpp
index a3c93ba..5fd68da 100644
--- a/libcopybit/copybit.cpp
+++ b/libcopybit/copybit.cpp
@@ -129,10 +129,10 @@
         case HAL_PIXEL_FORMAT_RGB_888:       return MDP_RGB_888;
         case HAL_PIXEL_FORMAT_RGBA_8888:     return MDP_RGBA_8888;
         case HAL_PIXEL_FORMAT_BGRA_8888:     return MDP_BGRA_8888;
-        case HAL_PIXEL_FORMAT_YCrCb_422_SP:  return MDP_Y_CBCR_H2V1;
-        case HAL_PIXEL_FORMAT_YCrCb_420_SP:  return MDP_Y_CBCR_H2V2;
-        case HAL_PIXEL_FORMAT_YCbCr_422_SP:  return MDP_Y_CRCB_H2V1;
-        case HAL_PIXEL_FORMAT_YCbCr_420_SP:  return MDP_Y_CRCB_H2V2;
+        case HAL_PIXEL_FORMAT_YCrCb_422_SP:  return MDP_Y_CRCB_H2V1;
+        case HAL_PIXEL_FORMAT_YCrCb_420_SP:  return MDP_Y_CRCB_H2V2;
+        case HAL_PIXEL_FORMAT_YCbCr_422_SP:  return MDP_Y_CBCR_H2V1;
+        case HAL_PIXEL_FORMAT_YCbCr_420_SP:  return MDP_Y_CBCR_H2V2;
         case HAL_PIXEL_FORMAT_YCrCb_420_SP_ADRENO: return MDP_Y_CBCR_H2V2_ADRENO;
         case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS: return MDP_Y_CBCR_H2V2_ADRENO;
         case HAL_PIXEL_FORMAT_NV12_ENCODEABLE: return MDP_Y_CBCR_H2V2;
@@ -481,7 +481,7 @@
             }
         }
         const uint32_t maxCount = sizeof(list->req)/sizeof(list->req[0]);
-        const struct copybit_rect_t bounds = { 0, 0, dst->w, dst->h };
+        const struct copybit_rect_t bounds = { 0, 0, (int)dst->w, (int)dst->h };
         struct copybit_rect_t clip;
         status = 0;
         while ((status == 0) && region->next(region, &clip)) {
@@ -532,8 +532,8 @@
     struct copybit_image_t const *src,
     struct copybit_region_t const *region)
 {
-    struct copybit_rect_t dr = { 0, 0, dst->w, dst->h };
-    struct copybit_rect_t sr = { 0, 0, src->w, src->h };
+    struct copybit_rect_t dr = { 0, 0, (int)dst->w, (int)dst->h };
+    struct copybit_rect_t sr = { 0, 0, (int)src->w, (int)src->h };
     return stretch_copybit(dev, dst, src, &dr, &sr, region);
 }
 
diff --git a/libcopybit/copybit_c2d.cpp b/libcopybit/copybit_c2d.cpp
index 193d067..385acb0 100644
--- a/libcopybit/copybit_c2d.cpp
+++ b/libcopybit/copybit_c2d.cpp
@@ -686,6 +686,9 @@
     ctx->blit_yuv_2_plane_count = 0;
     ctx->blit_yuv_3_plane_count = 0;
     ctx->blit_count = 0;
+    ctx->dst_surface_mapped = false;
+    ctx->dst_surface_base = 0;
+
     return status;
 }
 
diff --git a/libexternal/external.cpp b/libexternal/external.cpp
index 6f5cc09..97f031d 100644
--- a/libexternal/external.cpp
+++ b/libexternal/external.cpp
@@ -670,26 +670,28 @@
 bool ExternalDisplay::writeHPDOption(int userOption) const
 {
     bool ret = true;
-    char sysFsHPDFilePath[MAX_SYSFS_FILE_PATH];
-    snprintf(sysFsHPDFilePath ,sizeof(sysFsHPDFilePath),
-            "/sys/devices/virtual/graphics/fb%d/hpd", mHdmiFbNum);
-    int hdmiHPDFile = open(sysFsHPDFilePath,O_RDWR, 0);
-    if (hdmiHPDFile < 0) {
-        ALOGE("%s: state file '%s' not found : ret%d err str: %s", __FUNCTION__,
-                                sysFsHPDFilePath, hdmiHPDFile, strerror(errno));
-        ret = false;
-    } else {
-        int err = -1;
-        ALOGD_IF(DEBUG, "%s: option = %d", __FUNCTION__, userOption);
-        if(userOption)
-            err = write(hdmiHPDFile, "1", 2);
-        else
-            err = write(hdmiHPDFile, "0" , 2);
-        if (err <= 0) {
-            ALOGE("%s: file write failed '%s'", __FUNCTION__, sysFsHPDFilePath);
+    if(mHdmiFbNum != -1) {
+        char sysFsHPDFilePath[MAX_SYSFS_FILE_PATH];
+        snprintf(sysFsHPDFilePath ,sizeof(sysFsHPDFilePath),
+                 "/sys/devices/virtual/graphics/fb%d/hpd", mHdmiFbNum);
+        int hdmiHPDFile = open(sysFsHPDFilePath,O_RDWR, 0);
+        if (hdmiHPDFile < 0) {
+            ALOGE("%s: state file '%s' not found : ret%d err str: %s", __FUNCTION__,
+                  sysFsHPDFilePath, hdmiHPDFile, strerror(errno));
             ret = false;
+        } else {
+            int err = -1;
+            ALOGD_IF(DEBUG, "%s: option = %d", __FUNCTION__, userOption);
+            if(userOption)
+                err = write(hdmiHPDFile, "1", 2);
+            else
+                err = write(hdmiHPDFile, "0" , 2);
+            if (err <= 0) {
+                ALOGE("%s: file write failed '%s'", __FUNCTION__, sysFsHPDFilePath);
+                ret = false;
+            }
+            close(hdmiHPDFile);
         }
-        close(hdmiHPDFile);
     }
     return ret;
 }
diff --git a/libhwcomposer/hwc.cpp b/libhwcomposer/hwc.cpp
index d7375f8..e322357 100644
--- a/libhwcomposer/hwc.cpp
+++ b/libhwcomposer/hwc.cpp
@@ -105,6 +105,8 @@
             ctx->mFBUpdate[i]->reset();
         if(ctx->mCopyBit[i])
             ctx->mCopyBit[i]->reset();
+        if(ctx->mLayerRotMap[i])
+            ctx->mLayerRotMap[i]->reset();
     }
 }
 
@@ -122,7 +124,7 @@
     memset(&commit_info, 0, sizeof(struct mdp_display_commit));
     commit_info.flags = MDP_DISPLAY_COMMIT_OVERLAY;
     if(ioctl(ctx->dpyAttr[dpy].fd, MSMFB_DISPLAY_COMMIT, &commit_info) == -1) {
-       ALOGE("%s: MSMFB_DISPLAY_COMMIT for primary failed", __FUNCTION__);
+       ALOGE("%s: MSMFB_DISPLAY_COMMIT for dpy %d failed", __FUNCTION__,dpy);
        return -errno;
     }
     return 0;
@@ -418,43 +420,45 @@
     Locker::Autolock _l(ctx->mExtLock);
 
     if (LIKELY(list) && ctx->dpyAttr[dpy].isActive &&
-        !ctx->dpyAttr[dpy].isPause &&
         ctx->dpyAttr[dpy].connected) {
-        uint32_t last = list->numHwLayers - 1;
-        hwc_layer_1_t *fbLayer = &list->hwLayers[last];
-        int fd = -1; //FenceFD from the Copybit(valid in async mode)
-        bool copybitDone = false;
-        if(ctx->mCopyBit[dpy])
-            copybitDone = ctx->mCopyBit[dpy]->draw(ctx, list, dpy, &fd);
 
-        if(list->numHwLayers > 1)
-            hwc_sync(ctx, list, dpy, fd);
+        if(!ctx->dpyAttr[dpy].isPause) {
+            uint32_t last = list->numHwLayers - 1;
+            hwc_layer_1_t *fbLayer = &list->hwLayers[last];
+            int fd = -1; //FenceFD from the Copybit(valid in async mode)
+            bool copybitDone = false;
+            if(ctx->mCopyBit[dpy])
+                copybitDone = ctx->mCopyBit[dpy]->draw(ctx, list, dpy, &fd);
 
-        // Dump the layers for external
-        if(ctx->mHwcDebug[dpy])
-            ctx->mHwcDebug[dpy]->dumpLayers(list);
+            if(list->numHwLayers > 1)
+                hwc_sync(ctx, list, dpy, fd);
 
-        if (!ctx->mMDPComp[dpy]->draw(ctx, list)) {
-            ALOGE("%s: MDPComp draw failed", __FUNCTION__);
-            ret = -1;
-        }
+            // Dump the layers for external
+            if(ctx->mHwcDebug[dpy])
+                ctx->mHwcDebug[dpy]->dumpLayers(list);
 
-        int extOnlyLayerIndex =
-            ctx->listStats[dpy].extOnlyLayerIndex;
-
-        private_handle_t *hnd = (private_handle_t *)fbLayer->handle;
-        if(extOnlyLayerIndex!= -1) {
-            hwc_layer_1_t *extLayer = &list->hwLayers[extOnlyLayerIndex];
-            hnd = (private_handle_t *)extLayer->handle;
-        } else if(copybitDone) {
-            hnd = ctx->mCopyBit[dpy]->getCurrentRenderBuffer();
-        }
-
-        if(hnd && !isYuvBuffer(hnd)) {
-            if (!ctx->mFBUpdate[dpy]->draw(ctx, hnd)) {
-                ALOGE("%s: FBUpdate::draw fail!", __FUNCTION__);
+            if (!ctx->mMDPComp[dpy]->draw(ctx, list)) {
+                ALOGE("%s: MDPComp draw failed", __FUNCTION__);
                 ret = -1;
             }
+
+            int extOnlyLayerIndex =
+                    ctx->listStats[dpy].extOnlyLayerIndex;
+
+            private_handle_t *hnd = (private_handle_t *)fbLayer->handle;
+            if(extOnlyLayerIndex!= -1) {
+                hwc_layer_1_t *extLayer = &list->hwLayers[extOnlyLayerIndex];
+                hnd = (private_handle_t *)extLayer->handle;
+            } else if(copybitDone) {
+                hnd = ctx->mCopyBit[dpy]->getCurrentRenderBuffer();
+            }
+
+            if(hnd && !isYuvBuffer(hnd)) {
+                if (!ctx->mFBUpdate[dpy]->draw(ctx, hnd)) {
+                    ALOGE("%s: FBUpdate::draw fail!", __FUNCTION__);
+                    ret = -1;
+                }
+            }
         }
 
         if (display_commit(ctx, dpy) < 0) {
diff --git a/libhwcomposer/hwc_fbupdate.cpp b/libhwcomposer/hwc_fbupdate.cpp
index 7ed0577..2ec6019 100644
--- a/libhwcomposer/hwc_fbupdate.cpp
+++ b/libhwcomposer/hwc_fbupdate.cpp
@@ -34,8 +34,9 @@
 
 namespace ovutils = overlay::utils;
 
-IFBUpdate* IFBUpdate::getObject(const int& width, const int& dpy) {
-    if(width > MAX_DISPLAY_DIM) {
+IFBUpdate* IFBUpdate::getObject(const int& width, const int& rightSplit,
+        const int& dpy) {
+    if(width > MAX_DISPLAY_DIM || rightSplit) {
         return new FBUpdateHighRes(dpy);
     }
     return new FBUpdateLowRes(dpy);
@@ -223,7 +224,7 @@
 
 // Configure
 bool FBUpdateHighRes::configure(hwc_context_t *ctx,
-                                hwc_display_contents_1 *list, int fbZorder) {
+        hwc_display_contents_1 *list, int fbZorder) {
     bool ret = false;
     hwc_layer_1_t *layer = &list->hwLayers[list->numHwLayers - 1];
     if (LIKELY(ctx->mOverlay)) {
@@ -287,14 +288,33 @@
             getNonWormholeRegion(list, sourceCrop);
             displayFrame = sourceCrop;
         }
-        ovutils::Dim dcropL(sourceCrop.left, sourceCrop.top,
-                            (sourceCrop.right - sourceCrop.left) / 2,
-                            sourceCrop.bottom - sourceCrop.top);
+
+        const float xres = ctx->dpyAttr[mDpy].xres;
+        //Default even split for all displays with high res
+        float lSplit = xres / 2;
+        if(mDpy == HWC_DISPLAY_PRIMARY &&
+                qdutils::MDPVersion::getInstance().getLeftSplit()) {
+            //Override if split published by driver for primary
+            lSplit = qdutils::MDPVersion::getInstance().getLeftSplit();
+        }
+
+        const float lSplitRatio = lSplit / xres;
+
+        const float lCropWidth =
+                (sourceCrop.right - sourceCrop.left) * lSplitRatio;
+
+        ovutils::Dim dcropL(
+                sourceCrop.left,
+                sourceCrop.top,
+                lCropWidth,
+                sourceCrop.bottom - sourceCrop.top);
+
         ovutils::Dim dcropR(
-            sourceCrop.left + (sourceCrop.right - sourceCrop.left) / 2,
-            sourceCrop.top,
-            (sourceCrop.right - sourceCrop.left) / 2,
-            sourceCrop.bottom - sourceCrop.top);
+                sourceCrop.left + lCropWidth,
+                sourceCrop.top,
+                (sourceCrop.right - sourceCrop.left) - lCropWidth,
+                sourceCrop.bottom - sourceCrop.top);
+
         ov.setCrop(dcropL, destL);
         ov.setCrop(dcropR, destR);
 
@@ -304,19 +324,19 @@
         ov.setTransform(orient, destL);
         ov.setTransform(orient, destR);
 
-        const int halfWidth = (displayFrame.right - displayFrame.left) / 2;
+        const int lWidth = (lSplit - displayFrame.left);
+        const int rWidth = (displayFrame.right - lSplit);
         const int height = displayFrame.bottom - displayFrame.top;
 
-        const int halfDpy = ctx->dpyAttr[mDpy].xres / 2;
-        ovutils::Dim dposL(halfDpy - halfWidth,
+        ovutils::Dim dposL(displayFrame.left,
                            displayFrame.top,
-                           halfWidth,
+                           lWidth,
                            height);
         ov.setPosition(dposL, destL);
 
         ovutils::Dim dposR(0,
                            displayFrame.top,
-                           halfWidth,
+                           rWidth,
                            height);
         ov.setPosition(dposR, destR);
 
diff --git a/libhwcomposer/hwc_fbupdate.h b/libhwcomposer/hwc_fbupdate.h
index 5cf75f7..55cd655 100644
--- a/libhwcomposer/hwc_fbupdate.h
+++ b/libhwcomposer/hwc_fbupdate.h
@@ -45,7 +45,8 @@
     //Reset values
     virtual void reset();
     //Factory method that returns a low-res or high-res version
-    static IFBUpdate *getObject(const int& width, const int& dpy);
+    static IFBUpdate *getObject(const int& width, const int& rightSplit,
+            const int& dpy);
 
 protected:
     const int mDpy; // display to update
@@ -59,12 +60,12 @@
     explicit FBUpdateLowRes(const int& dpy);
     virtual ~FBUpdateLowRes() {};
     bool prepare(hwc_context_t *ctx, hwc_display_contents_1 *list,
-                                                          int fbZorder);
+            int fbZorder);
     bool draw(hwc_context_t *ctx, private_handle_t *hnd);
     void reset();
 private:
     bool configure(hwc_context_t *ctx, hwc_display_contents_1 *list,
-                                                               int fbZorder);
+            int fbZorder);
     ovutils::eDest mDest; //pipe to draw on
 };
 
@@ -74,12 +75,12 @@
     explicit FBUpdateHighRes(const int& dpy);
     virtual ~FBUpdateHighRes() {};
     bool prepare(hwc_context_t *ctx, hwc_display_contents_1 *list,
-                                                             int fbZorder);
+            int fbZorder);
     bool draw(hwc_context_t *ctx, private_handle_t *hnd);
     void reset();
 private:
     bool configure(hwc_context_t *ctx, hwc_display_contents_1 *list,
-                                                            int fbZorder);
+            int fbZorder);
     ovutils::eDest mDestLeft; //left pipe to draw on
     ovutils::eDest mDestRight; //right pipe to draw on
 };
diff --git a/libhwcomposer/hwc_mdpcomp.cpp b/libhwcomposer/hwc_mdpcomp.cpp
index ba6cae7..2103cb4 100644
--- a/libhwcomposer/hwc_mdpcomp.cpp
+++ b/libhwcomposer/hwc_mdpcomp.cpp
@@ -40,18 +40,19 @@
 bool MDPComp::sEnableMixedMode = true;
 int MDPComp::sMaxPipesPerMixer = MAX_PIPES_PER_MIXER;
 
-MDPComp* MDPComp::getObject(const int& width, int dpy) {
-    if(width <= MAX_DISPLAY_DIM) {
-        return new MDPCompLowRes(dpy);
-    } else {
+MDPComp* MDPComp::getObject(const int& width, const int& rightSplit,
+        const int& dpy) {
+    if(width > MAX_DISPLAY_DIM || rightSplit) {
         return new MDPCompHighRes(dpy);
     }
+    return new MDPCompLowRes(dpy);
 }
 
 MDPComp::MDPComp(int dpy):mDpy(dpy){};
 
 void MDPComp::dump(android::String8& buf)
 {
+    Locker::Autolock _l(mMdpCompLock);
     dumpsys_log(buf,"HWC Map for Dpy: %s \n",
                 mDpy ? "\"EXTERNAL\"" : "\"PRIMARY\"");
     dumpsys_log(buf,"PREV_FRAME: layerCount:%2d    mdpCount:%2d \
@@ -756,6 +757,9 @@
                  __FUNCTION__);
         return 0;
     }
+
+    Locker::Autolock _l(mMdpCompLock);
+
     //reset old data
     mCurrentFrame.reset(numLayers);
 
@@ -894,6 +898,8 @@
         return false;
     }
 
+    Locker::Autolock _l(mMdpCompLock);
+
     /* reset Invalidator */
     if(idleInvalidator && !sIdleFallBack && mCurrentFrame.mdpCount)
         idleInvalidator->markForSleep();
@@ -954,17 +960,24 @@
 //=============MDPCompHighRes===================================================
 
 int MDPCompHighRes::pipesNeeded(hwc_context_t *ctx,
-                                hwc_display_contents_1_t* list) {
+        hwc_display_contents_1_t* list) {
     int pipesNeeded = 0;
-    int hw_w = ctx->dpyAttr[mDpy].xres;
+    const int xres = ctx->dpyAttr[mDpy].xres;
+    //Default even split for all displays with high res
+    int lSplit = xres / 2;
+    if(mDpy == HWC_DISPLAY_PRIMARY &&
+            qdutils::MDPVersion::getInstance().getLeftSplit()) {
+        //Override if split published by driver for primary
+        lSplit = qdutils::MDPVersion::getInstance().getLeftSplit();
+    }
 
     for(int i = 0; i < mCurrentFrame.layerCount; ++i) {
         if(!mCurrentFrame.isFBComposed[i]) {
             hwc_layer_1_t* layer = &list->hwLayers[i];
             hwc_rect_t dst = layer->displayFrame;
-            if(dst.left > hw_w/2) {
+            if(dst.left > lSplit) {
                 pipesNeeded++;
-            } else if(dst.right <= hw_w/2) {
+            } else if(dst.right <= lSplit) {
                 pipesNeeded++;
             } else {
                 pipesNeeded += 2;
@@ -975,17 +988,24 @@
 }
 
 bool MDPCompHighRes::acquireMDPPipes(hwc_context_t *ctx, hwc_layer_1_t* layer,
-                                     MdpPipeInfoHighRes& pipe_info,
-                                     ePipeType type) {
-    int hw_w = ctx->dpyAttr[mDpy].xres;
+        MdpPipeInfoHighRes& pipe_info,
+        ePipeType type) {
+    const int xres = ctx->dpyAttr[mDpy].xres;
+    //Default even split for all displays with high res
+    int lSplit = xres / 2;
+    if(mDpy == HWC_DISPLAY_PRIMARY &&
+            qdutils::MDPVersion::getInstance().getLeftSplit()) {
+        //Override if split published by driver for primary
+        lSplit = qdutils::MDPVersion::getInstance().getLeftSplit();
+    }
 
     hwc_rect_t dst = layer->displayFrame;
-    if(dst.left > hw_w/2) {
+    if(dst.left > lSplit) {
         pipe_info.lIndex = ovutils::OV_INVALID;
         pipe_info.rIndex = getMdpPipe(ctx, type);
         if(pipe_info.rIndex == ovutils::OV_INVALID)
             return false;
-    } else if (dst.right <= hw_w/2) {
+    } else if (dst.right <= lSplit) {
         pipe_info.rIndex = ovutils::OV_INVALID;
         pipe_info.lIndex = getMdpPipe(ctx, type);
         if(pipe_info.lIndex == ovutils::OV_INVALID)
@@ -1035,7 +1055,7 @@
  * Configures pipe(s) for MDP composition
  */
 int MDPCompHighRes::configure(hwc_context_t *ctx, hwc_layer_1_t *layer,
-                              PipeLayerPair& PipeLayerPair) {
+        PipeLayerPair& PipeLayerPair) {
     MdpPipeInfoHighRes& mdp_info =
         *(static_cast<MdpPipeInfoHighRes*>(PipeLayerPair.pipeInfo));
     eZorder zOrder = static_cast<eZorder>(mdp_info.zOrder);
@@ -1063,6 +1083,8 @@
         return false;
     }
 
+    Locker::Autolock _l(mMdpCompLock);
+
     /* reset Invalidator */
     if(idleInvalidator && !sIdleFallBack && mCurrentFrame.mdpCount)
         idleInvalidator->markForSleep();
diff --git a/libhwcomposer/hwc_mdpcomp.h b/libhwcomposer/hwc_mdpcomp.h
index 6e04918..ea7c7b1 100644
--- a/libhwcomposer/hwc_mdpcomp.h
+++ b/libhwcomposer/hwc_mdpcomp.h
@@ -46,7 +46,8 @@
     /* dumpsys */
     void dump(android::String8& buf);
 
-    static MDPComp* getObject(const int& width, const int dpy);
+    static MDPComp* getObject(const int& width, const int& rightSplit,
+            const int& dpy);
     /* Handler to invoke frame redraw on Idle Timer expiry */
     static void timeout_handler(void *udata);
     /* Initialize MDP comp*/
@@ -173,6 +174,7 @@
     static IdleInvalidator *idleInvalidator;
     struct FrameInfo mCurrentFrame;
     struct LayerCache mCachedFrame;
+    mutable Locker mMdpCompLock;
 };
 
 class MDPCompLowRes : public MDPComp {
diff --git a/libhwcomposer/hwc_uevents.cpp b/libhwcomposer/hwc_uevents.cpp
index 1751cba..28b1849 100644
--- a/libhwcomposer/hwc_uevents.cpp
+++ b/libhwcomposer/hwc_uevents.cpp
@@ -31,6 +31,7 @@
 #include "hwc_copybit.h"
 #include "comptype.h"
 #include "external.h"
+#include "mdp_version.h"
 
 namespace qhwc {
 #define HWC_UEVENT_SWITCH_STR  "change@/devices/virtual/switch/"
@@ -53,8 +54,11 @@
 
 static void setup(hwc_context_t* ctx, int dpy, bool usecopybit)
 {
-    ctx->mFBUpdate[dpy] = IFBUpdate::getObject(ctx->dpyAttr[dpy].xres, dpy);
-    ctx->mMDPComp[dpy] =  MDPComp::getObject(ctx->dpyAttr[dpy].xres, dpy);
+    const int rSplit = 0; //Even split for external if at all
+    ctx->mFBUpdate[dpy] = IFBUpdate::getObject(ctx->dpyAttr[dpy].xres,
+            rSplit, dpy);
+    ctx->mMDPComp[dpy] =  MDPComp::getObject(ctx->dpyAttr[dpy].xres,
+            rSplit, dpy);
     if(usecopybit)
         ctx->mCopyBit[dpy] = new CopyBit();
 }
diff --git a/libhwcomposer/hwc_utils.cpp b/libhwcomposer/hwc_utils.cpp
index 1bb683a..90038f2 100644
--- a/libhwcomposer/hwc_utils.cpp
+++ b/libhwcomposer/hwc_utils.cpp
@@ -126,6 +126,7 @@
     ctx->mMDP.version = qdutils::MDPVersion::getInstance().getMDPVersion();
     ctx->mMDP.hasOverlay = qdutils::MDPVersion::getInstance().hasOverlay();
     ctx->mMDP.panel = qdutils::MDPVersion::getInstance().getPanelType();
+    const int rightSplit = qdutils::MDPVersion::getInstance().getRightSplit();
     overlay::Overlay::initOverlay();
     ctx->mOverlay = overlay::Overlay::getInstance();
     ctx->mRotMgr = new RotMgr();
@@ -135,7 +136,7 @@
     //on what external we connect to.
     ctx->mFBUpdate[HWC_DISPLAY_PRIMARY] =
         IFBUpdate::getObject(ctx->dpyAttr[HWC_DISPLAY_PRIMARY].xres,
-        HWC_DISPLAY_PRIMARY);
+                rightSplit, HWC_DISPLAY_PRIMARY);
 
     // Check if the target supports copybit compostion (dyn/mdp/c2d) to
     // decide if we need to open the copybit module.
@@ -152,11 +153,13 @@
 
     ctx->mMDPComp[HWC_DISPLAY_PRIMARY] =
          MDPComp::getObject(ctx->dpyAttr[HWC_DISPLAY_PRIMARY].xres,
-         HWC_DISPLAY_PRIMARY);
+                rightSplit, HWC_DISPLAY_PRIMARY);
 
     for (uint32_t i = 0; i < MAX_DISPLAYS; i++) {
         ctx->mHwcDebug[i] = new HwcDebug(i);
+        ctx->mLayerRotMap[i] = new LayerRotMap();
     }
+
     MDPComp::init(ctx);
 
     ctx->vstate.enable = false;
@@ -226,6 +229,10 @@
             delete ctx->mHwcDebug[i];
             ctx->mHwcDebug[i] = NULL;
         }
+        if(ctx->mLayerRotMap[i]) {
+            delete ctx->mLayerRotMap[i];
+            ctx->mLayerRotMap[i] = NULL;
+        }
     }
 
 
@@ -619,18 +626,25 @@
 }
 
 int hwc_sync(hwc_context_t *ctx, hwc_display_contents_1_t* list, int dpy,
-                                                        int fd) {
+        int fd) {
     int ret = 0;
-    struct mdp_buf_sync data;
     int acquireFd[MAX_NUM_APP_LAYERS];
     int count = 0;
     int releaseFd = -1;
     int fbFd = -1;
-    memset(&data, 0, sizeof(data));
+    int rotFd = -1;
     bool swapzero = false;
+    int mdpVersion = qdutils::MDPVersion::getInstance().getMDPVersion();
+
+    struct mdp_buf_sync data;
+    memset(&data, 0, sizeof(data));
+    //Until B-family supports sync for rotator
+#ifdef MDSS_TARGET
     data.flags = MDP_BUF_SYNC_FLAG_WAIT;
+#endif
     data.acq_fen_fd = acquireFd;
     data.rel_fen_fd = &releaseFd;
+
     char property[PROPERTY_VALUE_MAX];
     if(property_get("debug.egl.swapinterval", property, "1") > 0) {
         if(atoi(property) == 0)
@@ -640,10 +654,35 @@
     if(dpy)
        isExtAnimating = ctx->listStats[dpy].isDisplayAnimating;
 
-    //Accumulate acquireFenceFds
+    //Send acquireFenceFds to rotator
+#ifdef MDSS_TARGET
+    //TODO B-family
+#else
+    //A-family
+    int rotFd = ctx->mRotMgr->getRotDevFd();
+    struct msm_rotator_buf_sync rotData;
+
+    for(uint32_t i = 0; i < ctx->mLayerRotMap[dpy]->getCount(); i++) {
+        memset(&rotData, 0, sizeof(rotData));
+        int& acquireFenceFd =
+                ctx->mLayerRotMap[dpy]->getLayer(i)->acquireFenceFd;
+        rotData.acq_fen_fd = acquireFenceFd;
+        rotData.session_id = ctx->mLayerRotMap[dpy]->getRot(i)->getSessId();
+        ioctl(rotFd, MSM_ROTATOR_IOCTL_BUFFER_SYNC, &rotData);
+        close(acquireFenceFd);
+        //For MDP to wait on.
+        acquireFenceFd = dup(rotData.rel_fen_fd);
+        //A buffer is free to be used by producer as soon as its copied to
+        //rotator.
+        ctx->mLayerRotMap[dpy]->getLayer(i)->releaseFenceFd =
+                rotData.rel_fen_fd;
+    }
+#endif
+
+    //Accumulate acquireFenceFds for MDP
     for(uint32_t i = 0; i < list->numHwLayers; i++) {
         if(list->hwLayers[i].compositionType == HWC_OVERLAY &&
-                        list->hwLayers[i].acquireFenceFd != -1) {
+                        list->hwLayers[i].acquireFenceFd >= 0) {
             if(UNLIKELY(swapzero))
                 acquireFd[count++] = -1;
             else
@@ -652,19 +691,20 @@
         if(list->hwLayers[i].compositionType == HWC_FRAMEBUFFER_TARGET) {
             if(UNLIKELY(swapzero))
                 acquireFd[count++] = -1;
-            else if(fd != -1) {
+            else if(fd >= 0) {
                 //set the acquireFD from fd - which is coming from c2d
                 acquireFd[count++] = fd;
                 // Buffer sync IOCTL should be async when using c2d fence is
                 // used
                 data.flags &= ~MDP_BUF_SYNC_FLAG_WAIT;
-            } else if(list->hwLayers[i].acquireFenceFd != -1)
+            } else if(list->hwLayers[i].acquireFenceFd >= 0)
                 acquireFd[count++] = list->hwLayers[i].acquireFenceFd;
         }
     }
 
     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();
@@ -685,9 +725,9 @@
         if(list->hwLayers[i].compositionType == HWC_OVERLAY ||
            list->hwLayers[i].compositionType == HWC_FRAMEBUFFER_TARGET) {
             //Populate releaseFenceFds.
-            if(UNLIKELY(swapzero))
+            if(UNLIKELY(swapzero)) {
                 list->hwLayers[i].releaseFenceFd = -1;
-            else if(isExtAnimating) {
+            } else if(isExtAnimating) {
                 // Release all the app layer fds immediately,
                 // if animation is in progress.
                 hwc_layer_1_t const* layer = &list->hwLayers[i];
@@ -696,8 +736,10 @@
                     list->hwLayers[i].releaseFenceFd = dup(releaseFd);
                 } else
                     list->hwLayers[i].releaseFenceFd = -1;
-            } else
+            } else if(list->hwLayers[i].releaseFenceFd < 0) {
+                //If rotator has not already populated this field.
                 list->hwLayers[i].releaseFenceFd = dup(releaseFd);
+            }
         }
     }
 
@@ -708,11 +750,22 @@
 
     if (ctx->mCopyBit[dpy])
         ctx->mCopyBit[dpy]->setReleaseFd(releaseFd);
+
+#ifdef MDSS_TARGET
+    //TODO When B is implemented remove #ifdefs from here
+    //The API called applies to RotMem buffers
+#else
+    //A-family
+    //Signals when MDP finishes reading rotator buffers.
+    ctx->mLayerRotMap[dpy]->setReleaseFd(releaseFd);
+#endif
+
     // if external is animating, close the relaseFd
     if(isExtAnimating) {
         close(releaseFd);
         releaseFd = -1;
     }
+
     if(UNLIKELY(swapzero)){
         list->retireFenceFd = -1;
         close(releaseFd);
@@ -949,6 +1002,7 @@
             ctx->mOverlay->clear(dpy);
             return -1;
         }
+        ctx->mLayerRotMap[dpy]->add(layer, *rot);
         whf.format = (*rot)->getDstFormat();
         updateSource(orient, whf, crop);
         rotFlags |= ovutils::ROT_PREROTATED;
@@ -1024,6 +1078,7 @@
             ctx->mOverlay->clear(dpy);
             return -1;
         }
+        ctx->mLayerRotMap[dpy]->add(layer, *rot);
         whf.format = (*rot)->getDstFormat();
         updateSource(orient, whf, crop);
         rotFlags |= ROT_PREROTATED;
@@ -1035,23 +1090,24 @@
     hwc_rect_t tmp_cropL, tmp_dstL;
     hwc_rect_t tmp_cropR, tmp_dstR;
 
+    const int lSplit = qdutils::MDPVersion::getInstance().getLeftSplit();
     if(lDest != OV_INVALID) {
         tmp_cropL = crop;
         tmp_dstL = dst;
-        hwc_rect_t scissor = {0, 0, hw_w/2, hw_h };
+        hwc_rect_t scissor = {0, 0, lSplit, hw_h };
         qhwc::calculate_crop_rects(tmp_cropL, tmp_dstL, scissor, 0);
     }
     if(rDest != OV_INVALID) {
         tmp_cropR = crop;
         tmp_dstR = dst;
-        hwc_rect_t scissor = {hw_w/2, 0, hw_w, hw_h };
+        hwc_rect_t scissor = {lSplit, 0, hw_w, hw_h };
         qhwc::calculate_crop_rects(tmp_cropR, tmp_dstR, scissor, 0);
     }
 
-    //When buffer is flipped, contents of mixer config also needs to swapped.
+    //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_V) && lDest != OV_INVALID
+    if((orient & OVERLAY_TRANSFORM_FLIP_H) && lDest != OV_INVALID
             && rDest != OV_INVALID && (*rot) == NULL) {
         hwc_rect_t new_cropR;
         new_cropR.left = tmp_cropL.left;
@@ -1088,8 +1144,8 @@
     if(rDest != OV_INVALID) {
         PipeArgs pargR(mdpFlagsR, whf, z, isFg,
                 static_cast<eRotFlags>(rotFlags));
-        tmp_dstR.right = tmp_dstR.right - hw_w/2;
-        tmp_dstR.left = tmp_dstR.left - hw_w/2;
+        tmp_dstR.right = tmp_dstR.right - lSplit;
+        tmp_dstR.left = tmp_dstR.left - lSplit;
         if(configMdp(ctx->mOverlay, pargR, orient,
                 tmp_cropR, tmp_dstR, metadata, rDest) < 0) {
             ALOGE("%s: commit failed for right mixer config", __FUNCTION__);
@@ -1156,4 +1212,25 @@
     ovutils::setMdpFlags(mdpFlags, ovutils::OV_MDSS_MDP_BWC_EN);
 }
 
+void LayerRotMap::add(hwc_layer_1_t* layer, Rotator *rot) {
+    if(mCount >= MAX_SESS) return;
+    mLayer[mCount] = layer;
+    mRot[mCount] = rot;
+    mCount++;
+}
+
+void LayerRotMap::reset() {
+    for (int i = 0; i < MAX_SESS; i++) {
+        mLayer[i] = 0;
+        mRot[i] = 0;
+    }
+    mCount = 0;
+}
+
+void LayerRotMap::setReleaseFd(const int& fence) {
+    for(uint32_t i = 0; i < mCount; i++) {
+        mRot[i]->setReleaseFd(dup(fence));
+    }
+}
+
 };//namespace qhwc
diff --git a/libhwcomposer/hwc_utils.h b/libhwcomposer/hwc_utils.h
index 916a59d..4146787 100644
--- a/libhwcomposer/hwc_utils.h
+++ b/libhwcomposer/hwc_utils.h
@@ -121,6 +121,36 @@
     HWC_COPYBIT = 0x00000002,
 };
 
+class LayerRotMap {
+public:
+    LayerRotMap() { reset(); }
+    enum { MAX_SESS = 3 };
+    void add(hwc_layer_1_t* layer, overlay::Rotator *rot);
+    void reset();
+    uint32_t getCount() const;
+    hwc_layer_1_t* getLayer(uint32_t index) const;
+    overlay::Rotator* getRot(uint32_t index) const;
+    void setReleaseFd(const int& fence);
+private:
+    hwc_layer_1_t* mLayer[MAX_SESS];
+    overlay::Rotator* mRot[MAX_SESS];
+    uint32_t mCount;
+};
+
+inline uint32_t LayerRotMap::getCount() const {
+    return mCount;
+}
+
+inline hwc_layer_1_t* LayerRotMap::getLayer(uint32_t index) const {
+    if(index >= mCount) return NULL;
+    return mLayer[index];
+}
+
+inline overlay::Rotator* LayerRotMap::getRot(uint32_t index) const {
+    if(index >= mCount) return NULL;
+    return mRot[index];
+}
+
 // -----------------------------------------------------------------------------
 // Utility functions - implemented in hwc_utils.cpp
 void dumpLayer(hwc_layer_1_t const* l);
@@ -301,7 +331,6 @@
     hwc_rect_t mPrevCropVideo;
     hwc_rect_t mPrevDestVideo;
     int mPrevTransformVideo;
-
     //Securing in progress indicator
     bool mSecuring;
     //External Display configuring progress indicator
@@ -318,6 +347,7 @@
     int mExtOrientation;
     //Flags the transition of a video session
     bool mVideoTransFlag;
+    qhwc::LayerRotMap *mLayerRotMap[MAX_DISPLAYS];
 };
 
 namespace qhwc {
diff --git a/liboverlay/Android.mk b/liboverlay/Android.mk
index ed2f503..a375284 100644
--- a/liboverlay/Android.mk
+++ b/liboverlay/Android.mk
@@ -6,7 +6,7 @@
 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
+LOCAL_SHARED_LIBRARIES        := $(common_libs) libqdutils libmemalloc libsync
 LOCAL_CFLAGS                  := $(common_flags) -DLOG_TAG=\"qdoverlay\"
 LOCAL_ADDITIONAL_DEPENDENCIES := $(common_deps)
 LOCAL_SRC_FILES := \
diff --git a/liboverlay/overlayRotator.cpp b/liboverlay/overlayRotator.cpp
index 3861297..2995580 100644
--- a/liboverlay/overlayRotator.cpp
+++ b/liboverlay/overlayRotator.cpp
@@ -26,6 +26,8 @@
 
 namespace overlay {
 
+//============Rotator=========================
+
 Rotator::~Rotator() {}
 
 Rotator* Rotator::getRotator() {
@@ -56,6 +58,9 @@
     return TYPE_MDP;
 }
 
+
+//============RotMem=========================
+
 bool RotMem::close() {
     bool ret = true;
     for(uint32_t i=0; i < RotMem::MAX_ROT_MEM; ++i) {
@@ -70,11 +75,46 @@
     return ret;
 }
 
+RotMem::Mem::Mem() : mCurrOffset(0) {
+    utils::memset0(mRotOffset);
+    for(int i = 0; i < ROT_NUM_BUFS; i++) {
+        mRelFence[i] = -1;
+    }
+}
+
+RotMem::Mem::~Mem() {
+    for(int i = 0; i < ROT_NUM_BUFS; i++) {
+        ::close(mRelFence[i]);
+        mRelFence[i] = -1;
+    }
+}
+
+void RotMem::Mem::setReleaseFd(const int& fence) {
+    int ret = 0;
+
+    if(mRelFence[mCurrOffset] >= 0) {
+        //Wait for previous usage of this buffer to be over.
+        //Can happen if rotation takes > vsync and a fast producer. i.e queue
+        //happens in subsequent vsyncs either because content is 60fps or
+        //because the producer is hasty sometimes.
+        ret = sync_wait(mRelFence[mCurrOffset], 1000);
+        if(ret < 0) {
+            ALOGE("%s: sync_wait error!! error no = %d err str = %s",
+                __FUNCTION__, errno, strerror(errno));
+        }
+        ::close(mRelFence[mCurrOffset]);
+    }
+    mRelFence[mCurrOffset] = fence;
+}
+
+//============RotMgr=========================
+
 RotMgr::RotMgr() {
     for(int i = 0; i < MAX_ROT_SESS; i++) {
         mRot[i] = 0;
     }
     mUseCount = 0;
+    mRotDevFd = -1;
 }
 
 RotMgr::~RotMgr() {
@@ -118,6 +158,8 @@
         }
     }
     mUseCount = 0;
+    ::close(mRotDevFd);
+    mRotDevFd = -1;
 }
 
 void RotMgr::getDump(char *buf, size_t len) {
@@ -131,4 +173,15 @@
     strncat(buf, str, strlen(str));
 }
 
+int RotMgr::getRotDevFd() {
+    //2nd check just in case
+    if(mRotDevFd < 0 && Rotator::getRotatorHwType() == Rotator::TYPE_MDP) {
+        mRotDevFd = ::open("/dev/msm_rotator", O_RDWR, 0);
+        if(mRotDevFd < 0) {
+            ALOGE("%s failed to open rotator device", __FUNCTION__);
+        }
+    }
+    return mRotDevFd;
+}
+
 }
diff --git a/liboverlay/overlayRotator.h b/liboverlay/overlayRotator.h
index 120721c..7f90160 100644
--- a/liboverlay/overlayRotator.h
+++ b/liboverlay/overlayRotator.h
@@ -38,6 +38,45 @@
 
 namespace overlay {
 
+/*
+   Manages the case where new rotator memory needs to be
+   allocated, before previous is freed, due to resolution change etc. If we make
+   rotator memory to be always max size, irrespctive of source resolution then
+   we don't need this RotMem wrapper. The inner class is sufficient.
+*/
+struct RotMem {
+    // Max rotator memory allocations
+    enum { MAX_ROT_MEM = 2};
+
+    //Manages the rotator buffer offsets.
+    struct Mem {
+        Mem();
+        ~Mem();
+        bool valid() { return m.valid(); }
+        bool close() { return m.close(); }
+        uint32_t size() const { return m.bufSz(); }
+        void setReleaseFd(const int& fence);
+        // Max rotator buffers
+        enum { ROT_NUM_BUFS = 2 };
+        // rotator data info dst offset
+        uint32_t mRotOffset[ROT_NUM_BUFS];
+        int mRelFence[ROT_NUM_BUFS];
+        // current offset slot from mRotOffset
+        uint32_t mCurrOffset;
+        OvMem m;
+    };
+
+    RotMem() : _curr(0) {}
+    Mem& curr() { return m[_curr % MAX_ROT_MEM]; }
+    const Mem& curr() const { return m[_curr % MAX_ROT_MEM]; }
+    Mem& prev() { return m[(_curr+1) % MAX_ROT_MEM]; }
+    RotMem& operator++() { ++_curr; return *this; }
+    void setReleaseFd(const int& fence) { curr().setReleaseFd(fence); }
+    bool close();
+    uint32_t _curr;
+    Mem m[MAX_ROT_MEM];
+};
+
 class Rotator
 {
 public:
@@ -56,50 +95,19 @@
     virtual bool queueBuffer(int fd, uint32_t offset) = 0;
     virtual void dump() const = 0;
     virtual void getDump(char *buf, size_t len) const = 0;
+    void setReleaseFd(const int& fence) { mMem.setReleaseFd(fence); }
     static Rotator *getRotator();
 
 protected:
+    /* Rotator memory manager */
+    RotMem mMem;
     explicit Rotator() {}
     static uint32_t calcOutputBufSize(const utils::Whf& destWhf);
 
 private:
     /*Returns rotator h/w type */
     static int getRotatorHwType();
-};
-
-/*
-   Manages the case where new rotator memory needs to be
-   allocated, before previous is freed, due to resolution change etc. If we make
-   rotator memory to be always max size, irrespctive of source resolution then
-   we don't need this RotMem wrapper. The inner class is sufficient.
-*/
-struct RotMem {
-    // Max rotator memory allocations
-    enum { MAX_ROT_MEM = 2};
-
-    //Manages the rotator buffer offsets.
-    struct Mem {
-        Mem() : mCurrOffset(0) {utils::memset0(mRotOffset); }
-        bool valid() { return m.valid(); }
-        bool close() { return m.close(); }
-        uint32_t size() const { return m.bufSz(); }
-        // Max rotator buffers
-        enum { ROT_NUM_BUFS = 2 };
-        // rotator data info dst offset
-        uint32_t mRotOffset[ROT_NUM_BUFS];
-        // current offset slot from mRotOffset
-        uint32_t mCurrOffset;
-        OvMem m;
-    };
-
-    RotMem() : _curr(0) {}
-    Mem& curr() { return m[_curr % MAX_ROT_MEM]; }
-    const Mem& curr() const { return m[_curr % MAX_ROT_MEM]; }
-    Mem& prev() { return m[(_curr+1) % MAX_ROT_MEM]; }
-    RotMem& operator++() { ++_curr; return *this; }
-    bool close();
-    uint32_t _curr;
-    Mem m[MAX_ROT_MEM];
+    friend class RotMgr;
 };
 
 /*
@@ -155,8 +163,6 @@
     utils::eTransform mOrientation;
     /* rotator fd */
     OvFD mFd;
-    /* Rotator memory manager */
-    RotMem mMem;
 
     friend Rotator* Rotator::getRotator();
 };
@@ -209,8 +215,6 @@
     utils::eTransform mOrientation;
     /* rotator fd */
     OvFD mFd;
-    /* Rotator memory manager */
-    RotMem mMem;
     /* Enable/Disable Mdss Rot*/
     bool mEnabled;
 
@@ -233,9 +237,11 @@
      * Expects a NULL terminated buffer of big enough size.
      */
     void getDump(char *buf, size_t len);
+    int getRotDevFd(); //Called on A-fam only
 private:
     overlay::Rotator *mRot[MAX_ROT_SESS];
     int mUseCount;
+    int mRotDevFd; //A-fam
 };
 
 
diff --git a/liboverlay/overlayUtils.cpp b/liboverlay/overlayUtils.cpp
index 9bfa34e..c3d00f1 100644
--- a/liboverlay/overlayUtils.cpp
+++ b/liboverlay/overlayUtils.cpp
@@ -368,11 +368,6 @@
     return fmt3D;
 }
 
-bool isMdssRotator() {
-    int mdpVersion = qdutils::MDPVersion::getInstance().getMDPVersion();
-    return (mdpVersion >= qdutils::MDSS_V5);
-}
-
 void getDump(char *buf, size_t len, const char *prefix,
         const mdp_overlay& ov) {
     char str[256] = {'\0'};
diff --git a/libqdutils/mdp_version.cpp b/libqdutils/mdp_version.cpp
index cac6b1d..04dcf9f 100644
--- a/libqdutils/mdp_version.cpp
+++ b/libqdutils/mdp_version.cpp
@@ -101,8 +101,8 @@
             ptype = fb_finfo.id;
         }
         panel_type = *ptype;
-
     }
+    mPanelType = panel_type;
     close(fb_fd);
     mMDPVersion = mdp_version;
     mHasOverlay = false;
@@ -113,9 +113,26 @@
     if(mMDPVersion >= MDSS_V5) {
         //TODO get this from driver
         mMDPDownscale = 4;
-    }
 
-    mPanelType = panel_type;
+        char split[64];
+        FILE* fp = fopen("/sys/class/graphics/fb0/msm_fb_split", "r");
+        if(fp){
+            //Format "left right" space as delimiter
+            if(fread(split, sizeof(char), 64, fp)) {
+                mSplit.mLeft = atoi(split);
+                ALOGI_IF(mSplit.mLeft, "Left Split=%d", mSplit.mLeft);
+                char *rght = strpbrk(split, " ");
+                if(rght)
+                    mSplit.mRight = atoi(rght + 1);
+                ALOGI_IF(rght, "Right Split=%d", mSplit.mRight);
+            }
+        } else {
+            ALOGE("Failed to open mdss_fb_split node");
+        }
+
+        if(fp)
+            fclose(fp);
+    }
 }
 
 bool MDPVersion::supportsDecimation() {
@@ -132,7 +149,17 @@
 }
 
 bool MDPVersion::is8x26() {
-    return mMdpRev == MDSS_MDP_HW_REV_101;
+    // check for 8x26 variants
+    // chip variants have same major number and minor numbers usually vary
+    // for e.g., MDSS_MDP_HW_REV_101 is 0x10010000
+    //                                    1001       -  major number
+    //                                        0000   -  minor number
+    // 8x26 v1 minor number is 0000
+    //      v2 minor number is 0001 etc..
+    if( mMdpRev >= MDSS_MDP_HW_REV_101 && mMdpRev < MDSS_MDP_HW_REV_102) {
+        return true;
+    }
+    return false;
 }
 
 }; //namespace qdutils
diff --git a/libqdutils/mdp_version.h b/libqdutils/mdp_version.h
index f7b16fa..e26f4d3 100644
--- a/libqdutils/mdp_version.h
+++ b/libqdutils/mdp_version.h
@@ -74,6 +74,16 @@
 #define WRITEBACK_PANEL  'a'
 #define LVDS_PANEL       'b'
 
+class MDPVersion;
+
+struct Split {
+    int mLeft;
+    int mRight;
+    Split() : mLeft(0), mRight(0){}
+    int left() { return mLeft; }
+    int right() { return mRight; }
+    friend class MDPVersion;
+};
 
 class MDPVersion : public Singleton <MDPVersion>
 {
@@ -91,6 +101,8 @@
     uint32_t getMaxMDPDownscale();
     bool supportsBWC();
     bool is8x26();
+    int getLeftSplit() { return mSplit.left(); }
+    int getRightSplit() { return mSplit.right(); }
 private:
     int mMDPVersion;
     char mPanelType;
@@ -101,6 +113,7 @@
     uint8_t mDMAPipes;
     uint32_t mFeatures;
     uint32_t mMDPDownscale;
+    Split mSplit;
 };
 }; //namespace qdutils
 #endif //INCLUDE_LIBQCOMUTILS_MDPVER