Merge "qdutils : Retain the system property for default idle time."
diff --git a/libcopybit/copybit.cpp b/libcopybit/copybit.cpp
index 2302d64..da18c7b 100644
--- a/libcopybit/copybit.cpp
+++ b/libcopybit/copybit.cpp
@@ -126,6 +126,8 @@
 static int get_format(int format) {
     switch (format) {
         case HAL_PIXEL_FORMAT_RGB_565:       return MDP_RGB_565;
+        case HAL_PIXEL_FORMAT_RGBA_5551:     return MDP_RGBA_5551;
+        case HAL_PIXEL_FORMAT_RGBA_4444:     return MDP_RGBA_4444;
         case HAL_PIXEL_FORMAT_RGBX_8888:     return MDP_RGBX_8888;
         case HAL_PIXEL_FORMAT_BGRX_8888:     return MDP_BGRX_8888;
         case HAL_PIXEL_FORMAT_RGB_888:       return MDP_RGB_888;
@@ -440,6 +442,8 @@
                 // we don't support plane alpha with RGBA formats
                 case HAL_PIXEL_FORMAT_RGBA_8888:
                 case HAL_PIXEL_FORMAT_BGRA_8888:
+                case HAL_PIXEL_FORMAT_RGBA_5551:
+                case HAL_PIXEL_FORMAT_RGBA_4444:
                     ALOGE ("%s : Unsupported Pixel format %d", __FUNCTION__,
                            src->format);
                     return -EINVAL;
@@ -580,7 +584,6 @@
     struct blitReq list1;
     memset((char *)&list1 , 0 ,sizeof (struct blitReq) );
     list1.count = 1;
-    int rel_fen_fd = -1;
     int my_tmp_get_fence = -1;
 
     list1.sync.acq_fen_fd  =  ctx->acqFence;
diff --git a/libcopybit/copybit.h b/libcopybit/copybit.h
index dbb89f0..9a6de9b 100644
--- a/libcopybit/copybit.h
+++ b/libcopybit/copybit.h
@@ -48,6 +48,8 @@
     COPYBIT_FORMAT_RGB_888      = HAL_PIXEL_FORMAT_RGB_888,
     COPYBIT_FORMAT_RGB_565      = HAL_PIXEL_FORMAT_RGB_565,
     COPYBIT_FORMAT_BGRA_8888    = HAL_PIXEL_FORMAT_BGRA_8888,
+    COPYBIT_FORMAT_RGBA_5551    = HAL_PIXEL_FORMAT_RGBA_5551,
+    COPYBIT_FORMAT_RGBA_4444    = HAL_PIXEL_FORMAT_RGBA_4444,
     COPYBIT_FORMAT_YCbCr_422_SP = 0x10,
     COPYBIT_FORMAT_YCrCb_420_SP = 0x11,
 };
diff --git a/libcopybit/copybit_c2d.cpp b/libcopybit/copybit_c2d.cpp
index 7841bb7..23daa27 100644
--- a/libcopybit/copybit_c2d.cpp
+++ b/libcopybit/copybit_c2d.cpp
@@ -265,6 +265,8 @@
         case HAL_PIXEL_FORMAT_RGBA_8888:      return C2D_COLOR_FORMAT_8888_ARGB |
                                               C2D_FORMAT_SWAP_RB;
         case HAL_PIXEL_FORMAT_BGRA_8888:      return C2D_COLOR_FORMAT_8888_ARGB;
+        case HAL_PIXEL_FORMAT_RGBA_5551:      return C2D_COLOR_FORMAT_5551_RGBA;
+        case HAL_PIXEL_FORMAT_RGBA_4444:      return C2D_COLOR_FORMAT_4444_RGBA;
         case HAL_PIXEL_FORMAT_YCbCr_420_SP:   return C2D_COLOR_FORMAT_420_NV12;
         case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:return C2D_COLOR_FORMAT_420_NV12;
         case HAL_PIXEL_FORMAT_YCrCb_420_SP:   return C2D_COLOR_FORMAT_420_NV21;
@@ -403,7 +405,9 @@
         case HAL_PIXEL_FORMAT_RGBX_8888:
         case HAL_PIXEL_FORMAT_RGB_888:
         case HAL_PIXEL_FORMAT_RGB_565:
-        case HAL_PIXEL_FORMAT_BGRA_8888: {
+        case HAL_PIXEL_FORMAT_BGRA_8888:
+        case HAL_PIXEL_FORMAT_RGBA_5551:
+        case HAL_PIXEL_FORMAT_RGBA_4444: {
             return COPYBIT_SUCCESS;
         }
         default:
diff --git a/libgralloc/alloc_controller.cpp b/libgralloc/alloc_controller.cpp
index c361095..4167ae2 100644
--- a/libgralloc/alloc_controller.cpp
+++ b/libgralloc/alloc_controller.cpp
@@ -141,6 +141,8 @@
                 bpp = 3;
                 break;
             case HAL_PIXEL_FORMAT_RGB_565:
+            case HAL_PIXEL_FORMAT_RGBA_5551:
+            case HAL_PIXEL_FORMAT_RGBA_4444:
                 bpp = 2;
                 break;
             default: break;
@@ -294,6 +296,7 @@
             // for targets/OEMs which do not need HW level protection
             // do not set ion secure flag & MM heap. Fallback to IOMMU heap.
             ionFlags |= ION_HEAP(ION_IOMMU_HEAP_ID);
+            data.allocType |= private_handle_t::PRIV_FLAGS_PROTECTED_BUFFER;
         }
     } else if(usage & GRALLOC_USAGE_PRIVATE_MM_HEAP) {
         //MM Heap is exclusively a secure heap.
@@ -400,6 +403,8 @@
             size = alignedw * alignedh * 3;
             break;
         case HAL_PIXEL_FORMAT_RGB_565:
+        case HAL_PIXEL_FORMAT_RGBA_5551:
+        case HAL_PIXEL_FORMAT_RGBA_4444:
         case HAL_PIXEL_FORMAT_RAW_SENSOR:
             size = alignedw * alignedh * 2;
             break;
diff --git a/libgralloc/gralloc_priv.h b/libgralloc/gralloc_priv.h
index 75b8349..d64914e 100644
--- a/libgralloc/gralloc_priv.h
+++ b/libgralloc/gralloc_priv.h
@@ -193,6 +193,8 @@
             PRIV_FLAGS_NOT_MAPPED         = 0x00001000,
             // Display on external only
             PRIV_FLAGS_EXTERNAL_ONLY      = 0x00002000,
+            // Set by HWC for protected non secure buffers
+            PRIV_FLAGS_PROTECTED_BUFFER   = 0x00004000,
             PRIV_FLAGS_VIDEO_ENCODER      = 0x00010000,
             PRIV_FLAGS_CAMERA_WRITE       = 0x00020000,
             PRIV_FLAGS_CAMERA_READ        = 0x00040000,
diff --git a/libhdmi/hdmi.cpp b/libhdmi/hdmi.cpp
index 4fb7cfa..1aee664 100644
--- a/libhdmi/hdmi.cpp
+++ b/libhdmi/hdmi.cpp
@@ -101,15 +101,16 @@
     }
     readCEUnderscanInfo();
     readResolution();
-    // TODO: Move this to activate
     /* Used for changing the resolution
-     * getUserMode will get the preferred
-     * mode set thru adb shell */
-    mCurrentMode = getUserMode();
-    if (mCurrentMode == -1) {
+     * getUserConfig will get the preferred
+     * config index set thru adb shell */
+    mActiveConfig = getUserConfig();
+    if (mActiveConfig == -1) {
         //Get the best mode and set
-        mCurrentMode = getBestMode();
+        mActiveConfig = getBestConfig();
     }
+    // Set the mode corresponding to the active index
+    mCurrentMode = mEDIDModes[mActiveConfig];
     setAttributes();
     // set system property
     property_set("hw.hdmiON", "1");
@@ -121,6 +122,14 @@
             && !strcmp(value, "true")) {
         mMDPDownscaleEnabled = true;
     }
+
+    // XXX: A debug property can be used to enable resolution change for
+    // testing purposes: debug.hwc.enable_resolution_change
+    mEnableResolutionChange = false;
+    if(property_get("debug.hwc.enable_resolution_change", value, "false")
+            && !strcmp(value, "true")) {
+        mEnableResolutionChange = true;
+    }
     return 0;
 }
 
@@ -425,8 +434,8 @@
     return -1;
 }
 
-/// Returns the user mode set(if any) using adb shell
-int HDMIDisplay::getUserMode() {
+/// Returns the index of the user mode set(if any) using adb shell
+int HDMIDisplay::getUserConfig() {
     /* Based on the property set the resolution */
     char property_value[PROPERTY_VALUE_MAX];
     property_get("hw.hdmi.resolution", property_value, "-1");
@@ -434,15 +443,16 @@
     // We dont support interlaced modes
     if(isValidMode(mode) && !isInterlacedMode(mode)) {
         ALOGD_IF(DEBUG, "%s: setting the HDMI mode = %d", __FUNCTION__, mode);
-        return mode;
+        return getModeIndex(mode);
     }
     return -1;
 }
 
-// Get the best mode for the current HD TV
-int HDMIDisplay::getBestMode() {
+// Get the index of the best mode for the current HD TV
+int HDMIDisplay::getBestConfig() {
     int bestOrder = 0;
     int bestMode = HDMI_VFRMT_640x480p60_4_3;
+    int bestModeIndex = -1;
     // for all the edid read, get the best mode
     for(int i = 0; i < mModeCount; i++) {
         int mode = mEDIDModes[i];
@@ -450,9 +460,19 @@
         if (order > bestOrder) {
             bestOrder = order;
             bestMode = mode;
+            bestModeIndex = i;
         }
     }
-    return bestMode;
+    // If we fail to read from EDID when HDMI is connected, then
+    // mModeCount will be 0 and bestModeIndex will be invalid.
+    // In this case, we populate the mEDIDModes structure with
+    // a default mode at index 0.
+    if (bestModeIndex == -1) {
+        bestModeIndex = 0;
+        mModeCount = 1;
+        mEDIDModes[bestModeIndex] = bestMode;
+    }
+    return bestModeIndex;
 }
 
 inline bool HDMIDisplay::isValidMode(int ID)
@@ -696,4 +716,79 @@
     mPrimaryWidth = primaryWidth;
 }
 
+int HDMIDisplay::setActiveConfig(int newConfig) {
+    if(newConfig < 0 || newConfig > mModeCount) {
+        ALOGE("%s Invalid configuration %d", __FUNCTION__, newConfig);
+        return -EINVAL;
+    }
+
+    // XXX: Currently, we only support a change in frame rate.
+    // We need to validate the new config before proceeding.
+    if (!isValidConfigChange(newConfig)) {
+        ALOGE("%s Invalid configuration %d", __FUNCTION__, newConfig);
+        return -EINVAL;
+    }
+
+    mCurrentMode =  mEDIDModes[newConfig];
+    mActiveConfig = newConfig;
+    activateDisplay();
+    ALOGD("%s config(%d) mode(%d)", __FUNCTION__, mActiveConfig, mCurrentMode);
+    return 0;
+}
+
+// returns false if the xres or yres of the new config do
+// not match the current config
+bool HDMIDisplay::isValidConfigChange(int newConfig) {
+    int newMode = mEDIDModes[newConfig];
+    uint32_t width = 0, height = 0, refresh = 0;
+    getAttrForConfig(newConfig, width, height, refresh);
+    return ((mXres == width) && (mYres == height)) || mEnableResolutionChange;
+}
+
+int HDMIDisplay::getModeIndex(int mode) {
+    int modeIndex = -1;
+    for(int i = 0; i < mModeCount; i++) {
+        if(mode == mEDIDModes[i]) {
+            modeIndex = i;
+            break;
+        }
+    }
+    return modeIndex;
+}
+
+int HDMIDisplay::getAttrForConfig(int config, uint32_t& xres,
+        uint32_t& yres, uint32_t& refresh) const {
+    if(config < 0 || config > mModeCount) {
+        ALOGE("%s Invalid configuration %d", __FUNCTION__, config);
+        return -EINVAL;
+    }
+    int mode = mEDIDModes[config];
+    uint32_t fps = 0;
+    // Retrieve the mode attributes from gEDIDData
+    for (int dataIndex = 0; dataIndex < gEDIDCount; dataIndex++) {
+        if (gEDIDData[dataIndex].mMode == mode) {
+            xres = gEDIDData[dataIndex].mWidth;
+            yres = gEDIDData[dataIndex].mHeight;
+            fps = gEDIDData[dataIndex].mFps;
+        }
+    }
+    refresh = (uint32_t) 1000000000l / fps;
+    ALOGD_IF(DEBUG, "%s xres(%d) yres(%d) fps(%d) refresh(%d)", __FUNCTION__,
+            xres, yres, fps, refresh);
+    return 0;
+}
+
+int HDMIDisplay::getDisplayConfigs(uint32_t* configs,
+        size_t* numConfigs) const {
+    if (*numConfigs <= 0) {
+        ALOGE("%s Invalid number of configs (%d)", __FUNCTION__, *numConfigs);
+        return -EINVAL;
+    }
+    *numConfigs = mModeCount;
+    for (int configIndex = 0; configIndex < mModeCount; configIndex++) {
+        configs[configIndex] = (uint32_t)configIndex;
+    }
+    return 0;
+}
+
 };
diff --git a/libhdmi/hdmi.h b/libhdmi/hdmi.h
index 605d9be..d262a63 100644
--- a/libhdmi/hdmi.h
+++ b/libhdmi/hdmi.h
@@ -68,6 +68,11 @@
     /* when HDMI is an EXTERNAL display, PRIMARY display attributes are needed
        for scaling mode */
     void setPrimaryAttributes(uint32_t primaryWidth, uint32_t primaryHeight);
+    int getActiveConfig() const { return mActiveConfig; };
+    int setActiveConfig(int newConfig);
+    int getAttrForConfig(int config, uint32_t& xres,
+            uint32_t& yres, uint32_t& refresh) const;
+    int getDisplayConfigs(uint32_t* configs, size_t* numConfigs) const;
 
 private:
     int getModeCount() const;
@@ -80,17 +85,26 @@
     bool writeHPDOption(int userOption) const;
     bool isValidMode(int mode);
     int  getModeOrder(int mode);
-    int  getUserMode();
-    int  getBestMode();
+    int  getUserConfig();
+    int  getBestConfig();
     bool isInterlacedMode(int mode);
     void resetInfo();
     void setAttributes();
     void getAttrForMode(uint32_t& width, uint32_t& height, uint32_t& fps);
     int openDeviceNode(const char* node, int fileMode) const;
+    int getModeIndex(int mode);
+    bool isValidConfigChange(int newConfig);
 
     int mFd;
     int mFbNum;
+    // mCurrentMode is the HDMI video format that corresponds to the mEDIDMode
+    // entry referenced by mActiveConfig
     int mCurrentMode;
+    // mActiveConfig is the index correponding to the currently active mode for
+    // the HDMI display. It basically indexes the mEDIDMode array
+    int mActiveConfig;
+    // mEDIDModes contains a list of HDMI video formats (modes) supported by the
+    // HDMI display
     int mEDIDModes[64];
     int mModeCount;
     fb_var_screeninfo mVInfo;
@@ -102,6 +116,7 @@
     // Downscale feature switch, set via system property
     // sys.hwc.mdp_downscale_enabled
     bool mMDPDownscaleEnabled;
+    bool mEnableResolutionChange;
     int mDisplayId;
 };
 
diff --git a/libhwcomposer/hwc.cpp b/libhwcomposer/hwc.cpp
index b5ba073..0a7f940 100644
--- a/libhwcomposer/hwc.cpp
+++ b/libhwcomposer/hwc.cpp
@@ -113,11 +113,12 @@
     }
 }
 
-/* Based on certain conditions, isPaddingRound will be set
+/* Based on certain conditions, isDMAStateChanging will be set
  * to make this function self-contained */
 static void setDMAState(hwc_context_t *ctx, int numDisplays,
                         hwc_display_contents_1_t** displays) {
 
+    ctx->isDMAStateChanging = false;
     if(ctx->mRotMgr->getNumActiveSessions() == 0)
         Overlay::setDMAMode(Overlay::DMA_LINE_MODE);
 
@@ -142,7 +143,7 @@
                                           dpy)) {
                             if(ctx->mOverlay->isPipeTypeAttached(
                                              overlay::utils::OV_MDP_PIPE_DMA))
-                                ctx->isPaddingRound = true;
+                                ctx->isDMAStateChanging = true;
                         }
                         Overlay::setDMAMode(Overlay::DMA_BLOCK_MODE);
                     }
@@ -160,7 +161,7 @@
                 if(ctx->mExtOrientation || ctx->mBufferMirrorMode) {
                     if(ctx->mOverlay->isPipeTypeAttached(
                                          overlay::utils::OV_MDP_PIPE_DMA)) {
-                        ctx->isPaddingRound = true;
+                        ctx->isDMAStateChanging = true;
                     }
                     Overlay::setDMAMode(Overlay::DMA_BLOCK_MODE);
                 }
@@ -187,6 +188,12 @@
     }
 }
 
+static bool isHotPluggable(hwc_context_t *ctx, int dpy) {
+    return ((dpy == HWC_DISPLAY_EXTERNAL) ||
+            ((dpy == HWC_DISPLAY_PRIMARY) &&
+             ctx->mHDMIDisplay->isHDMIPrimaryDisplay()));
+}
+
 static void reset(hwc_context_t *ctx, int numDisplays,
                   hwc_display_contents_1_t** displays) {
 
@@ -735,40 +742,54 @@
 
 int hwc_getDisplayConfigs(struct hwc_composer_device_1* dev, int disp,
         uint32_t* configs, size_t* numConfigs) {
-    int ret = 0;
     hwc_context_t* ctx = (hwc_context_t*)(dev);
-    //Currently we allow only 1 config, reported as config id # 0
-    //This config is passed in to getDisplayAttributes. Ignored for now.
+
+    Locker::Autolock _l(ctx->mDrawLock);
+    bool hotPluggable = isHotPluggable(ctx, disp);
+    bool isVirtualDisplay = (disp == HWC_DISPLAY_VIRTUAL);
+    // If hotpluggable or virtual displays are inactive return error
+    if ((hotPluggable || isVirtualDisplay) && !ctx->dpyAttr[disp].connected) {
+        ALOGE("%s display (%d) is inactive", __FUNCTION__, disp);
+        return -EINVAL;
+    }
+
+    if (*numConfigs <= 0) {
+        ALOGE("%s Invalid number of configs (%d)", __FUNCTION__, *numConfigs);
+        return -EINVAL;
+    }
+
     switch(disp) {
         case HWC_DISPLAY_PRIMARY:
-            if(*numConfigs > 0) {
+            if (hotPluggable) {
+                ctx->mHDMIDisplay->getDisplayConfigs(configs, numConfigs);
+            } else {
                 configs[0] = 0;
                 *numConfigs = 1;
             }
-            ret = 0; //NO_ERROR
             break;
         case HWC_DISPLAY_EXTERNAL:
+                ctx->mHDMIDisplay->getDisplayConfigs(configs, numConfigs);
+            break;
         case HWC_DISPLAY_VIRTUAL:
-            ret = -1; //Not connected
-            if(ctx->dpyAttr[disp].connected) {
-                ret = 0; //NO_ERROR
-                if(*numConfigs > 0) {
-                    configs[0] = 0;
-                    *numConfigs = 1;
-                }
-            }
+            configs[0] = 0;
+            *numConfigs = 1;
             break;
     }
-    return ret;
+    return 0;
 }
 
 int hwc_getDisplayAttributes(struct hwc_composer_device_1* dev, int disp,
-        uint32_t /*config*/, const uint32_t* attributes, int32_t* values) {
+        uint32_t config, const uint32_t* attributes, int32_t* values) {
 
     hwc_context_t* ctx = (hwc_context_t*)(dev);
-    //If hotpluggable displays(i.e, HDMI, WFD) are inactive return error
-    if( (disp != HWC_DISPLAY_PRIMARY) && !ctx->dpyAttr[disp].connected) {
-        return -1;
+
+    Locker::Autolock _l(ctx->mDrawLock);
+    bool hotPluggable = isHotPluggable(ctx, disp);
+    bool isVirtualDisplay = (disp == HWC_DISPLAY_VIRTUAL);
+    // If hotpluggable or virtual displays are inactive return error
+    if ((hotPluggable || isVirtualDisplay) && !ctx->dpyAttr[disp].connected) {
+        ALOGE("%s display (%d) is inactive", __FUNCTION__, disp);
+        return -EINVAL;
     }
 
     //From HWComposer
@@ -784,16 +805,27 @@
     const size_t NUM_DISPLAY_ATTRIBUTES = (sizeof(DISPLAY_ATTRIBUTES) /
             sizeof(DISPLAY_ATTRIBUTES)[0]);
 
+    uint32_t xres = 0, yres = 0, refresh = 0;
+    int ret = 0;
+    if (hotPluggable) {
+        ret = ctx->mHDMIDisplay->getAttrForConfig(config, xres, yres, refresh);
+        if(ret < 0) {
+            ALOGE("%s Error getting attributes for config %d", config);
+            return ret;
+        }
+    }
+
     for (size_t i = 0; i < NUM_DISPLAY_ATTRIBUTES - 1; i++) {
         switch (attributes[i]) {
         case HWC_DISPLAY_VSYNC_PERIOD:
-            values[i] = ctx->dpyAttr[disp].vsync_period;
+            values[i] =
+                    hotPluggable ? refresh : ctx->dpyAttr[disp].vsync_period;
             break;
         case HWC_DISPLAY_WIDTH:
             if (ctx->dpyAttr[disp].customFBSize)
                 values[i] = ctx->dpyAttr[disp].xres_new;
             else
-                values[i] = ctx->dpyAttr[disp].xres;
+                values[i] = hotPluggable ? xres : ctx->dpyAttr[disp].xres;
 
             ALOGD("%s disp = %d, width = %d",__FUNCTION__, disp,
                     values[i]);
@@ -802,7 +834,7 @@
             if (ctx->dpyAttr[disp].customFBSize)
                 values[i] = ctx->dpyAttr[disp].yres_new;
             else
-                values[i] = ctx->dpyAttr[disp].yres;
+                values[i] = hotPluggable ? yres : ctx->dpyAttr[disp].yres;
             ALOGD("%s disp = %d, height = %d",__FUNCTION__, disp,
                     values[i]);
             break;
@@ -849,15 +881,49 @@
     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_getActiveConfig(struct hwc_composer_device_1* dev, int disp)
+{
+    hwc_context_t* ctx = (hwc_context_t*)(dev);
+
+    Locker::Autolock _l(ctx->mDrawLock);
+    bool hotPluggable = isHotPluggable(ctx, disp);
+    bool isVirtualDisplay = (disp == HWC_DISPLAY_VIRTUAL);
+    // If hotpluggable or virtual displays are inactive return error
+    if ((hotPluggable || isVirtualDisplay) && !ctx->dpyAttr[disp].connected) {
+        ALOGE("%s display (%d) is inactive", __FUNCTION__, disp);
+        return -EINVAL;
+    }
+
+    // For use cases when primary panel is the default interface we only have
+    // the default config (0th index)
+    if (!hotPluggable) {
+        return 0;
+    }
+
+    return ctx->mHDMIDisplay->getActiveConfig();
 }
 
-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;
+int hwc_setActiveConfig(struct hwc_composer_device_1* dev, int disp, int index)
+{
+    hwc_context_t* ctx = (hwc_context_t*)(dev);
+
+    Locker::Autolock _l(ctx->mDrawLock);
+    bool hotPluggable = isHotPluggable(ctx, disp);
+    bool isVirtualDisplay = (disp == HWC_DISPLAY_VIRTUAL);
+    // If hotpluggable or virtual displays are inactive return error
+    if ((hotPluggable || isVirtualDisplay) && !ctx->dpyAttr[disp].connected) {
+        ALOGE("%s display (%d) is inactive", __FUNCTION__, disp);
+        return -EINVAL;
+    }
+
+    // For use cases when primary panel is the default interface we only have
+    // the default config (0th index)
+    if (!hotPluggable) {
+        // Primary and virtual supports only the default config (0th index)
+        return (index == 0) ? index : -EINVAL;
+    }
+
+    return ctx->mHDMIDisplay->setActiveConfig(index);
 }
 
 static int hwc_device_close(struct hw_device_t *dev)
diff --git a/libhwcomposer/hwc_dump_layers.cpp b/libhwcomposer/hwc_dump_layers.cpp
index 0a92def..e717c26 100644
--- a/libhwcomposer/hwc_dump_layers.cpp
+++ b/libhwcomposer/hwc_dump_layers.cpp
@@ -331,6 +331,8 @@
                 tempSkBmpConfig = SkBitmap::kARGB_8888_Config;
                 break;
             case HAL_PIXEL_FORMAT_RGB_565:
+            case HAL_PIXEL_FORMAT_RGBA_5551:
+            case HAL_PIXEL_FORMAT_RGBA_4444:
                 tempSkBmpConfig = SkBitmap::kRGB_565_Config;
                 break;
             case HAL_PIXEL_FORMAT_RGB_888:
@@ -394,6 +396,12 @@
         case HAL_PIXEL_FORMAT_BGRA_8888:
             strlcpy(pixFormatStr, "BGRA_8888", sizeof(pixFormatStr));
             break;
+        case HAL_PIXEL_FORMAT_RGBA_5551:
+            strlcpy(pixFormatStr, "RGBA_5551", sizeof(pixFormatStr));
+            break;
+        case HAL_PIXEL_FORMAT_RGBA_4444:
+            strlcpy(pixFormatStr, "RGBA_4444", sizeof(pixFormatStr));
+            break;
         case HAL_PIXEL_FORMAT_YV12:
             strlcpy(pixFormatStr, "YV12", sizeof(pixFormatStr));
             break;
diff --git a/libhwcomposer/hwc_fbupdate.cpp b/libhwcomposer/hwc_fbupdate.cpp
index 43ae916..3e16072 100644
--- a/libhwcomposer/hwc_fbupdate.cpp
+++ b/libhwcomposer/hwc_fbupdate.cpp
@@ -157,6 +157,8 @@
         }
 
         ovutils::eMdpFlags mdpFlags = ovutils::OV_MDP_BLEND_FG_PREMULT;
+        ovutils::setMdpFlags(mdpFlags,
+                ovutils::OV_MDP_SMP_FORCE_ALLOC);
         ovutils::eZorder zOrder = static_cast<ovutils::eZorder>(fbZorder);
 
         hwc_rect_t sourceCrop = integerizeSourceCrop(layer->sourceCropf);
@@ -280,6 +282,8 @@
 
         overlay::Overlay& ov = *(ctx->mOverlay);
         ovutils::eMdpFlags mdpFlags = ovutils::OV_MDP_BLEND_FG_PREMULT;
+        ovutils::setMdpFlags(mdpFlags,
+                ovutils::OV_MDP_SMP_FORCE_ALLOC);
         ovutils::eZorder zOrder = static_cast<ovutils::eZorder>(fbZorder);
         ovutils::eTransform orient =
             static_cast<ovutils::eTransform>(layer->transform);
@@ -442,6 +446,8 @@
                 mTileEnabled));
 
     ovutils::eMdpFlags mdpFlags = OV_MDP_BLEND_FG_PREMULT;
+    ovutils::setMdpFlags(mdpFlags,
+                ovutils::OV_MDP_SMP_FORCE_ALLOC);
     ovutils::eZorder zOrder = static_cast<ovutils::eZorder>(fbZorder);
 
     ovutils::PipeArgs parg(mdpFlags,
diff --git a/libhwcomposer/hwc_mdpcomp.cpp b/libhwcomposer/hwc_mdpcomp.cpp
index 2904e6f..56d86ec 100644
--- a/libhwcomposer/hwc_mdpcomp.cpp
+++ b/libhwcomposer/hwc_mdpcomp.cpp
@@ -43,7 +43,7 @@
 bool MDPComp::sEnabled = false;
 bool MDPComp::sEnableMixedMode = true;
 int MDPComp::sSimulationFlags = 0;
-int MDPComp::sMaxPipesPerMixer = MAX_PIPES_PER_MIXER;
+int MDPComp::sMaxPipesPerMixer = 0;
 bool MDPComp::sEnableYUVsplit = false;
 bool MDPComp::sSrcSplitEnabled = false;
 bool MDPComp::enablePartialUpdateForMDP3 = false;
@@ -127,11 +127,15 @@
         sEnableMixedMode = false;
     }
 
-    sMaxPipesPerMixer = MAX_PIPES_PER_MIXER;
-    if(property_get("debug.mdpcomp.maxpermixer", property, "-1") > 0) {
+    qdutils::MDPVersion &mdpVersion = qdutils::MDPVersion::getInstance();
+
+    /* MDSS_MDP_STAGE_UNUSED and MDSS_MDP_STAGE_BASE are not available for MDP
+     * composition. */
+    sMaxPipesPerMixer = (int)mdpVersion.getBlendStages() - 2;
+    if(property_get("persist.hwc.mdpcomp.maxpermixer", property, "-1") > 0) {
         int val = atoi(property);
         if(val >= 0)
-            sMaxPipesPerMixer = min(val, MAX_PIPES_PER_MIXER);
+            sMaxPipesPerMixer = min(val, sMaxPipesPerMixer);
     }
 
     if(ctx->mMDP.panel != MIPI_CMD_PANEL) {
@@ -213,6 +217,16 @@
     ctx->proc->invalidate(ctx->proc);
 }
 
+void MDPComp::setMaxPipesPerMixer(const uint32_t value) {
+    qdutils::MDPVersion &mdpVersion = qdutils::MDPVersion::getInstance();
+    uint32_t maxSupported = (int)mdpVersion.getBlendStages() - 2;
+    if(value > maxSupported) {
+        ALOGW("%s: Input exceeds max value supported. Setting to"
+                "max value: %d", __FUNCTION__, maxSupported);
+    }
+    sMaxPipesPerMixer = min(value, maxSupported);
+}
+
 void MDPComp::setIdleTimeout(const uint32_t& timeout) {
     enum { ONE_REFRESH_PERIOD_MS = 17, ONE_BILLION_MS = 1000000000 };
 
@@ -268,7 +282,7 @@
 }
 
 void MDPComp::FrameInfo::reset(const int& numLayers) {
-    for(int i = 0; i < MAX_PIPES_PER_MIXER; i++) {
+    for(int i = 0 ; i < MAX_NUM_BLEND_STAGES; i++ ) {
         if(mdpToLayer[i].pipeInfo) {
             delete mdpToLayer[i].pipeInfo;
             mdpToLayer[i].pipeInfo = NULL;
@@ -466,7 +480,15 @@
                      __FUNCTION__,mDpy);
             ret = false;
         }
+    } else if (ctx->isDMAStateChanging) {
+        // Bail out if a padding round has been invoked in order to switch DMA
+        // state to block mode. We need this to cater for the case when a layer
+        // requires rotation in the current frame.
+        ALOGD_IF(isDebug(), "%s: padding round invoked to switch DMA state",
+                __FUNCTION__);
+        return false;
     }
+
     return ret;
 }
 
@@ -2061,7 +2083,7 @@
                              PipeLayerPair& PipeLayerPair) {
     MdpPipeInfoNonSplit& mdp_info =
         *(static_cast<MdpPipeInfoNonSplit*>(PipeLayerPair.pipeInfo));
-    eMdpFlags mdpFlags = OV_MDP_BACKEND_COMPOSITION;
+    eMdpFlags mdpFlags = ovutils::OV_MDP_FLAGS_NONE;
     eZorder zOrder = static_cast<eZorder>(mdp_info.zOrder);
     eDest dest = mdp_info.index;
 
@@ -2117,7 +2139,7 @@
     MdpYUVPipeInfo& mdp_info =
             *(static_cast<MdpYUVPipeInfo*>(PipeLayerPair.pipeInfo));
     eZorder zOrder = static_cast<eZorder>(mdp_info.zOrder);
-    eMdpFlags mdpFlagsL = OV_MDP_BACKEND_COMPOSITION;
+    eMdpFlags mdpFlagsL = ovutils::OV_MDP_FLAGS_NONE;
     eDest lDest = mdp_info.lIndex;
     eDest rDest = mdp_info.rIndex;
 
@@ -2349,7 +2371,7 @@
         MdpYUVPipeInfo& mdp_info =
                 *(static_cast<MdpYUVPipeInfo*>(PipeLayerPair.pipeInfo));
         eZorder zOrder = static_cast<eZorder>(mdp_info.zOrder);
-        eMdpFlags mdpFlagsL = OV_MDP_BACKEND_COMPOSITION;
+        eMdpFlags mdpFlagsL = ovutils::OV_MDP_FLAGS_NONE;
         eDest lDest = mdp_info.lIndex;
         eDest rDest = mdp_info.rIndex;
 
@@ -2369,7 +2391,7 @@
     MdpPipeInfoSplit& mdp_info =
         *(static_cast<MdpPipeInfoSplit*>(PipeLayerPair.pipeInfo));
     eZorder zOrder = static_cast<eZorder>(mdp_info.zOrder);
-    eMdpFlags mdpFlagsL = OV_MDP_BACKEND_COMPOSITION;
+    eMdpFlags mdpFlagsL = ovutils::OV_MDP_FLAGS_NONE;
     eDest lDest = mdp_info.lIndex;
     eDest rDest = mdp_info.rIndex;
 
@@ -2616,7 +2638,7 @@
     calcExtDisplayPosition(ctx, hnd, mDpy, crop, dst, transform, orient);
 
     int downscale = getRotDownscale(ctx, layer);
-    eMdpFlags mdpFlags = OV_MDP_BACKEND_COMPOSITION;
+    eMdpFlags mdpFlags = ovutils::OV_MDP_FLAGS_NONE;
     setMdpFlags(ctx, layer, mdpFlags, downscale, transform);
 
     if(lDest != OV_INVALID && rDest != OV_INVALID) {
diff --git a/libhwcomposer/hwc_mdpcomp.h b/libhwcomposer/hwc_mdpcomp.h
index 4634fbc..7fa6674 100644
--- a/libhwcomposer/hwc_mdpcomp.h
+++ b/libhwcomposer/hwc_mdpcomp.h
@@ -25,8 +25,6 @@
 #include <cutils/properties.h>
 #include <overlay.h>
 
-#define MAX_PIPES_PER_MIXER 4
-
 namespace overlay {
 class Rotator;
 };
@@ -57,6 +55,7 @@
     static bool isIdleFallback() { return sIdleFallBack; }
     static void dynamicDebug(bool enable){ sDebugLogs = enable; }
     static void setIdleTimeout(const uint32_t& timeout);
+    static void setMaxPipesPerMixer(const uint32_t value);
 
 protected:
     enum { MAX_SEC_LAYERS = 1 }; //TODO add property support
@@ -104,7 +103,7 @@
 
         /* maps mdp list to layer list */
         int mdpCount;
-        struct PipeLayerPair mdpToLayer[MAX_PIPES_PER_MIXER];
+        struct PipeLayerPair mdpToLayer[MAX_NUM_BLEND_STAGES];
 
         /* layer composing on FB? */
         int fbCount;
diff --git a/libhwcomposer/hwc_qclient.cpp b/libhwcomposer/hwc_qclient.cpp
index fd0a36c..0af8090 100644
--- a/libhwcomposer/hwc_qclient.cpp
+++ b/libhwcomposer/hwc_qclient.cpp
@@ -184,7 +184,7 @@
             handle_resume(ctx, dpy);
         }
     } else {
-        ALOGE("%s: Invalid dpy", __FUNCTION__, dpy);
+        ALOGE("%s: Invalid dpy %d", __FUNCTION__, dpy);
         return;
     }
 }
@@ -244,6 +244,13 @@
     MDPComp::setIdleTimeout(timeout);
 }
 
+static void setMaxPipesPerMixer(hwc_context_t* ctx, const Parcel* inParcel) {
+    uint32_t value = (uint32_t)inParcel->readInt32();
+    ALOGD("%s : setting MaxPipesPerMixer: %d ", __FUNCTION__, value);
+    Locker::Autolock _sl(ctx->mDrawLock);
+    MDPComp::setMaxPipesPerMixer(value);
+}
+
 status_t QClient::notifyCallback(uint32_t command, const Parcel* inParcel,
         Parcel* outParcel) {
     status_t ret = NO_ERROR;
@@ -289,6 +296,9 @@
         case IQService::SET_IDLE_TIMEOUT:
             setIdleTimeout(mHwcContext, inParcel);
             break;
+        case IQService::SET_MAX_PIPES_PER_MIXER:
+            setMaxPipesPerMixer(mHwcContext, inParcel);
+            break;
         default:
             ret = NO_ERROR;
     }
diff --git a/libhwcomposer/hwc_utils.cpp b/libhwcomposer/hwc_utils.cpp
index 3eec011..b091ae2 100644
--- a/libhwcomposer/hwc_utils.cpp
+++ b/libhwcomposer/hwc_utils.cpp
@@ -856,6 +856,9 @@
     src_w = sourceCrop.right - sourceCrop.left;
     src_h = sourceCrop.bottom - sourceCrop.top;
 
+    if(layer->transform & HWC_TRANSFORM_ROT_90)
+        swap(src_w, src_h);
+
     if(((src_w != dst_w) || (src_h != dst_h)))
         return true;
 
@@ -1151,22 +1154,26 @@
 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;
+    if(hnd != NULL) {
+        switch(hnd->format) {
+            case HAL_PIXEL_FORMAT_RGBA_8888:
+            case HAL_PIXEL_FORMAT_RGBA_5551:
+            case HAL_PIXEL_FORMAT_RGBA_4444:
+            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
+    // Rotate layers, if it is not secure display buffer and not
     // for the MDP versions below MDP5
-    if((isCPURendered(hnd) && isRotatorSupportedFormat(hnd) &&
+    if((!isSecureDisplayBuffer(hnd) && isRotatorSupportedFormat(hnd) &&
         !ctx->mMDP.version < qdutils::MDSS_V5)
                    || isYuvBuffer(hnd)) {
         return true;
@@ -1668,6 +1675,13 @@
     if(isSecureBuffer(hnd)) {
         ovutils::setMdpFlags(mdpFlags,
                 ovutils::OV_MDP_SECURE_OVERLAY_SESSION);
+        ovutils::setMdpFlags(mdpFlags,
+                ovutils::OV_MDP_SMP_FORCE_ALLOC);
+    }
+
+    if(isProtectedBuffer(hnd)) {
+        ovutils::setMdpFlags(mdpFlags,
+                ovutils::OV_MDP_SMP_FORCE_ALLOC);
     }
 
     if(isSecureDisplayBuffer(hnd)) {
diff --git a/libhwcomposer/hwc_utils.h b/libhwcomposer/hwc_utils.h
index b3d7047..96d1e58 100644
--- a/libhwcomposer/hwc_utils.h
+++ b/libhwcomposer/hwc_utils.h
@@ -41,6 +41,7 @@
 #define LIKELY( exp )       (__builtin_expect( (exp) != 0, true  ))
 #define UNLIKELY( exp )     (__builtin_expect( (exp) != 0, false ))
 #define MAX_NUM_APP_LAYERS 32
+#define MAX_NUM_BLEND_STAGES 16
 #define MIN_DISPLAY_XRES 200
 #define MIN_DISPLAY_YRES 200
 #define HWC_WFDDISPSYNC_LOG 0
@@ -463,12 +464,14 @@
     return (hnd && (private_handle_t::PRIV_FLAGS_SECURE_BUFFER & hnd->flags));
 }
 
-static inline bool isTileRendered(const private_handle_t* hnd) {
-    return (hnd && (private_handle_t::PRIV_FLAGS_TILE_RENDERED & hnd->flags));
+// Returns true if the buffer is protected
+static inline bool isProtectedBuffer(const private_handle_t* hnd) {
+    return (hnd && (private_handle_t::PRIV_FLAGS_PROTECTED_BUFFER & hnd->flags));
 }
 
-static inline bool isCPURendered(const private_handle_t* hnd) {
-    return (hnd && (private_handle_t::PRIV_FLAGS_CPU_RENDERED & hnd->flags));
+
+static inline bool isTileRendered(const private_handle_t* hnd) {
+    return (hnd && (private_handle_t::PRIV_FLAGS_TILE_RENDERED & hnd->flags));
 }
 
 //Return true if buffer is marked locked
@@ -601,6 +604,8 @@
     mutable Locker mDrawLock;
     //Drawing round when we use GPU
     bool isPaddingRound;
+    // Used to mark composition cycle when DMA state change is required
+    bool isDMAStateChanging;
     // External Orientation
     int mExtOrientation;
     //Flags the transition of a video session
diff --git a/libhwcomposer/hwc_vsync.cpp b/libhwcomposer/hwc_vsync.cpp
index 7b97c6c..722916a 100644
--- a/libhwcomposer/hwc_vsync.cpp
+++ b/libhwcomposer/hwc_vsync.cpp
@@ -88,9 +88,10 @@
         thermalLevel = strtoull(data + strlen("thermal_level="), NULL, 0);
     }
 
-    if (thermalLevel >= MAX_THERMAL_LEVEL)
+    if (thermalLevel >= MAX_THERMAL_LEVEL) {
+        ALOGD("%s: dpy:%d thermal_level=%"PRIu64"",__FUNCTION__,dpy,thermalLevel);
         ctx->mThermalBurstMode = true;
-    else
+    } else
         ctx->mThermalBurstMode = false;
 }
 
diff --git a/liboverlay/overlay.cpp b/liboverlay/overlay.cpp
index 96c057f..3a96b71 100644
--- a/liboverlay/overlay.cpp
+++ b/liboverlay/overlay.cpp
@@ -279,8 +279,29 @@
     uint8_t pipe2Prio = mPipeBook[(int)pipe2Index].mPipe->getPriority();
     if(pipe1Prio > pipe2Prio)
         return -1;
-    if(pipe1Prio < pipe2Prio)
+    else if(pipe1Prio < pipe2Prio)
         return 1;
+    else {
+        // If we are here, Source Split is enabled and both pipes are
+        // new requests. In this case left type should be of higher prio
+        // than right type
+        utils::eMdpPipeType leftType = PipeBook::getPipeType(pipe1Index);
+        utils::eMdpPipeType rightType = PipeBook::getPipeType(pipe2Index);
+
+        if(leftType == rightType) {
+            //Safe. Onus on driver to assign correct pipes within same type
+            return 1;
+        } else if(leftType == OV_MDP_PIPE_DMA or rightType == OV_MDP_PIPE_VG) {
+            //If we are here, right is definitely a higher prio type.
+            //This check takes advantage of having only 3 types and avoids 3
+            //different failure combination checks.
+            return -1;
+        } else {
+            //Types are correct priority-wise
+            return 1;
+        }
+    }
+
     return 0;
 }
 
diff --git a/liboverlay/overlayUtils.cpp b/liboverlay/overlayUtils.cpp
index cbd52ae..32b2013 100644
--- a/liboverlay/overlayUtils.cpp
+++ b/liboverlay/overlayUtils.cpp
@@ -93,6 +93,10 @@
             return MDP_RGB_888;
         case HAL_PIXEL_FORMAT_RGB_565:
             return MDP_RGB_565;
+        case HAL_PIXEL_FORMAT_RGBA_5551:
+            return MDP_RGBA_5551;
+        case HAL_PIXEL_FORMAT_RGBA_4444:
+            return MDP_RGBA_4444;
         case HAL_PIXEL_FORMAT_BGRA_8888:
             return MDP_BGRA_8888;
         case HAL_PIXEL_FORMAT_BGRX_8888:
@@ -126,9 +130,6 @@
             return MDP_Y_CBCR_H2V2_VENUS;
         default:
             //Unsupported by MDP
-            //---graphics.h--------
-            //HAL_PIXEL_FORMAT_RGBA_5551
-            //HAL_PIXEL_FORMAT_RGBA_4444
             //---gralloc_priv.h-----
             //HAL_PIXEL_FORMAT_YCrCb_420_SP_ADRENO    = 0x7FA30C01
             //HAL_PIXEL_FORMAT_R_8                    = 0x10D
@@ -180,6 +181,10 @@
             return HAL_PIXEL_FORMAT_RGB_888;
         case MDP_RGB_565:
             return HAL_PIXEL_FORMAT_RGB_565;
+        case MDP_RGBA_5551:
+            return HAL_PIXEL_FORMAT_RGBA_5551;
+        case MDP_RGBA_4444:
+            return HAL_PIXEL_FORMAT_RGBA_4444;
         case MDP_BGRA_8888:
             return HAL_PIXEL_FORMAT_BGRA_8888;
         case MDP_Y_CR_CB_GH2V2:
diff --git a/liboverlay/overlayUtils.h b/liboverlay/overlayUtils.h
index 2b8e303..54ee0fd 100644
--- a/liboverlay/overlayUtils.h
+++ b/liboverlay/overlayUtils.h
@@ -223,7 +223,6 @@
     OV_MDP_SECURE_OVERLAY_SESSION = MDP_SECURE_OVERLAY_SESSION,
     OV_MDP_SECURE_DISPLAY_OVERLAY_SESSION = MDP_SECURE_DISPLAY_OVERLAY_SESSION,
     OV_MDP_SOURCE_ROTATED_90 = MDP_SOURCE_ROTATED_90,
-    OV_MDP_BACKEND_COMPOSITION = MDP_BACKEND_COMPOSITION,
     OV_MDP_BLEND_FG_PREMULT = MDP_BLEND_FG_PREMULT,
     OV_MDP_FLIP_H = MDP_FLIP_LR,
     OV_MDP_FLIP_V = MDP_FLIP_UD,
@@ -232,6 +231,7 @@
     OV_MDSS_MDP_BWC_EN = MDP_BWC_EN,
     OV_MDSS_MDP_DUAL_PIPE = MDSS_MDP_DUAL_PIPE,
     OV_MDP_SOLID_FILL = MDP_SOLID_FILL,
+    OV_MDP_SMP_FORCE_ALLOC = MDP_SMP_FORCE_ALLOC,
 };
 
 enum eZorder {
@@ -239,6 +239,9 @@
     ZORDER_1,
     ZORDER_2,
     ZORDER_3,
+    ZORDER_4,
+    ZORDER_5,
+    ZORDER_6,
     Z_SYSTEM_ALLOC = 0xFFFF
 };
 
@@ -432,6 +435,8 @@
         case MDP_BGRA_8888:
         case MDP_RGBX_8888:
         case MDP_RGB_565:
+        case MDP_RGBA_4444:
+        case MDP_RGBA_5551:
             return true;
         default:
             return false;
@@ -443,6 +448,8 @@
     #define STR(f) #f;
     static const char* formats[MDP_IMGTYPE_LIMIT + 1] = {0};
     formats[MDP_RGB_565] = STR(MDP_RGB_565);
+    formats[MDP_RGBA_5551] = STR(MDP_RGBA_5551);
+    formats[MDP_RGBA_4444] = STR(MDP_RGBA_4444);
     formats[MDP_XRGB_8888] = STR(MDP_XRGB_8888);
     formats[MDP_Y_CBCR_H2V2] = STR(MDP_Y_CBCR_H2V2);
     formats[MDP_Y_CBCR_H2V2_ADRENO] = STR(MDP_Y_CBCR_H2V2_ADRENO);
diff --git a/libqdutils/mdp_version.cpp b/libqdutils/mdp_version.cpp
index 088f82b..f8729a5 100644
--- a/libqdutils/mdp_version.cpp
+++ b/libqdutils/mdp_version.cpp
@@ -57,7 +57,7 @@
 #define MDSS_MDP_HW_REV_103 0x10030000 //8084
 #endif
 #ifndef MDSS_MDP_HW_REV_104
-#define MDSS_MDP_HW_REV_104 0x10040000 //Next version
+#define MDSS_MDP_HW_REV_104 0x10040000 //Unused
 #endif
 #ifndef MDSS_MDP_HW_REV_105
 #define MDSS_MDP_HW_REV_105 0x10050000 //8994
@@ -66,13 +66,16 @@
 #define MDSS_MDP_HW_REV_106 0x10060000 //8x16
 #endif
 #ifndef MDSS_MDP_HW_REV_107
-#define MDSS_MDP_HW_REV_107 0x10070000 //Next version
+#define MDSS_MDP_HW_REV_107 0x10070000 //Unused
 #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
+#define MDSS_MDP_HW_REV_109 0x10090000 //8994 v2
+#endif
+#ifndef MDSS_MDP_HW_REV_110
+#define MDSS_MDP_HW_REV_110 0x100a0000 //Next version
 #endif
 #ifndef MDSS_MDP_HW_REV_200
 #define MDSS_MDP_HW_REV_200 0x20000000 //8092
@@ -98,6 +101,7 @@
     mSourceSplitAlways = false;
     mRGBHasNoScalar = false;
     mRotDownscale = false;
+    mBlendStages = 6; //min no. of stages supported by MDP.
 
     // this is the default limit of mixer unless driver reports it.
     // For resolutions beyond this, we use dual/split overlay pipes.
@@ -300,6 +304,10 @@
                 else if(!strncmp(tokens[0], "dma_pipes", strlen("dma_pipes"))) {
                     mDMAPipes = (uint8_t)atoi(tokens[1]);
                 }
+                else if(!strncmp(tokens[0], "blending_stages",
+                                strlen("blending_stages"))) {
+                    mBlendStages = (uint8_t)atoi(tokens[1]);
+                }
                 else if(!strncmp(tokens[0], "max_downscale_ratio",
                                 strlen("max_downscale_ratio"))) {
                     mMDPDownscale = atoi(tokens[1]);
@@ -470,8 +478,10 @@
 }
 
 bool MDPVersion::is8994() {
-    return (mMdpRev >= MDSS_MDP_HW_REV_105 and
-            mMdpRev < MDSS_MDP_HW_REV_106);
+    return ((mMdpRev >= MDSS_MDP_HW_REV_105 and
+            mMdpRev < MDSS_MDP_HW_REV_106) or
+            (mMdpRev >= MDSS_MDP_HW_REV_109 and
+            mMdpRev < MDSS_MDP_HW_REV_110));
 }
 
 bool MDPVersion::is8x16() {
diff --git a/libqdutils/mdp_version.h b/libqdutils/mdp_version.h
index 3c7f6a3..dcde240 100644
--- a/libqdutils/mdp_version.h
+++ b/libqdutils/mdp_version.h
@@ -116,6 +116,7 @@
     uint8_t getRGBPipes() { return mRGBPipes; }
     uint8_t getVGPipes() { return mVGPipes; }
     uint8_t getDMAPipes() { return mDMAPipes; }
+    uint8_t getBlendStages() { return mBlendStages; }
     bool supportsDecimation();
     uint32_t getMaxMDPDownscale();
     uint32_t getMaxMDPUpscale();
@@ -163,6 +164,7 @@
     uint8_t mRGBPipes;
     uint8_t mVGPipes;
     uint8_t mDMAPipes;
+    uint8_t mBlendStages;
     uint32_t mFeatures;
     uint32_t mMDPDownscale;
     uint32_t mMDPUpscale;
diff --git a/libqservice/IQService.h b/libqservice/IQService.h
index 87d51fc..6f2f0e3 100644
--- a/libqservice/IQService.h
+++ b/libqservice/IQService.h
@@ -50,7 +50,7 @@
         SET_HSIC_DATA,           // Set HSIC on dspp
         GET_DISPLAY_VISIBLE_REGION,  // Get the visibleRegion for dpy
         SET_SECONDARY_DISPLAY_STATUS,  // Sets secondary display status
-        UNUSED_SLOT,             // XXX: Unsed - New one can go here
+        SET_MAX_PIPES_PER_MIXER, // Set max pipes per mixer for MDPComp
         SET_VIEW_FRAME,          // Set view frame of display
         DYNAMIC_DEBUG,           // Enable more logging on the fly
         SET_IDLE_TIMEOUT,        // Set idle timeout for GPU fallback