Merge "sde: Add support for swapinterval 0"
diff --git a/common.mk b/common.mk
index 464f296..183ee99 100644
--- a/common.mk
+++ b/common.mk
@@ -29,6 +29,10 @@
     common_flags += -DVENUS_COLOR_FORMAT
 endif
 
+ifeq ($(call is-board-platform-in-list, $(MASTER_SIDE_CP_TARGET_LIST)), true)
+    common_flags += -DMASTER_SIDE_CP
+endif
+
 common_deps  :=
 kernel_includes :=
 
diff --git a/displayengine/include/core/layer_buffer.h b/displayengine/include/core/layer_buffer.h
index 2ab6b29..2493c13 100644
--- a/displayengine/include/core/layer_buffer.h
+++ b/displayengine/include/core/layer_buffer.h
@@ -134,20 +134,30 @@
   @sa LayerBuffer
 */
 struct LayerBufferFlags {
-  uint64_t secure : 1;      //!< This flag shall be set by client to indicate that the buffer need
-                            //!< to be handled securely.
-  uint64_t video  : 1;      //!< This flag shall be set by client to indicate that the buffer is
-                            //!< video/ui buffer
-  uint64_t macro_tile : 1;  //!< This flag shall be set by client to indicate that the buffer format
-                            //!< is macro tiled.
-  uint64_t interlace : 1;   //!< This flag shall be set by the client to indicate that the buffer
-                            //!< has interlaced content.
-  uint64_t secure_display : 1;
-                            //!< This flag shall be set by the client to indicate that the secure
-                            //!< display session is in progress. Secure display session cannot
-                            //!< coexist with non-secure session.
+  union {
+    struct {
+      uint32_t secure : 1;          //!< This flag shall be set by client to indicate that the
+                                    //!< buffer need to be handled securely.
 
-  LayerBufferFlags() : secure(0), video(0), macro_tile(0), interlace(0), secure_display(0) { }
+      uint32_t video  : 1;          //!< This flag shall be set by client to indicate that the
+                                    //!< buffer is video/ui buffer.
+
+      uint32_t macro_tile : 1;      //!< This flag shall be set by client to indicate that the
+                                    //!< buffer format is macro tiled.
+
+      uint32_t interlace : 1;       //!< This flag shall be set by the client to indicate that
+                                    //!< the buffer has interlaced content.
+
+      uint32_t secure_display : 1;
+                                    //!< This flag shall be set by the client to indicate that the
+                                    //!< secure display session is in progress. Secure display
+                                    //!< session can not coexist with non-secure session.
+      };
+
+      uint32_t flags;   //!< For initialization purpose only. Client shall not refer it directly.
+  };
+
+  LayerBufferFlags() : flags(0) { }
 };
 
 /*! @brief This structure defines a layer buffer handle which contains raw buffer and its associated
diff --git a/displayengine/include/core/layer_stack.h b/displayengine/include/core/layer_stack.h
index d85fd98..66f60e7 100644
--- a/displayengine/include/core/layer_stack.h
+++ b/displayengine/include/core/layer_stack.h
@@ -92,15 +92,22 @@
   @sa LayerBuffer
 */
 struct LayerFlags {
-  uint64_t skip : 1;      //!< This flag shall be set by client to indicate that this layer will be
-                          //!< handled by GPU. Display Device will not consider it for composition.
+  union {
+    struct {
+      uint32_t skip : 1;      //!< This flag shall be set by client to indicate that this layer
+                              //!< will be handled by GPU. Display Device will not consider it
+                              //!< for composition.
 
-  uint64_t updating : 1;  //!< This flag shall be set by client to indicate that this is updating/
-                          //!< non-updating. so strategy manager will mark them for SDE/GPU
-                          //!< composition respectively when the layer stack qualifies for cache
-                          //!< based composition.
+      uint32_t updating : 1;  //!< This flag shall be set by client to indicate that this is
+                              //!< updating non-updating. so strategy manager will mark them for
+                              //!< SDE/GPU composition respectively when the layer stack qualifies
+                              //!< for cache based composition.
+    };
 
-  LayerFlags() : skip(0), updating(0) { }
+    uint32_t flags;   //!< For initialization purpose only. Client shall not refer it directly.
+  };
+
+  LayerFlags() : flags(0) { }
 };
 
 /*! @brief This structure defines flags associated with a layer stack. The 1-bit flag can be set to
@@ -109,24 +116,29 @@
   @sa LayerBuffer
 */
 struct LayerStackFlags {
-  uint64_t geometry_changed : 1;  //!< This flag shall be set by client to indicate that the layer
-                                  //!< set passed to Prepare() has changed by more than just the
-                                  //!< buffer handles and acquire fences.
+  union {
+    struct {
+      uint32_t geometry_changed : 1;  //!< This flag shall be set by client to indicate that the
+                                      //!< layer set passed to Prepare() has changed by more than
+                                      //!< just the buffer handles and acquire fences.
 
-  uint64_t skip_present : 1;      //!< This flag will be set to true, if the current layer stack
-                                  //!< contains skip layers.
+      uint32_t skip_present : 1;      //!< This flag will be set to true, if the current layer
+                                      //!< stack contains skip layers.
 
-  uint64_t video_present : 1;     //!< This flag will be set to true, if current layer stack
-                                  //!< contains video.
+      uint32_t video_present : 1;     //!< This flag will be set to true, if current layer stack
+                                      //!< contains video.
 
-  uint64_t secure_present : 1;    //!< This flag will be set to true, if the current layer stack
-                                  //!< contains secure layers.
+      uint32_t secure_present : 1;    //!< This flag will be set to true, if the current layer
+                                      //!< stack contains secure layers.
 
-  uint64_t animating : 1;         //!< This flag shall be set by client to indicate that the current
-                                  //!< frame is animating.
+      uint32_t animating : 1;         //!< This flag shall be set by client to indicate that the
+                                      //!<  current frame is animating.
+      };
 
-  LayerStackFlags()
-    : geometry_changed(0), skip_present(0), video_present(0), secure_present(0), animating(0) { }
+      uint32_t flags;   //!< For initialization purpose only. Client shall not refer it directly.
+  };
+
+  LayerStackFlags() : flags(0) { }
 };
 
 /*! @brief This structure defines a rectanglular area inside a display layer.
diff --git a/displayengine/include/private/hw_info_types.h b/displayengine/include/private/hw_info_types.h
index 49abafe..1740615 100644
--- a/displayengine/include/private/hw_info_types.h
+++ b/displayengine/include/private/hw_info_types.h
@@ -65,6 +65,7 @@
   uint64_t max_bandwidth_low;
   uint64_t max_bandwidth_high;
   uint32_t max_mixer_width;
+  uint32_t max_pipe_width;
   uint32_t max_pipe_bw;
   uint32_t max_sde_clk;
   float clk_fudge_factor;
@@ -81,8 +82,8 @@
       num_cursor_pipe(0), num_blending_stages(0), num_rotator(0), num_control(0),
       num_mixer_to_disp(0), smp_total(0), smp_size(0), num_smp_per_pipe(0), max_scale_up(1),
       max_scale_down(1), max_bandwidth_low(0), max_bandwidth_high(0), max_mixer_width(2048),
-      max_pipe_bw(0), max_sde_clk(0), clk_fudge_factor(1.0f), has_bwc(false), has_ubwc(false),
-      has_decimation(false), has_macrotile(false), has_rotator_downscale(false),
+      max_pipe_width(2048), max_pipe_bw(0), max_sde_clk(0), clk_fudge_factor(1.0f), has_bwc(false),
+      has_ubwc(false), has_decimation(false), has_macrotile(false), has_rotator_downscale(false),
       has_non_scalar_rgb(false), is_src_split(false) { }
 
   void Reset() { *this = HWResourceInfo(); }
diff --git a/displayengine/libs/core/display_base.cpp b/displayengine/libs/core/display_base.cpp
index 8725a7b..47beac0 100644
--- a/displayengine/libs/core/display_base.cpp
+++ b/displayengine/libs/core/display_base.cpp
@@ -22,6 +22,7 @@
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
+#include <stdio.h>
 #include <utils/constants.h>
 #include <utils/debug.h>
 
@@ -146,6 +147,11 @@
           continue;
         }
         error = rotator_ctrl_->Prepare(display_rotator_ctx_, &hw_layers_);
+      } else {
+        // Release all the previous rotator sessions.
+        if (rotator_ctrl_) {
+          error = rotator_ctrl_->Purge(display_rotator_ctx_, &hw_layers_);
+        }
       }
 
       if (error == kErrorNone) {
@@ -409,9 +415,11 @@
                          num_modes_, active_mode_index_);
 
   DisplayConfigVariableInfo &info = display_attributes_[active_mode_index_];
-  DumpImpl::AppendString(buffer, length, "\nres:%ux%u, dpi:%.2fx%.2f, fps:%.2f, vsync period: %u",
-                         info.x_pixels, info.y_pixels, info.x_dpi, info.y_dpi, info.fps,
-                         info.vsync_period_ns);
+  DumpImpl::AppendString(buffer, length, "\nres:%u x %u, dpi:%.2f x %.2f, fps:%.2f,"
+                         "vsync period: %u", info.x_pixels, info.y_pixels, info.x_dpi,
+                         info.y_dpi, info.fps, info.vsync_period_ns);
+
+  DumpImpl::AppendString(buffer, length, "\n");
 
   uint32_t num_layers = 0;
   uint32_t num_hw_layers = 0;
@@ -420,64 +428,101 @@
     num_hw_layers = hw_layers_.info.count;
   }
 
-  DumpImpl::AppendString(buffer, length, "\n\nnum actual layers: %u, num sde layers: %u",
-                         num_layers, num_hw_layers);
+  if (num_hw_layers == 0) {
+    DumpImpl::AppendString(buffer, length, "\nNo hardware layers programmed");
+    return;
+  }
+
+  HWLayersInfo &layer_info = hw_layers_.info;
+  LayerRect &l_roi = layer_info.left_partial_update;
+  LayerRect &r_roi = layer_info.right_partial_update;
+  DumpImpl::AppendString(buffer, length, "\nROI(L T R B) : LEFT(%d %d %d %d), RIGHT(%d %d %d %d)",
+                         INT(l_roi.left), INT(l_roi.top), INT(l_roi.right), INT(l_roi.bottom),
+                         INT(r_roi.left), INT(r_roi.top), INT(r_roi.right), INT(r_roi.bottom));
+
+  const char *header  = "\n| Idx |  Comp Type  |  Split | WB |  Pipe |    W x H    |       Format       |  Src Rect (L T R B) |  Dst Rect (L T R B) |  Z |    Flags   | Deci(HxV) |";  //NOLINT
+  const char *newline = "\n|-----|-------------|--------|----|-------|-------------|--------------------|---------------------|---------------------|----|------------|-----------|";  //NOLINT
+  const char *format  = "\n| %3s | %11s "     "| %6s " "| %2s | 0x%03x | %4d x %4d | %18s "            "| %4d %4d %4d %4d "  "| %4d %4d %4d %4d "  "| %2s | %10s "   "| %9s |";  //NOLINT
+
+  DumpImpl::AppendString(buffer, length, "\n");
+  DumpImpl::AppendString(buffer, length, newline);
+  DumpImpl::AppendString(buffer, length, header);
+  DumpImpl::AppendString(buffer, length, newline);
 
   for (uint32_t i = 0; i < num_hw_layers; i++) {
-    Layer &layer = hw_layers_.info.stack->layers[hw_layers_.info.index[i]];
+    uint32_t layer_index = hw_layers_.info.index[i];
+    Layer &layer = hw_layers_.info.stack->layers[layer_index];
     LayerBuffer *input_buffer = layer.input_buffer;
     HWLayerConfig &layer_config = hw_layers_.config[i];
-
-    HWPipeInfo &left_pipe = hw_layers_.config[i].left_pipe;
-    HWPipeInfo &right_pipe = hw_layers_.config[i].right_pipe;
-
     HWRotatorSession &hw_rotator_session = layer_config.hw_rotator_session;
-    HWRotateInfo &left_rotate = hw_rotator_session.hw_rotate_info[0];
-    HWRotateInfo &right_rotate = hw_rotator_session.hw_rotate_info[1];
 
-    DumpImpl::AppendString(buffer, length, "\n\nsde idx: %u, actual idx: %u", i,
-                           hw_layers_.info.index[i]);
-    DumpImpl::AppendString(buffer, length, "\nw: %u, h: %u, fmt: %u",
-                           input_buffer->width, input_buffer->height, input_buffer->format);
-    AppendRect(buffer, length, "\nsrc_rect:", &layer.src_rect);
-    AppendRect(buffer, length, "\ndst_rect:", &layer.dst_rect);
+    char idx[8] = { 0 };
+    const char *comp_type = GetName(layer.composition);
+    const char *buffer_format = GetName(input_buffer->format);
+    const char *rotate_split[2] = { "Rot-L", "Rot-R" };
+    const char *comp_split[2] = { "Comp-L", "Comp-R" };
 
-    if (left_rotate.valid) {
-      DumpImpl::AppendString(buffer, length, "\n\tleft rotate =>");
-      DumpImpl::AppendString(buffer, length, "\n\t  pipe id: 0x%x", left_rotate.pipe_id);
-      AppendRect(buffer, length, "\n\t  src_roi:", &left_rotate.src_roi);
-      AppendRect(buffer, length, "\n\t  dst_roi:", &left_rotate.dst_roi);
+    snprintf(idx, sizeof(idx), "%d", layer_index);
+
+    for (uint32_t count = 0; count < hw_rotator_session.hw_block_count; count++) {
+      char writeback_id[8];
+      HWRotateInfo &rotate = hw_rotator_session.hw_rotate_info[count];
+      LayerRect &src_roi = rotate.src_roi;
+      LayerRect &dst_roi = rotate.dst_roi;
+
+      snprintf(writeback_id, sizeof(writeback_id), "%d", rotate.writeback_id);
+
+      DumpImpl::AppendString(buffer, length, format, idx, comp_type, rotate_split[count],
+                             writeback_id, rotate.pipe_id, input_buffer->width,
+                             input_buffer->height, buffer_format, INT(src_roi.left),
+                             INT(src_roi.top), INT(src_roi.right), INT(src_roi.bottom),
+                             INT(dst_roi.left), INT(dst_roi.top), INT(dst_roi.right),
+                             INT(dst_roi.bottom), "-", "-    ", "-    ");
+
+      // print the below only once per layer block, fill with spaces for rest.
+      idx[0] = 0;
+      comp_type = "";
     }
 
-    if (right_rotate.valid) {
-      DumpImpl::AppendString(buffer, length, "\n\tright rotate =>");
-      DumpImpl::AppendString(buffer, length, "\n\t  pipe id: 0x%x", right_rotate.pipe_id);
-      AppendRect(buffer, length, "\n\t  src_roi:", &right_rotate.src_roi);
-      AppendRect(buffer, length, "\n\t  dst_roi:", &right_rotate.dst_roi);
+    if (hw_rotator_session.hw_block_count > 0) {
+      input_buffer = &hw_rotator_session.output_buffer;
+      buffer_format = GetName(input_buffer->format);
     }
 
-    if (left_pipe.valid) {
-      DumpImpl::AppendString(buffer, length, "\n\tleft pipe =>");
-      DumpImpl::AppendString(buffer, length, "\n\t  pipe id: 0x%x", left_pipe.pipe_id);
-      AppendRect(buffer, length, "\n\t  src_roi:", &left_pipe.src_roi);
-      AppendRect(buffer, length, "\n\t  dst_roi:", &left_pipe.dst_roi);
+    for (uint32_t count = 0; count < 2; count++) {
+      char decimation[16];
+      char flags[16];
+      char z_order[8];
+      HWPipeInfo &pipe = (count == 0) ? layer_config.left_pipe : layer_config.right_pipe;
+
+      if (!pipe.valid) {
+        continue;
+      }
+
+      LayerRect &src_roi = pipe.src_roi;
+      LayerRect &dst_roi = pipe.dst_roi;
+
+      snprintf(z_order, sizeof(z_order), "%d", pipe.z_order);
+      snprintf(flags, sizeof(flags), "0x%08x", layer.flags.flags);
+      snprintf(decimation, sizeof(decimation), "%3d x %3d", pipe.horizontal_decimation,
+               pipe.vertical_decimation);
+
+      DumpImpl::AppendString(buffer, length, format, idx, comp_type, comp_split[count],
+                             "-", pipe.pipe_id, input_buffer->width, input_buffer->height,
+                             buffer_format, INT(src_roi.left), INT(src_roi.top),
+                             INT(src_roi.right), INT(src_roi.bottom), INT(dst_roi.left),
+                             INT(dst_roi.top), INT(dst_roi.right), INT(dst_roi.bottom),
+                             z_order, flags, decimation);
+
+      // print the below only once per layer block, fill with spaces for rest.
+      idx[0] = 0;
+      comp_type = "";
     }
 
-    if (right_pipe.valid) {
-      DumpImpl::AppendString(buffer, length, "\n\tright pipe =>");
-      DumpImpl::AppendString(buffer, length, "\n\t  pipe id: 0x%x", right_pipe.pipe_id);
-      AppendRect(buffer, length, "\n\t  src_roi:", &right_pipe.src_roi);
-      AppendRect(buffer, length, "\n\t  dst_roi:", &right_pipe.dst_roi);
-    }
+    DumpImpl::AppendString(buffer, length, newline);
   }
 }
 
-void DisplayBase::AppendRect(char *buffer, uint32_t length, const char *rect_name,
-                             LayerRect *rect) {
-  DumpImpl::AppendString(buffer, length, "%s %.1f, %.1f, %.1f, %.1f",
-                         rect_name, rect->left, rect->top, rect->right, rect->bottom);
-}
-
 int DisplayBase::GetBestConfig() {
   return (num_modes_ == 1) ? 0 : -1;
 }
@@ -497,5 +542,44 @@
   return false;
 }
 
-}  // namespace sde
+const char * DisplayBase::GetName(const LayerComposition &composition) {
+  switch (composition) {
+  case kCompositionGPU:         return "GPU";
+  case kCompositionSDE:         return "SDE";
+  case kCompositionGPUTarget:   return "GPU_TARGET";
+  default:                      return "UNKNOWN";
+  }
+}
 
+const char * DisplayBase::GetName(const LayerBufferFormat &format) {
+  switch (format) {
+  case kFormatARGB8888:                 return "ARGB_8888";
+  case kFormatRGBA8888:                 return "RGBA_8888";
+  case kFormatBGRA8888:                 return "BGRA_8888";
+  case kFormatXRGB8888:                 return "XRGB_8888";
+  case kFormatRGBX8888:                 return "RGBX_8888";
+  case kFormatBGRX8888:                 return "BGRX_8888";
+  case kFormatRGBA5551:                 return "RGBA_5551";
+  case kFormatRGBA4444:                 return "RGBA_4444";
+  case kFormatRGB888:                   return "RGB_888";
+  case kFormatBGR888:                   return "BGR_888";
+  case kFormatRGB565:                   return "RGB_565";
+  case kFormatRGBA8888Ubwc:             return "RGBA_8888_UBWC";
+  case kFormatRGBX8888Ubwc:             return "RGBX_8888_UBWC";
+  case kFormatRGB565Ubwc:               return "RGB_565_UBWC";
+  case kFormatYCbCr420Planar:           return "Y_CB_CR_420";
+  case kFormatYCrCb420Planar:           return "Y_CR_CB_420";
+  case kFormatYCbCr420SemiPlanar:       return "Y_CBCR_420";
+  case kFormatYCrCb420SemiPlanar:       return "Y_CRCB_420";
+  case kFormatYCbCr420SemiPlanarVenus:  return "Y_CBCR_420_VENUS";
+  case kFormatYCbCr422H1V2SemiPlanar:   return "Y_CBCR_422_H1V2";
+  case kFormatYCrCb422H1V2SemiPlanar:   return "Y_CRCB_422_H1V2";
+  case kFormatYCbCr422H2V1SemiPlanar:   return "Y_CBCR_422_H2V1";
+  case kFormatYCrCb422H2V1SemiPlanar:   return "Y_CRCB_422_H2V2";
+  case kFormatYCbCr420SPVenusUbwc:      return "Y_CBCR_420_VENUS_UBWC";
+  case kFormatYCbCr422H2V1Packed:       return "YCBYCR_422_H2V1";
+  default:                              return "UNKNOWN";
+  }
+}
+
+}  // namespace sde
diff --git a/displayengine/libs/core/display_base.h b/displayengine/libs/core/display_base.h
index 1edef9e..0a33011 100644
--- a/displayengine/libs/core/display_base.h
+++ b/displayengine/libs/core/display_base.h
@@ -60,15 +60,14 @@
   virtual DisplayError SetMaxMixerStages(uint32_t max_mixer_stages);
   virtual DisplayError SetDisplayMode(uint32_t mode);
 
- private:
-  bool IsRotationRequired(HWLayers *hw_layers);
-
  protected:
   // DumpImpl method
   void AppendDump(char *buffer, uint32_t length);
-  void AppendRect(char *buffer, uint32_t length, const char *rect_name, LayerRect *rect);
 
   virtual int GetBestConfig();
+  bool IsRotationRequired(HWLayers *hw_layers);
+  const char * GetName(const LayerComposition &composition);
+  const char * GetName(const LayerBufferFormat &format);
 
   DisplayType display_type_;
   DisplayEventHandler *event_handler_;
diff --git a/displayengine/libs/core/display_hdmi.h b/displayengine/libs/core/display_hdmi.h
index 1a96884..ea1b80c 100644
--- a/displayengine/libs/core/display_hdmi.h
+++ b/displayengine/libs/core/display_hdmi.h
@@ -26,6 +26,7 @@
 #define __DISPLAY_HDMI_H__
 
 #include "display_base.h"
+#include "dump_impl.h"
 
 namespace sde {
 
diff --git a/displayengine/libs/core/display_primary.cpp b/displayengine/libs/core/display_primary.cpp
index d6116fa..0fa5d2b 100644
--- a/displayengine/libs/core/display_primary.cpp
+++ b/displayengine/libs/core/display_primary.cpp
@@ -186,7 +186,7 @@
     return kErrorNotSupported;
   }
 
-  switch(mode) {
+  switch (mode) {
   case kModeVideo:
     hw_display_mode = kModeVideo;
     break;
diff --git a/displayengine/libs/core/display_primary.h b/displayengine/libs/core/display_primary.h
index be422de..1ed28b2 100644
--- a/displayengine/libs/core/display_primary.h
+++ b/displayengine/libs/core/display_primary.h
@@ -26,6 +26,7 @@
 #define __DISPLAY_PRIMARY_H__
 
 #include "display_base.h"
+#include "dump_impl.h"
 
 namespace sde {
 
diff --git a/displayengine/libs/core/display_virtual.h b/displayengine/libs/core/display_virtual.h
index 8e7a764..f868612 100644
--- a/displayengine/libs/core/display_virtual.h
+++ b/displayengine/libs/core/display_virtual.h
@@ -26,6 +26,7 @@
 #define __DISPLAY_VIRTUAL_H__
 
 #include "display_base.h"
+#include "dump_impl.h"
 
 namespace sde {
 
diff --git a/displayengine/libs/core/dump_impl.cpp b/displayengine/libs/core/dump_impl.cpp
index a5aca81..f9219f3 100755
--- a/displayengine/libs/core/dump_impl.cpp
+++ b/displayengine/libs/core/dump_impl.cpp
@@ -44,7 +44,7 @@
   for (uint32_t i = 0; i < DumpImpl::dump_count_; i++) {
     DumpImpl::dump_list_[i]->AppendDump(buffer, length);
   }
-  DumpImpl::AppendString(buffer, length, "\n-------------------------------------------\n");
+  DumpImpl::AppendString(buffer, length, "\n\n");
 
   return kErrorNone;
 }
diff --git a/displayengine/libs/core/fb/hw_device.cpp b/displayengine/libs/core/fb/hw_device.cpp
index 70d98de..d96820f 100644
--- a/displayengine/libs/core/fb/hw_device.cpp
+++ b/displayengine/libs/core/fb/hw_device.cpp
@@ -40,7 +40,6 @@
 #include <utils/debug.h>
 
 #include "hw_device.h"
-#include "scalar_helper.h"
 
 #define __CLASS__ "HWDevice"
 
@@ -249,17 +248,15 @@
         SetRect(pipe_info->dst_roi, &mdp_layer.dst_rect);
         SetMDPFlags(layer, is_rotator_used, &mdp_layer.flags);
 
-        mdp_scale_data* mdp_scale = GetScaleDataRef(mdp_layer_count);
-#ifdef USES_SCALAR
-        // Set the configured scale data for MDP driver
-        ScalarHelper::GetInstance()->SetScaleData(i, !count, mdp_scale);
-        if (mdp_scale->enable_pxl_ext) {
-          if ((mdp_layer.flags & MDP_LAYER_DEINTERLACE) && (layer.transform.rotation == 90.0f))
-            ScalarHelper::GetInstance()->UpdateSrcWidth(i, !count, &mdp_buffer.width);
+        if (pipe_info->scale_data.enable_pixel_ext) {
+          if ((mdp_layer.flags & MDP_LAYER_DEINTERLACE) && (layer.transform.rotation == 90.0f)) {
+            mdp_buffer.width = pipe_info->scale_data.src_width;
+          }
+          SetHWScaleData(pipe_info->scale_data, mdp_layer_count);
         }
-#endif
-        mdp_layer.scale = mdp_scale;
 
+        // Send scale data to MDP driver
+        mdp_layer.scale = GetScaleDataRef(mdp_layer_count);
         mdp_layer_count++;
 
         DLOGV_IF(kTagDriverConfig, "******************* Layer[%d] %s pipe Input ******************",
@@ -274,7 +271,7 @@
                  mdp_layer.src_rect.y, mdp_layer.src_rect.w, mdp_layer.src_rect.h);
         DLOGV_IF(kTagDriverConfig, "dst_rect [%d, %d, %d, %d]", mdp_layer.dst_rect.x,
                  mdp_layer.dst_rect.y, mdp_layer.dst_rect.w, mdp_layer.dst_rect.h);
-        for (int j = 0; j < MAX_PLANES; j++) {
+        for (int j = 0; j < 4; j++) {
           DLOGV_IF(kTagDriverConfig, "Scale Data[%d]: Phase=[%x %x %x %x] Pixel_Ext=[%d %d %d %d]",
                  j, mdp_layer.scale->init_phase_x[j], mdp_layer.scale->phase_step_x[j],
                  mdp_layer.scale->init_phase_y[j], mdp_layer.scale->phase_step_y[j],
@@ -318,9 +315,9 @@
   return kErrorNone;
 }
 
-void HWDevice::DumpLayerCommit(mdp_layer_commit &layer_commit) {
-  mdp_layer_commit_v1 &mdp_commit = layer_commit.commit_v1;
-  mdp_input_layer *mdp_layers = mdp_commit.input_layers;
+void HWDevice::DumpLayerCommit(const mdp_layer_commit &layer_commit) {
+  const mdp_layer_commit_v1 &mdp_commit = layer_commit.commit_v1;
+  const mdp_input_layer *mdp_layers = mdp_commit.input_layers;
 
   DLOGE("mdp_commit: flags = %x, release fence = %x", mdp_commit.flags, mdp_commit.release_fence);
   DLOGE("left_roi: x = %d, y = %d, w = %d, h = %d", mdp_commit.left_roi.x, mdp_commit.left_roi.y,
@@ -330,10 +327,10 @@
   for (uint32_t i = 0; i < mdp_commit.input_layer_cnt; i++) {
     DLOGE("mdp_commit: layer_cnt = %d, pipe_ndx = %x, zorder = %d, flags = %x",
           i, mdp_layers[i].pipe_ndx, mdp_layers[i].z_order, mdp_layers[i].flags);
-    mdp_rect &src_rect = mdp_layers[i].src_rect;
+    const mdp_rect &src_rect = mdp_layers[i].src_rect;
     DLOGE("src rect: x = %d, y = %d, w = %d, h = %d",
           src_rect.x, src_rect.y, src_rect.w, src_rect.h);
-    mdp_rect &dst_rect = mdp_layers[i].dst_rect;
+    const mdp_rect &dst_rect = mdp_layers[i].dst_rect;
     DLOGE("dst rect: x = %d, y = %d, w = %d, h = %d",
           dst_rect.x, dst_rect.y, dst_rect.w, dst_rect.h);
   }
@@ -907,5 +904,36 @@
   mdp_disp_commit_.commit_v1.retire_fence = -1;
 }
 
+void HWDevice::SetHWScaleData(const ScaleData &scale, uint32_t index) {
+  mdp_scale_data *mdp_scale = GetScaleDataRef(index);
+  mdp_scale->enable_pxl_ext = scale.enable_pixel_ext;
+
+  for (int i = 0; i < 4; i++) {
+    const HWPlane &plane = scale.plane[i];
+    mdp_scale->init_phase_x[i] = plane.init_phase_x;
+    mdp_scale->phase_step_x[i] = plane.phase_step_x;
+    mdp_scale->init_phase_y[i] = plane.init_phase_y;
+    mdp_scale->phase_step_y[i] = plane.phase_step_y;
+
+    mdp_scale->num_ext_pxls_left[i] = plane.left.extension;
+    mdp_scale->left_ftch[i] = plane.left.overfetch;
+    mdp_scale->left_rpt[i] = plane.left.repeat;
+
+    mdp_scale->num_ext_pxls_top[i] = plane.top.extension;
+    mdp_scale->top_ftch[i] = plane.top.overfetch;
+    mdp_scale->top_rpt[i] = plane.top.repeat;
+
+    mdp_scale->num_ext_pxls_right[i] = plane.right.extension;
+    mdp_scale->right_ftch[i] = plane.right.overfetch;
+    mdp_scale->right_rpt[i] = plane.right.repeat;
+
+    mdp_scale->num_ext_pxls_btm[i] = plane.bottom.extension;
+    mdp_scale->btm_ftch[i] = plane.bottom.overfetch;
+    mdp_scale->btm_rpt[i] = plane.bottom.repeat;
+
+    mdp_scale->roi_w[i] = plane.roi_width;
+  }
+}
+
 }  // namespace sde
 
diff --git a/displayengine/libs/core/fb/hw_device.h b/displayengine/libs/core/fb/hw_device.h
index 917c884..18c6652 100644
--- a/displayengine/libs/core/fb/hw_device.h
+++ b/displayengine/libs/core/fb/hw_device.h
@@ -72,7 +72,7 @@
   static const int kNumPhysicalDisplays = 2;
   static const int kNumDisplayEvents = 4;
 
-  void DumpLayerCommit(mdp_layer_commit &layer_commit);
+  void DumpLayerCommit(const mdp_layer_commit &layer_commit);
   DisplayError SetFormat(const LayerBufferFormat &source, uint32_t *target);
   DisplayError SetStride(HWDeviceType device_type, LayerBufferFormat format,
                          uint32_t width, uint32_t *target);
@@ -91,6 +91,7 @@
   void GetSplitInfo(int device_node, HWPanelInfo *panel_info);
   int ParseLine(char *input, char *tokens[], const uint32_t max_token, uint32_t *count);
   mdp_scale_data* GetScaleDataRef(uint32_t index) { return &scale_data_[index]; }
+  void SetHWScaleData(const ScaleData &scale, uint32_t index);
   void ResetDisplayParams();
 
   bool EnableHotPlugDetection(int enable);
diff --git a/displayengine/libs/core/fb/hw_info.cpp b/displayengine/libs/core/fb/hw_info.cpp
index cddb590..7833c3c 100644
--- a/displayengine/libs/core/fb/hw_info.cpp
+++ b/displayengine/libs/core/fb/hw_info.cpp
@@ -123,6 +123,8 @@
         hw_resource->max_bandwidth_high = atol(tokens[1]);
       } else if (!strncmp(tokens[0], "max_mixer_width", strlen("max_mixer_width"))) {
         hw_resource->max_mixer_width = atoi(tokens[1]);
+      } else if (!strncmp(tokens[0], "max_pipe_width", strlen("max_pipe_width"))) {
+        hw_resource->max_pipe_width = atoi(tokens[1]);
       } else if (!strncmp(tokens[0], "max_pipe_bw", strlen("max_pipe_bw"))) {
         hw_resource->max_pipe_bw = atoi(tokens[1]);
       } else if (!strncmp(tokens[0], "max_mdp_clk", strlen("max_mdp_clk"))) {
diff --git a/displayengine/libs/core/hw_interface.h b/displayengine/libs/core/hw_interface.h
index 36cb85e..5610ccd 100644
--- a/displayengine/libs/core/hw_interface.h
+++ b/displayengine/libs/core/hw_interface.h
@@ -102,12 +102,45 @@
   HWRotatorSession() : hw_block_count(0), downscale_ratio(1.0f), session_id(-1) { }
 };
 
+struct HWPixelExtension {
+  // Number of pixels extension in left, right, top and bottom directions for all color components.
+  // This pixel value for each color component should be sum of fetch and repeat pixels.
+  int extension;
+
+  // Number of pixels need to be overfetched in left, right, top and bottom directions from source
+  // image for scaling.
+  int overfetch;
+
+  // Number of pixels need to be repeated in left, right, top and bottom directions for scaling.
+  int repeat;
+};
+
+struct HWPlane {
+  int init_phase_x;
+  int phase_step_x;
+  int init_phase_y;
+  int phase_step_y;
+  HWPixelExtension left;
+  HWPixelExtension top;
+  HWPixelExtension right;
+  HWPixelExtension bottom;
+  uint32_t roi_width;
+};
+
+struct ScaleData {
+  uint8_t enable_pixel_ext;
+  uint32_t src_width;
+  uint32_t src_height;
+  HWPlane plane[4];
+};
+
 struct HWPipeInfo {
   uint32_t pipe_id;
   LayerRect src_roi;
   LayerRect dst_roi;
   uint8_t horizontal_decimation;
   uint8_t vertical_decimation;
+  ScaleData scale_data;
   bool valid;
   uint32_t z_order;
 
diff --git a/displayengine/libs/core/res_config.cpp b/displayengine/libs/core/res_config.cpp
index 29a92cf..c5a8a06 100644
--- a/displayengine/libs/core/res_config.cpp
+++ b/displayengine/libs/core/res_config.cpp
@@ -122,7 +122,7 @@
   // For perf/power optimization, even if "always_src_split" is enabled, use 2 pipes only if:
   // 1. Source width is greater than split_left (left_mixer_width)
   // 2. Pipe clock exceeds the mixer clock
-  if ((src_width > kMaxSourcePipeWidth) || (dst_width > kMaxSourcePipeWidth) ||
+  if ((src_width > hw_res_info_.max_pipe_width) || (dst_width > hw_res_info_.max_pipe_width) ||
       (display_resource_ctx->display_attributes.always_src_split &&
       ((src_width > left_mixer_width) || (pipe_clock > mixer_clock)))) {
     SplitRect(transform.flip_horizontal, src_rect, dst_rect, &left_pipe->src_roi,
@@ -169,7 +169,7 @@
     crop_right_valid = CalculateCropRects(scissor, transform, &crop_right, &dst_right);
   }
 
-  if (crop_left_valid && (crop_left.right - crop_left.left) > kMaxSourcePipeWidth) {
+  if (crop_left_valid && (crop_left.right - crop_left.left) > hw_res_info_.max_pipe_width) {
     if (crop_right_valid) {
       DLOGV_IF(kTagResources, "Need more than 2 pipes: left width = %.0f, right width = %.0f",
                crop_left.right - crop_left.left, crop_right.right - crop_right.left);
@@ -181,7 +181,8 @@
     left_pipe->valid = true;
     right_pipe->valid = true;
     crop_right_valid = true;
-  } else if (crop_right_valid && (crop_right.right - crop_right.left) > kMaxSourcePipeWidth) {
+  } else if (crop_right_valid &&
+             (crop_right.right - crop_right.left) > hw_res_info_.max_pipe_width) {
     if (crop_left_valid) {
       DLOGV_IF(kTagResources, "Need more than 2 pipes: left width = %.0f, right width = %.0f",
                crop_left.right - crop_left.left, crop_right.right - crop_right.left);
@@ -234,12 +235,11 @@
 
   for (uint32_t i = 0; i < layer_info.count; i++) {
     Layer& layer = layer_info.stack->layers[layer_info.index[i]];
-    float rot_scale = 1.0f;
-    if (!IsValidDimension(layer)) {
-      DLOGV_IF(kTagResources, "Input is invalid");
-      Log(kTagResources, "input layer src_rect", layer.src_rect);
-      Log(kTagResources, "input layer dst_rect", layer.dst_rect);
-      return kErrorNotSupported;
+    float rotator_scale_factor = 1.0f;
+
+    error = ValidateLayerDimensions(layer);
+    if (error != kErrorNone) {
+      return error;
     }
 
     LayerRect scissor, src_rect, dst_rect;
@@ -253,7 +253,7 @@
     HWPipeInfo &right_pipe = layer_config->right_pipe;
     HWRotatorSession *hw_rotator_session = &layer_config->hw_rotator_session;
     LayerTransform transform = layer.transform;
-    bool rot90 = IsRotationNeeded(transform.rotation);
+    bool rotated90 = IsRotationNeeded(transform.rotation);
 
     if (!CalculateCropRects(scissor, layer.transform, &src_rect, &dst_rect)) {
       layer_config->Reset();
@@ -268,8 +268,19 @@
       Normalize(align_x, align_y, &src_rect);
     }
 
-    if (ValidateScaling(layer, src_rect, dst_rect, &rot_scale)) {
-      return kErrorNotSupported;
+    error = ValidateDimensions(src_rect, dst_rect, rotated90);
+    if (error != kErrorNone) {
+      return error;
+    }
+
+    error = ValidateScaling(src_rect, dst_rect, rotated90);
+    if (error != kErrorNone) {
+      return error;
+    }
+
+    error = GetRotatorScaleFactor(src_rect, dst_rect, rotated90, &rotator_scale_factor);
+    if (error != kErrorNone) {
+      return error;
     }
 
     // config rotator first
@@ -278,8 +289,8 @@
     }
     hw_rotator_session->hw_block_count = 0;
 
-    if (rot90 || UINT32(rot_scale) != 1) {
-      RotationConfig(layer, rot_scale, &src_rect, layer_config, rotate_count);
+    if (rotated90 || UINT32(rotator_scale_factor) != 1) {
+      RotationConfig(layer, rotator_scale_factor, &src_rect, layer_config, rotate_count);
       // rotator will take care of flipping, reset tranform
       transform = LayerTransform();
     }
@@ -306,7 +317,7 @@
     Log(kTagResources, "input layer src_rect", layer.src_rect);
     Log(kTagResources, "input layer dst_rect", layer.dst_rect);
     for (uint32_t k = 0; k < hw_rotator_session->hw_block_count; k++) {
-      DLOGV_IF(kTagResources, "rotate num = %d, scale_x = %.2f", k, rot_scale);
+      DLOGV_IF(kTagResources, "rotate num = %d, scale_x = %.2f", k, rotator_scale_factor);
       Log(kTagResources, "rotate src", hw_rotator_session->hw_rotate_info[k].src_roi);
       Log(kTagResources, "rotate dst", hw_rotator_session->hw_rotate_info[k].dst_roi);
     }
@@ -343,91 +354,6 @@
   return error;
 }
 
-DisplayError ResManager::ValidateScaling(const Layer &layer, const LayerRect &crop,
-                                         const LayerRect &dst, float *rot_scale) {
-  bool rotated90 = IsRotationNeeded(layer.transform.rotation) && (rot_scale != NULL);
-  float crop_width = rotated90 ? crop.bottom - crop.top : crop.right - crop.left;
-  float crop_height = rotated90 ? crop.right - crop.left : crop.bottom - crop.top;
-  float dst_width = dst.right - dst.left;
-  float dst_height = dst.bottom - dst.top;
-
-  if ((dst_width < 1.0f) || (dst_height < 1.0f)) {
-    DLOGV_IF(kTagResources, "dst ROI is too small w = %.0f, h = %.0f, right = %.0f, bottom = %.0f",
-             dst_width, dst_height, dst.right, dst.bottom);
-    return kErrorNotSupported;
-  }
-
-  if ((crop_width < 1.0f) || (crop_height < 1.0f)) {
-    DLOGV_IF(kTagResources, "src ROI is too small w = %.0f, h = %.0f, right = %.0f, bottom = %.0f",
-             crop_width, crop_height, crop.right, crop.bottom);
-    return kErrorNotSupported;
-  }
-
-  if ((UINT32(crop_width - dst_width) == 1) || (UINT32(crop_height - dst_height) == 1)) {
-    DLOGV_IF(kTagResources, "One pixel downscaling detected crop_w = %.0f, dst_w = %.0f, " \
-             "crop_h = %.0f, dst_h = %.0f", crop_width, dst_width, crop_height, dst_height);
-    return kErrorNotSupported;
-  }
-
-  float scale_x = crop_width / dst_width;
-  float scale_y = crop_height / dst_height;
-  uint32_t rot_scale_local = 1;
-
-  if ((UINT32(scale_x) > 1) || (UINT32(scale_y) > 1)) {
-    float max_scale_down = FLOAT(hw_res_info_.max_scale_down);
-
-    if (hw_res_info_.has_rotator_downscale && !property_setting_.disable_rotator_downscaling &&
-        rot_scale && !IsMacroTileFormat(layer.input_buffer)) {
-      float scale_min = MIN(scale_x, scale_y);
-      float scale_max = MAX(scale_x, scale_y);
-      // use rotator to downscale when over the pipe scaling ability
-      if (UINT32(scale_min) >= 2 && scale_max > max_scale_down) {
-        // downscaling ratio needs be the same for both direction, use the smaller one.
-        rot_scale_local = 1 << UINT32(ceilf(log2f(scale_min / max_scale_down)));
-        if (rot_scale_local > kMaxRotateDownScaleRatio)
-          rot_scale_local = kMaxRotateDownScaleRatio;
-        scale_x /= FLOAT(rot_scale_local);
-        scale_y /= FLOAT(rot_scale_local);
-      }
-      *rot_scale = FLOAT(rot_scale_local);
-    }
-
-    if (hw_res_info_.has_decimation && !property_setting_.disable_decimation &&
-               !IsMacroTileFormat(layer.input_buffer)) {
-      max_scale_down *= FLOAT(kMaxDecimationDownScaleRatio);
-    }
-
-    if (scale_x > max_scale_down || scale_y > max_scale_down) {
-      DLOGV_IF(kTagResources,
-               "Scaling down is over the limit: is_tile = %d, scale_x = %.0f, scale_y = %.0f, " \
-               "crop_w = %.0f, dst_w = %.0f, has_deci = %d, disable_deci = %d, rot_scale = %d",
-               IsMacroTileFormat(layer.input_buffer), scale_x, scale_y, crop_width, dst_width,
-               hw_res_info_.has_decimation, property_setting_.disable_decimation, rot_scale_local);
-      return kErrorNotSupported;
-    }
-  }
-
-  float max_scale_up = FLOAT(hw_res_info_.max_scale_up);
-  if (UINT32(scale_x) < 1 && scale_x > 0.0f) {
-    if ((1.0f / scale_x) > max_scale_up) {
-      DLOGV_IF(kTagResources, "Scaling up is over limit scale_x = %f", 1.0f / scale_x);
-      return kErrorNotSupported;
-    }
-  }
-
-  if (UINT32(scale_y) < 1 && scale_y > 0.0f) {
-    if ((1.0f / scale_y) > max_scale_up) {
-      DLOGV_IF(kTagResources, "Scaling up is over limit scale_y = %f", 1.0f / scale_y);
-      return kErrorNotSupported;
-    }
-  }
-
-  DLOGV_IF(kTagResources, "scale_x = %.4f, scale_y = %.4f, rot_scale = %d",
-           scale_x, scale_y, rot_scale_local);
-
-  return kErrorNone;
-}
-
 void ResManager::CalculateCut(const LayerTransform &transform, float *left_cut_ratio,
                               float *top_cut_ratio, float *right_cut_ratio,
                               float *bottom_cut_ratio) {
@@ -514,7 +440,7 @@
     return false;
 }
 
-bool ResManager::IsValidDimension(const Layer &layer) {
+DisplayError ResManager::ValidateLayerDimensions(const Layer &layer) {
   const LayerRect &src = layer.src_rect;
   const LayerRect &dst = layer.dst_rect;
   LayerBuffer *input_buffer = layer.input_buffer;
@@ -522,17 +448,231 @@
   if (!IsValid(src) || !IsValid(dst)) {
     Log(kTagResources, "input layer src_rect", src);
     Log(kTagResources, "input layer dst_rect", dst);
-    return false;
+    return kErrorNotSupported;
   }
 
   // Make sure source in integral only if it is a non secure layer.
   if (!input_buffer->flags.secure && (src.left - roundf(src.left) || src.top - roundf(src.top) ||
       src.right - roundf(src.right) || src.bottom - roundf(src.bottom))) {
     DLOGV_IF(kTagResources, "Input ROI is not integral");
-    return false;
+    return kErrorNotSupported;
   }
 
-  return true;
+  return kErrorNone;
+}
+
+DisplayError ResManager::ValidateDimensions(const LayerRect &crop, const LayerRect &dst,
+                                            bool rotated90) {
+  float crop_width = 0.0f, crop_height = 0.0f, dst_width = 0.0f, dst_height = 0.0f;
+
+  DisplayError error = GetCropAndDestination(crop, dst, rotated90, &crop_width, &crop_height,
+                                             &dst_width, &dst_height);
+  if (error != kErrorNone) {
+    return error;
+  }
+
+  if ((dst_width < 1.0f) || (dst_height < 1.0f)) {
+    DLOGV_IF(kTagResources, "dst ROI is too small w = %.0f, h = %.0f, right = %.0f, bottom = %.0f",
+             dst_width, dst_height, dst.right, dst.bottom);
+    return kErrorNotSupported;
+  }
+
+  if ((crop_width < 1.0f) || (crop_height < 1.0f)) {
+    DLOGV_IF(kTagResources, "src ROI is too small w = %.0f, h = %.0f, right = %.0f, bottom = %.0f",
+             crop_width, crop_height, crop.right, crop.bottom);
+    return kErrorNotSupported;
+  }
+
+  if ((UINT32(crop_width - dst_width) == 1) || (UINT32(crop_height - dst_height) == 1)) {
+    DLOGV_IF(kTagResources, "One pixel downscaling detected crop_w = %.0f, dst_w = %.0f, " \
+             "crop_h = %.0f, dst_h = %.0f", crop_width, dst_width, crop_height, dst_height);
+    return kErrorNotSupported;
+  }
+
+  return kErrorNone;
+}
+
+DisplayError ResManager::ValidatePipeParams(HWPipeInfo *pipe_info) {
+  DisplayError error = kErrorNone;
+
+  const LayerRect &src_rect = pipe_info->src_roi;
+  const LayerRect &dst_rect = pipe_info->dst_roi;
+
+  error = ValidateDimensions(src_rect, dst_rect, false /* rotated90 */);
+  if (error != kErrorNone) {
+    return error;
+  }
+
+  error = ValidateScaling(src_rect, dst_rect, false /* rotated90 */);
+  if (error != kErrorNone) {
+    return error;
+  }
+
+  return kErrorNone;
+}
+
+DisplayError ResManager::ValidateScaling(const LayerRect &crop, const LayerRect &dst,
+                                         bool rotated90) {
+  DisplayError error = kErrorNone;
+
+  float scale_x = 1.0f;
+  float scale_y = 1.0f;
+
+  error = GetScaleFactor(crop, dst, rotated90, &scale_x, &scale_y);
+  if (error != kErrorNone) {
+    return error;
+  }
+
+  error = ValidateDownScaling(scale_x, scale_y);
+  if (error != kErrorNone) {
+    return error;
+  }
+
+  error = ValidateUpScaling(scale_x, scale_y);
+  if (error != kErrorNone) {
+    return error;
+  }
+
+  return kErrorNone;
+}
+
+DisplayError ResManager::ValidateDownScaling(float scale_x, float scale_y) {
+  if ((UINT32(scale_x) > 1) || (UINT32(scale_y) > 1)) {
+    float max_scale_down = FLOAT(hw_res_info_.max_scale_down);
+    float rotator_scale_factor = 1.0f;
+
+    if (hw_res_info_.has_rotator_downscale && !property_setting_.disable_rotator_downscaling) {
+      rotator_scale_factor =  GetRotatorScaleFactor(scale_x, scale_y);
+      scale_x /= rotator_scale_factor;
+      scale_y /= rotator_scale_factor;
+
+      DLOGV_IF(kTagResources, "scale_x = %.4f, scale_y = %.4f, rotator_scale_factor = %d",
+               scale_x, scale_y, rotator_scale_factor);
+    }
+
+    if (hw_res_info_.has_decimation && !property_setting_.disable_decimation) {
+      max_scale_down *= FLOAT(kMaxDecimationDownScaleRatio);
+    }
+
+    if (scale_x > max_scale_down || scale_y > max_scale_down) {
+      DLOGV_IF(kTagResources,
+               "Scaling down is over the limit: scale_x = %.0f, scale_y = %.0f, " \
+               "has_deci = %d, disable_deci = %d, rotator_scale_factor= %.0f",
+               scale_x, scale_y, hw_res_info_.has_decimation, property_setting_.disable_decimation,
+               rotator_scale_factor);
+      return kErrorNotSupported;
+    }
+  }
+
+  DLOGV_IF(kTagResources, "scale_x = %.4f, scale_y = %.4f", scale_x, scale_y);
+
+  return kErrorNone;
+}
+
+DisplayError ResManager::ValidateUpScaling(float scale_x, float scale_y) {
+  float max_scale_up = FLOAT(hw_res_info_.max_scale_up);
+
+  if (UINT32(scale_x) < 1 && scale_x > 0.0f) {
+    if ((1.0f / scale_x) > max_scale_up) {
+      DLOGV_IF(kTagResources, "Scaling up is over limit scale_x = %f", 1.0f / scale_x);
+      return kErrorNotSupported;
+    }
+  }
+
+  if (UINT32(scale_y) < 1 && scale_y > 0.0f) {
+    if ((1.0f / scale_y) > max_scale_up) {
+      DLOGV_IF(kTagResources, "Scaling up is over limit scale_y = %f", 1.0f / scale_y);
+      return kErrorNotSupported;
+    }
+  }
+
+  DLOGV_IF(kTagResources, "scale_x = %.4f, scale_y = %.4f", scale_x, scale_y);
+
+  return kErrorNone;
+}
+
+DisplayError ResManager::GetCropAndDestination(const LayerRect &crop, const LayerRect &dst,
+                                               const bool rotated90, float *crop_width,
+                                               float *crop_height, float *dst_width,
+                                               float *dst_height) {
+  if (!IsValid(crop)) {
+    Log(kTagResources, "Invalid crop rect", crop);
+    return kErrorNotSupported;
+  }
+
+  if (!IsValid(dst)) {
+    Log(kTagResources, "Invalid dst rect", dst);
+    return kErrorNotSupported;
+  }
+
+  *crop_width = crop.right - crop.left;
+  *crop_height = crop.bottom - crop.top;
+  if (rotated90) {
+    Swap(*crop_width, *crop_height);
+  }
+
+  *dst_width = dst.right - dst.left;
+  *dst_height = dst.bottom - dst.top;
+
+  return kErrorNone;
+}
+
+DisplayError ResManager::GetRotatorScaleFactor(const LayerRect &crop, const LayerRect &dst,
+                                               bool rotated90, float *rotator_scale_factor) {
+  DisplayError error = kErrorNone;
+
+  float scale_x = 1.0f;
+  float scale_y = 1.0f;
+
+  if (hw_res_info_.has_rotator_downscale && !property_setting_.disable_rotator_downscaling) {
+    error = GetScaleFactor(crop, dst, rotated90, &scale_x, &scale_y);
+    if (error != kErrorNone) {
+      return error;
+    }
+
+    *rotator_scale_factor =  GetRotatorScaleFactor(scale_x, scale_y);
+  } else {
+    *rotator_scale_factor = 1.0f;
+  }
+
+  return kErrorNone;
+}
+
+float ResManager::GetRotatorScaleFactor(float scale_x, float scale_y) {
+  float max_scale_down = FLOAT(hw_res_info_.max_scale_down);
+  float scale_min = MIN(scale_x, scale_y);
+  float scale_max = MAX(scale_x, scale_y);
+  uint32_t rotator_scale_factor = 1;
+
+  // use rotator to downscale when over the pipe scaling ability
+  if (UINT32(scale_min) >= 2 && scale_max > max_scale_down) {
+    // downscaling ratio needs be the same for both direction, use the smaller one.
+    rotator_scale_factor = 1 << UINT32(ceilf(log2f(scale_min / max_scale_down)));
+    if (rotator_scale_factor > kMaxRotateDownScaleRatio) {
+      rotator_scale_factor = kMaxRotateDownScaleRatio;
+    }
+  }
+
+  DLOGV_IF(kTagResources, "scale_x = %.4f, scale_y = %.4f, rotator_scale_factor = %d",
+           scale_x, scale_y, rotator_scale_factor);
+
+  return FLOAT(rotator_scale_factor);
+}
+
+DisplayError ResManager::GetScaleFactor(const LayerRect &crop, const LayerRect &dst,
+                                        bool rotated90, float *scale_x, float *scale_y) {
+  float crop_width = 1.0f, crop_height = 1.0f, dst_width = 1.0f, dst_height = 1.0f;
+
+  DisplayError error = GetCropAndDestination(crop, dst, rotated90, &crop_width, &crop_height,
+                                             &dst_width, &dst_height);
+  if (error != kErrorNone) {
+    return error;
+  }
+
+  *scale_x = crop_width / dst_width;
+  *scale_y = crop_height / dst_height;
+
+  return kErrorNone;
 }
 
 DisplayError ResManager::SetDecimationFactor(HWPipeInfo *pipe) {
@@ -631,13 +771,14 @@
     }
     right_pipe->dst_roi.left = left_pipe->dst_roi.right;
   }
-  error = ValidateScaling(layer, left_pipe->src_roi, left_pipe->dst_roi, NULL);
+
+  error = ValidatePipeParams(left_pipe);
   if (error != kErrorNone) {
     goto PipeConfigExit;
   }
 
   if (right_pipe->valid) {
-    error = ValidateScaling(layer, right_pipe->src_roi, right_pipe->dst_roi, NULL);
+    error = ValidatePipeParams(right_pipe);
   }
 PipeConfigExit:
   if (error != kErrorNone) {
diff --git a/displayengine/libs/core/res_manager.cpp b/displayengine/libs/core/res_manager.cpp
index 06f6b4d..2bd1edf 100644
--- a/displayengine/libs/core/res_manager.cpp
+++ b/displayengine/libs/core/res_manager.cpp
@@ -28,7 +28,6 @@
 #include <dlfcn.h>
 
 #include "res_manager.h"
-#include "scalar_helper.h"
 
 #define __CLASS__ "ResManager"
 
@@ -36,24 +35,22 @@
 
 ResManager::ResManager()
   : num_pipe_(0), vig_pipes_(NULL), rgb_pipes_(NULL), dma_pipes_(NULL), virtual_count_(0),
-    buffer_allocator_(NULL), buffer_sync_handler_(NULL) {
+    buffer_allocator_(NULL), buffer_sync_handler_(NULL), scalar_(NULL) {
 }
 
 DisplayError ResManager::Init(const HWResourceInfo &hw_res_info) {
-  hw_res_info_ = hw_res_info;
-
-  if (!hw_res_info_.max_mixer_width)
-    hw_res_info_.max_mixer_width = kMaxSourcePipeWidth;
-
   DisplayError error = kErrorNone;
+  uint32_t num_pipe = 0;
 
-  num_pipe_ = hw_res_info_.num_vig_pipe + hw_res_info_.num_rgb_pipe + hw_res_info_.num_dma_pipe;
+  num_pipe = hw_res_info.num_vig_pipe + hw_res_info.num_rgb_pipe + hw_res_info.num_dma_pipe;
 
-  if (num_pipe_ > kPipeIdMax) {
-    DLOGE("Number of pipe is over the limit! %d", num_pipe_);
+  if (num_pipe > kPipeIdMax) {
+    DLOGE("Number of pipe is over the limit! %d", num_pipe);
     return kErrorParameters;
   }
 
+  num_pipe_ = num_pipe;
+  hw_res_info_ = hw_res_info;
   // Init pipe info
   vig_pipes_ = &src_pipes_[0];
   rgb_pipes_ = &src_pipes_[hw_res_info_.num_vig_pipe];
@@ -112,18 +109,17 @@
   rgb_pipes_[0].state = kPipeStateOwnedByKernel;
   rgb_pipes_[1].state = kPipeStateOwnedByKernel;
 
-#ifdef USES_SCALAR
-  ScalarHelper::GetInstance()->Init();
-#endif
+  error = Scalar::CreateScalar(&scalar_);
+  if (error != kErrorNone) {
+    DLOGE("Failed to create Scalar object!");
+  }
 
   max_system_bw_ = FLOAT(hw_res_info_.max_bandwidth_high);
-  return kErrorNone;
+  return error;
 }
 
 DisplayError ResManager::Deinit() {
-#ifdef USES_SCALAR
-  ScalarHelper::GetInstance()->Deinit();
-#endif
+  Scalar::Destroy(scalar_);
   return kErrorNone;
 }
 
@@ -381,12 +377,10 @@
              i, layer_config.left_pipe.pipe_id,  pipe_info->pipe_id);
   }
 
-#ifdef USES_SCALAR
-  if (!ScalarHelper::GetInstance()->ConfigureScale(hw_layers)) {
+  if (scalar_->ConfigureScale(hw_layers) != kErrorNone) {
     DLOGV_IF(kTagResources, "Scale data configuration has failed!");
     goto CleanupOnError;
   }
-#endif
 
   if (!CheckBandwidth(display_resource_ctx, hw_layers)) {
     DLOGV_IF(kTagResources, "Bandwidth check failed!");
diff --git a/displayengine/libs/core/res_manager.h b/displayengine/libs/core/res_manager.h
index bd33fec..32eb6ea 100644
--- a/displayengine/libs/core/res_manager.h
+++ b/displayengine/libs/core/res_manager.h
@@ -31,6 +31,7 @@
 
 #include "hw_interface.h"
 #include "dump_impl.h"
+#include "scalar_helper.h"
 
 namespace sde {
 
@@ -49,6 +50,7 @@
   DisplayError PostCommit(Handle display_ctx, HWLayers *hw_layers);
   void Purge(Handle display_ctx);
   DisplayError SetMaxMixerStages(Handle display_ctx, uint32_t max_mixer_stages);
+  DisplayError ValidateScaling(const LayerRect &crop, const LayerRect &dst, bool rotate90);
 
   // DumpImpl method
   virtual void AppendDump(char *buffer, uint32_t length);
@@ -85,7 +87,6 @@
 
   // todo: retrieve all these from kernel
   enum {
-    kMaxSourcePipeWidth = 2048,
     kMaxInterfaceWidth = 2048,
     kMaxRotateDownScaleRatio = 8,
     kMaxDecimationDownScaleRatio = 8,
@@ -164,8 +165,6 @@
                                   const LayerTransform &transform, const LayerRect &src_rect,
                                   const LayerRect &dst_rect, HWLayerConfig *layer_config,
                                   uint32_t align_x);
-  DisplayError ValidateScaling(const Layer &layer, const LayerRect &crop,
-                               const LayerRect &dst, float *rot_scale);
   DisplayError SrcSplitConfig(DisplayResourceContext *display_resource_ctx,
                               const LayerTransform &transform, const LayerRect &src_rect,
                               const LayerRect &dst_rect, HWLayerConfig *layer_config,
@@ -174,7 +173,19 @@
                     float *right_cut_ratio, float *bottom_cut_ratio);
   bool CalculateCropRects(const LayerRect &scissor, const LayerTransform &transform,
                           LayerRect *crop, LayerRect *dst);
-  bool IsValidDimension(const Layer &layer);
+  DisplayError ValidateLayerDimensions(const Layer &layer);
+  DisplayError ValidateDimensions(const LayerRect &crop, const LayerRect &dst, bool rotate90);
+  DisplayError ValidatePipeParams(HWPipeInfo *pipe_info);
+  DisplayError ValidateDownScaling(float scale_x, float scale_y);
+  DisplayError ValidateUpScaling(float scale_x, float scale_y);
+  DisplayError GetCropAndDestination(const LayerRect &crop, const LayerRect &dst,
+                                     bool rotate90, float *crop_width, float *crop_height,
+                                     float *dst_width, float *dst_height);
+  DisplayError GetRotatorScaleFactor(const LayerRect &crop, const LayerRect &dst,
+                                     bool rotate90, float *rotator_scale_factor);
+  float GetRotatorScaleFactor(float scale_x, float scale_y);
+  DisplayError GetScaleFactor(const LayerRect &crop, const LayerRect &dst, bool rotate90,
+                              float *scale_x, float *scale_y);
   bool CheckBandwidth(DisplayResourceContext *display_ctx, HWLayers *hw_layers);
   float GetPipeBw(DisplayResourceContext *display_ctx, HWPipeInfo *pipe, float bpp);
   float GetClockForPipe(DisplayResourceContext *display_ctx, HWPipeInfo *pipe);
@@ -200,7 +211,7 @@
                                HWPipeInfo *left_pipe, HWPipeInfo *right_pipe,
                                uint32_t align_x, uint32_t align_y);
   void ResourceStateLog(void);
-  DisplayError CalculateDecimation(float downscale, uint8_t* decimation);
+  DisplayError CalculateDecimation(float downscale, uint8_t *decimation);
 
   Locker locker_;
   HWResourceInfo hw_res_info_;
@@ -221,6 +232,7 @@
   BufferSyncHandler *buffer_sync_handler_;  // Pointer to buffer sync handler that was defined by
                                             // the display engine's client
   PropertySetting property_setting_;
+  Scalar *scalar_;
 };
 
 }  // namespace sde
diff --git a/displayengine/libs/core/rotator_ctrl.cpp b/displayengine/libs/core/rotator_ctrl.cpp
index 701006c..8018e31 100644
--- a/displayengine/libs/core/rotator_ctrl.cpp
+++ b/displayengine/libs/core/rotator_ctrl.cpp
@@ -84,7 +84,7 @@
 }
 
 DisplayError RotatorCtrl::RegisterDisplay(DisplayType type, Handle *display_ctx) {
-  DisplaRotatorContext *disp_rotator_ctx = new DisplaRotatorContext();
+  DisplayRotatorContext *disp_rotator_ctx = new DisplayRotatorContext();
   if (disp_rotator_ctx == NULL) {
     return kErrorMemory;
   }
@@ -96,7 +96,7 @@
 }
 
 void RotatorCtrl::UnregisterDisplay(Handle display_ctx) {
-  DisplaRotatorContext *disp_rotator_ctx = reinterpret_cast<DisplaRotatorContext *>(display_ctx);
+  DisplayRotatorContext *disp_rotator_ctx = reinterpret_cast<DisplayRotatorContext *>(display_ctx);
 
   delete disp_rotator_ctx;
   disp_rotator_ctx = NULL;
@@ -106,9 +106,9 @@
 DisplayError RotatorCtrl::Prepare(Handle display_ctx, HWLayers *hw_layers) {
   DisplayError error = kErrorNone;
 
-  DisplaRotatorContext *disp_rotator_ctx = reinterpret_cast<DisplaRotatorContext *>(display_ctx);
+  DisplayRotatorContext *disp_rotator_ctx = reinterpret_cast<DisplayRotatorContext *>(display_ctx);
 
-  error = PrepareSessions(hw_layers);
+  error = PrepareSessions(disp_rotator_ctx, hw_layers);
   if (error != kErrorNone) {
     DLOGE("Prepare rotator session failed for display %d", disp_rotator_ctx->display_type);
     return error;
@@ -126,9 +126,9 @@
 DisplayError RotatorCtrl::Commit(Handle display_ctx, HWLayers *hw_layers) {
   DisplayError error = kErrorNone;
 
-  DisplaRotatorContext *disp_rotator_ctx = reinterpret_cast<DisplaRotatorContext *>(display_ctx);
+  DisplayRotatorContext *disp_rotator_ctx = reinterpret_cast<DisplayRotatorContext *>(display_ctx);
 
-  error = GetOutputBuffers(hw_layers);
+  error = GetOutputBuffers(disp_rotator_ctx, hw_layers);
   if (error != kErrorNone) {
     return error;
   }
@@ -145,7 +145,8 @@
 DisplayError RotatorCtrl::PostCommit(Handle display_ctx, HWLayers *hw_layers) {
   HWLayersInfo &hw_layer_info = hw_layers->info;
   DisplayError error = kErrorNone;
-  DisplaRotatorContext *disp_rotator_ctx = reinterpret_cast<DisplaRotatorContext *>(display_ctx);
+  DisplayRotatorContext *disp_rotator_ctx = reinterpret_cast<DisplayRotatorContext *>(display_ctx);
+  int client_id = INT(disp_rotator_ctx->display_type);
 
   for (uint32_t i = 0; i < hw_layer_info.count; i++) {
     Layer& layer = hw_layer_info.stack->layers[hw_layer_info.index[i]];
@@ -155,7 +156,7 @@
       continue;
     }
 
-    error = session_manager_->SetReleaseFd(hw_rotator_session);
+    error = session_manager_->SetReleaseFd(client_id, hw_rotator_session);
     if (error != kErrorNone) {
       DLOGE("Rotator Post commit failed for display %d", disp_rotator_ctx->display_type);
       return error;
@@ -165,11 +166,22 @@
   return kErrorNone;
 }
 
-DisplayError RotatorCtrl::PrepareSessions(HWLayers *hw_layers) {
+DisplayError RotatorCtrl::Purge(Handle display_ctx, HWLayers *hw_layers) {
+  DisplayRotatorContext *disp_rotator_ctx = reinterpret_cast<DisplayRotatorContext *>(display_ctx);
+  int client_id = INT(disp_rotator_ctx->display_type);
+
+  session_manager_->Start(client_id);
+
+  return session_manager_->Stop(client_id);
+}
+
+DisplayError RotatorCtrl::PrepareSessions(DisplayRotatorContext *disp_rotator_ctx,
+                                          HWLayers *hw_layers) {
   HWLayersInfo &hw_layer_info = hw_layers->info;
   DisplayError error = kErrorNone;
+  int client_id = INT(disp_rotator_ctx->display_type);
 
-  session_manager_->Start();
+  session_manager_->Start(client_id);
 
   for (uint32_t i = 0; i < hw_layer_info.count; i++) {
     Layer& layer = hw_layer_info.stack->layers[hw_layer_info.index[i]];
@@ -197,20 +209,25 @@
     hw_session_config.secure = layer.input_buffer->flags.secure;
     hw_session_config.frame_rate = layer.frame_rate;
 
-    error = session_manager_->OpenSession(hw_rotator_session);
+    error = session_manager_->OpenSession(client_id, hw_rotator_session);
     if (error != kErrorNone) {
       return error;
     }
   }
 
-  session_manager_->Stop();
+  error = session_manager_->Stop(client_id);
+  if (error != kErrorNone) {
+    return error;
+  }
 
   return kErrorNone;
 }
 
-DisplayError RotatorCtrl::GetOutputBuffers(HWLayers *hw_layers) {
+DisplayError RotatorCtrl::GetOutputBuffers(DisplayRotatorContext *disp_rotator_ctx,
+                                           HWLayers *hw_layers) {
   HWLayersInfo &hw_layer_info = hw_layers->info;
   DisplayError error = kErrorNone;
+  int client_id = INT(disp_rotator_ctx->display_type);
 
   for (uint32_t i = 0; i < hw_layer_info.count; i++) {
     Layer& layer = hw_layer_info.stack->layers[hw_layer_info.index[i]];
@@ -220,7 +237,7 @@
       continue;
     }
 
-    error = session_manager_->GetNextBuffer(hw_rotator_session);
+    error = session_manager_->GetNextBuffer(client_id, hw_rotator_session);
     if (error != kErrorNone) {
       return error;
     }
diff --git a/displayengine/libs/core/rotator_ctrl.h b/displayengine/libs/core/rotator_ctrl.h
index 083f4ca..3e5deaf 100644
--- a/displayengine/libs/core/rotator_ctrl.h
+++ b/displayengine/libs/core/rotator_ctrl.h
@@ -47,6 +47,7 @@
   DisplayError Prepare(Handle display_ctx, HWLayers *hw_layers);
   DisplayError Commit(Handle display_ctx, HWLayers *hw_layers);
   DisplayError PostCommit(Handle display_ctx, HWLayers *hw_layers);
+  DisplayError Purge(Handle display_ctx, HWLayers *hw_layers);
 
  private:
   enum {
@@ -55,14 +56,14 @@
     kTripleBuffering = 3,
   };
 
-  struct DisplaRotatorContext {
+  struct DisplayRotatorContext {
     DisplayType display_type;
 
-    DisplaRotatorContext() : display_type(kPrimary) { }
+    DisplayRotatorContext() : display_type(kPrimary) { }
   };
 
-  DisplayError PrepareSessions(HWLayers *hw_layers);
-  DisplayError GetOutputBuffers(HWLayers *hw_layers);
+  DisplayError PrepareSessions(DisplayRotatorContext *disp_rotator_ctx, HWLayers *hw_layers);
+  DisplayError GetOutputBuffers(DisplayRotatorContext *disp_rotator_ctx, HWLayers *hw_layers);
 
   HWRotatorInterface *hw_rotator_intf_;
   SessionManager *session_manager_;
diff --git a/displayengine/libs/core/scalar_helper.cpp b/displayengine/libs/core/scalar_helper.cpp
index b5d8989..e600b79 100644
--- a/displayengine/libs/core/scalar_helper.cpp
+++ b/displayengine/libs/core/scalar_helper.cpp
@@ -22,8 +22,6 @@
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
-#ifdef USES_SCALAR
-
 #include <dlfcn.h>
 #include <utils/debug.h>
 #include "scalar_helper.h"
@@ -32,40 +30,94 @@
 
 namespace sde {
 
-ScalarHelper* ScalarHelper::scalar_helper_ = NULL;
+#ifdef USES_SCALAR
+ScalarHelper::ScalarHelper()
+  : scalar_library_name_("libscalar.so"), configure_scale_api_("configureScale"),
+    lib_scalar_(NULL), configure_scale_(NULL) {
+}
 
-ScalarHelper* ScalarHelper::GetInstance() {
-  if (scalar_helper_ == NULL) {
-    scalar_helper_ = new ScalarHelper();
+DisplayError ScalarHelper::Init() {
+  lib_scalar_ = dlopen(scalar_library_name_, RTLD_NOW);
+  if (lib_scalar_) {
+    void **scalar_func = reinterpret_cast<void **>(&configure_scale_);
+    *scalar_func = ::dlsym(lib_scalar_, configure_scale_api_);
+    if (!configure_scale_) {
+      DLOGE("Unable to find symbol for %s API!", configure_scale_api_);
+      dlclose(lib_scalar_);
+      return kErrorUndefined;
+    }
+  } else {
+    DLOGW("Unable to load %s !", scalar_library_name_);
+    return kErrorNotSupported;
   }
-  return scalar_helper_;
+
+  return kErrorNone;
 }
 
-// Scalar helper functions
-static void SetPipeInfo(HWPipeInfo* hw_pipe, scalar::PipeInfo* pipe) {
-  pipe->id = hw_pipe->pipe_id;
-  pipe->horz_deci = hw_pipe->horizontal_decimation;
-  pipe->vert_deci = hw_pipe->vertical_decimation;
-
-  pipe->src_rect.x = UINT32(hw_pipe->src_roi.left);
-  pipe->src_rect.y = UINT32(hw_pipe->src_roi.top);
-  pipe->src_rect.w = UINT32(hw_pipe->src_roi.right) - pipe->src_rect.x;
-  pipe->src_rect.h = UINT32(hw_pipe->src_roi.bottom) - pipe->src_rect.y;
-
-  pipe->dst_rect.x = UINT32(hw_pipe->dst_roi.left);
-  pipe->dst_rect.y = UINT32(hw_pipe->dst_roi.top);
-  pipe->dst_rect.w = UINT32(hw_pipe->dst_roi.right) - pipe->dst_rect.x;
-  pipe->dst_rect.h = UINT32(hw_pipe->dst_roi.bottom) - pipe->dst_rect.y;
+void ScalarHelper::Deinit() {
+  if (lib_scalar_) {
+    dlclose(lib_scalar_);
+  }
 }
 
-static void UpdateSrcRoi(scalar::PipeInfo* pipe, HWPipeInfo* hw_pipe) {
-  hw_pipe->src_roi.left   = FLOAT(pipe->src_rect.x);
-  hw_pipe->src_roi.top    = FLOAT(pipe->src_rect.y);
-  hw_pipe->src_roi.right  = FLOAT(pipe->src_rect.x + pipe->src_rect.w);
-  hw_pipe->src_roi.bottom = FLOAT(pipe->src_rect.y + pipe->src_rect.h);
+// Helper functions
+void ScalarHelper::SetPipeInfo(const HWPipeInfo &hw_pipe, scalar::PipeInfo *pipe) {
+  pipe->id = hw_pipe.pipe_id;
+  pipe->horz_deci = hw_pipe.horizontal_decimation;
+  pipe->vert_deci = hw_pipe.vertical_decimation;
+
+  pipe->src_rect.x = UINT32(hw_pipe.src_roi.left);
+  pipe->src_rect.y = UINT32(hw_pipe.src_roi.top);
+  pipe->src_rect.w = UINT32(hw_pipe.src_roi.right) - pipe->src_rect.x;
+  pipe->src_rect.h = UINT32(hw_pipe.src_roi.bottom) - pipe->src_rect.y;
+
+  pipe->dst_rect.x = UINT32(hw_pipe.dst_roi.left);
+  pipe->dst_rect.y = UINT32(hw_pipe.dst_roi.top);
+  pipe->dst_rect.w = UINT32(hw_pipe.dst_roi.right) - pipe->dst_rect.x;
+  pipe->dst_rect.h = UINT32(hw_pipe.dst_roi.bottom) - pipe->dst_rect.y;
 }
 
-static uint32_t GetScalarFormat(LayerBufferFormat source) {
+void ScalarHelper::UpdateSrcRoi(const scalar::PipeInfo &pipe, HWPipeInfo *hw_pipe) {
+  hw_pipe->src_roi.left   = FLOAT(pipe.src_rect.x);
+  hw_pipe->src_roi.top    = FLOAT(pipe.src_rect.y);
+  hw_pipe->src_roi.right  = FLOAT(pipe.src_rect.x + pipe.src_rect.w);
+  hw_pipe->src_roi.bottom = FLOAT(pipe.src_rect.y + pipe.src_rect.h);
+}
+
+void ScalarHelper::SetScaleData(const scalar::PipeInfo &pipe, ScaleData *scale_data) {
+  scalar::Scale *scale = pipe.scale_data;
+  scale_data->src_width = pipe.src_width;
+  scale_data->src_height = pipe.src_height;
+  scale_data->enable_pixel_ext = scale->enable_pxl_ext;
+
+  for (int i = 0; i < 4; i++) {
+    HWPlane &plane = scale_data->plane[i];
+    plane.init_phase_x = scale->init_phase_x[i];
+    plane.phase_step_x = scale->phase_step_x[i];
+    plane.init_phase_y = scale->init_phase_y[i];
+    plane.phase_step_y = scale->phase_step_y[i];
+
+    plane.left.extension = scale->left.extension[i];
+    plane.left.overfetch = scale->left.overfetch[i];
+    plane.left.repeat = scale->left.repeat[i];
+
+    plane.top.extension = scale->top.extension[i];
+    plane.top.overfetch = scale->top.overfetch[i];
+    plane.top.repeat = scale->top.repeat[i];
+
+    plane.right.extension = scale->right.extension[i];
+    plane.right.overfetch = scale->right.overfetch[i];
+    plane.right.repeat = scale->right.repeat[i];
+
+    plane.bottom.extension = scale->bottom.extension[i];
+    plane.bottom.overfetch = scale->bottom.overfetch[i];
+    plane.bottom.repeat = scale->bottom.repeat[i];
+
+    plane.roi_width = scale->roi_width[i];
+  }
+}
+
+uint32_t ScalarHelper::GetScalarFormat(LayerBufferFormat source) {
   uint32_t format = scalar::UNKNOWN_FORMAT;
 
   switch (source) {
@@ -101,48 +153,26 @@
   return format;
 }
 
-void ScalarHelper::Init() {
-  lib_scalar_handle_   = NULL;
-  ScalarConfigureScale = NULL;
-
-  lib_scalar_handle_ = dlopen(SCALAR_LIBRARY_NAME, RTLD_NOW);
-  if (lib_scalar_handle_) {
-    void **scalar_func = reinterpret_cast<void **>(&ScalarConfigureScale);
-    *scalar_func = ::dlsym(lib_scalar_handle_, "configureScale");
-  } else {
-    DLOGW("Unable to load %s !", SCALAR_LIBRARY_NAME);
-  }
-}
-
-void ScalarHelper::Deinit() {
-  if (lib_scalar_handle_) {
-    dlclose(lib_scalar_handle_);
-    lib_scalar_handle_ = NULL;
-  }
-}
-
-bool ScalarHelper::ConfigureScale(HWLayers *hw_layers) {
-
-  if (!lib_scalar_handle_ || !ScalarConfigureScale) {
-    // No scalar library
-    return true;
-  }
-
-  // Reset scale data
-  memset(&scale_data_, 0, sizeof(scale_data_));
+DisplayError ScalarHelper::ConfigureScale(HWLayers *hw_layers) {
   HWLayersInfo &hw_layer_info = hw_layers->info;
 
   for (uint32_t i = 0; i < hw_layer_info.count; i++) {
     Layer &layer = hw_layer_info.stack->layers[hw_layer_info.index[i]];
     uint32_t width = layer.input_buffer->width;
+    uint32_t height = layer.input_buffer->height;
     LayerBufferFormat format = layer.input_buffer->format;
-    HWPipeInfo* left_pipe = &hw_layers->config[i].left_pipe;
-    HWPipeInfo* right_pipe = &hw_layers->config[i].right_pipe;
+    HWPipeInfo &left_pipe = hw_layers->config[i].left_pipe;
+    HWPipeInfo &right_pipe = hw_layers->config[i].right_pipe;
     HWRotatorSession *hw_rotator_session = &hw_layers->config[i].hw_rotator_session;
 
+    // Reset scale data
+    memset(&left_pipe.scale_data, 0, sizeof(ScaleData));
+    memset(&right_pipe.scale_data, 0, sizeof(ScaleData));
+
     // Prepare data structure for lib scalar
     uint32_t flags = 0;
     struct scalar::LayerInfo layer_info;
+    struct scalar::Scale left_scale, right_scale;
 
     if (layer.transform.rotation == 90.0f) {
       // Flips will be taken care by rotator, if layer requires 90 rotation
@@ -153,18 +183,20 @@
     }
 
     for (uint32_t count = 0; count < 2; count++) {
-      HWPipeInfo* hw_pipe = (count == 0) ? left_pipe : right_pipe;
+      const HWPipeInfo &hw_pipe = (count == 0) ? left_pipe : right_pipe;
       HWRotateInfo* hw_rotate_info = &hw_rotator_session->hw_rotate_info[count];
       scalar::PipeInfo* pipe = (count == 0) ? &layer_info.left_pipe : &layer_info.right_pipe;
 
       if (hw_rotate_info->valid) {
         width = UINT32(hw_rotate_info->dst_roi.right - hw_rotate_info->dst_roi.left);
+        height = UINT32(hw_rotate_info->dst_roi.bottom - hw_rotate_info->dst_roi.top);
         format = hw_rotator_session->output_buffer.format;
       }
 
       pipe->flags = flags;
-      pipe->scale_data = GetScaleRef(i, !count);
-      pipe->scale_data->src_width = width;
+      pipe->scale_data = (count == 0) ? &left_scale : &right_scale;
+      pipe->src_width = width;
+      pipe->src_height = height;
       SetPipeInfo(hw_pipe, pipe);
     }
     layer_info.src_format = GetScalarFormat(format);
@@ -184,57 +216,52 @@
       layer_info.right_pipe.dst_rect.w, layer_info.right_pipe.dst_rect.h);
 
     // Configure scale data structure
-    if (ScalarConfigureScale(&layer_info) < 0) {
+    if (configure_scale_(&layer_info) < 0) {
       DLOGE("Scalar library failed to configure scale data!");
-      return false;
+      return kErrorParameters;
     }
 
-    // Update Src Roi in HWPipeInfo
-    if (layer_info.left_pipe.scale_data->enable_pxl_ext)
-      UpdateSrcRoi(&layer_info.left_pipe, left_pipe);
-    if (layer_info.right_pipe.scale_data->enable_pxl_ext)
-      UpdateSrcRoi(&layer_info.right_pipe, right_pipe);
+    // Set ScaleData and update SrcRoi in HWPipeInfo
+    if (left_scale.enable_pxl_ext) {
+      SetScaleData(layer_info.left_pipe, &left_pipe.scale_data);
+      UpdateSrcRoi(layer_info.left_pipe, &left_pipe);
+    }
+    if (right_scale.enable_pxl_ext) {
+      SetScaleData(layer_info.right_pipe, &right_pipe.scale_data);
+      UpdateSrcRoi(layer_info.right_pipe, &right_pipe);
+    }
   }
-  return true;
+
+  return kErrorNone;
 }
-
-void ScalarHelper::UpdateSrcWidth(uint32_t index, bool left, uint32_t* width) {
-  *width = GetScaleRef(index, left)->src_width;
-}
-
-void ScalarHelper::SetScaleData(uint32_t index, bool left, mdp_scale_data* mdp_scale) {
-
-  if (!lib_scalar_handle_ || !ScalarConfigureScale)
-    return;
-
-  scalar::Scale* scale = GetScaleRef(index, left);
-  mdp_scale->enable_pxl_ext = scale->enable_pxl_ext;
-
-  for (int i = 0; i < MAX_PLANES; i++) {
-    mdp_scale->init_phase_x[i] = scale->init_phase_x[i];
-    mdp_scale->phase_step_x[i] = scale->phase_step_x[i];
-    mdp_scale->init_phase_y[i] = scale->init_phase_y[i];
-    mdp_scale->phase_step_y[i] = scale->phase_step_y[i];
-
-    mdp_scale->num_ext_pxls_left[i] = scale->left.extension[i];
-    mdp_scale->num_ext_pxls_top[i] = scale->top.extension[i];
-    mdp_scale->num_ext_pxls_right[i] = scale->right.extension[i];
-    mdp_scale->num_ext_pxls_btm[i] = scale->bottom.extension[i];
-
-    mdp_scale->left_ftch[i] = scale->left.overfetch[i];
-    mdp_scale->top_ftch[i] = scale->top.overfetch[i];
-    mdp_scale->right_ftch[i] = scale->right.overfetch[i];
-    mdp_scale->btm_ftch[i] = scale->bottom.overfetch[i];
-
-    mdp_scale->left_rpt[i] = scale->left.repeat[i];
-    mdp_scale->top_rpt[i] = scale->top.repeat[i];
-    mdp_scale->right_rpt[i] = scale->right.repeat[i];
-    mdp_scale->btm_rpt[i] = scale->bottom.repeat[i];
-
-    mdp_scale->roi_w[i] = scale->roi_width[i];
-  }
-}
-
-} // namespace sde
-
 #endif
+
+DisplayError Scalar::CreateScalar(Scalar **scalar) {
+  Scalar *scalar_obj = NULL;
+
+#ifdef USES_SCALAR
+  scalar_obj = new ScalarHelper();
+  if (scalar_obj) {
+    if (scalar_obj->Init() == kErrorNone) {
+      goto OnSuccess;
+    } else {
+      delete scalar_obj;
+    }
+  }
+#endif
+
+  scalar_obj = new Scalar();
+  if (!scalar_obj) {
+    return kErrorMemory;
+  }
+
+OnSuccess:
+  *scalar = scalar_obj;
+  return kErrorNone;
+}
+
+void Scalar::Destroy(Scalar *scalar) {
+  scalar->Deinit();
+}
+
+}  // namespace sde
diff --git a/displayengine/libs/core/scalar_helper.h b/displayengine/libs/core/scalar_helper.h
index a54cb0c..35217c5 100755
--- a/displayengine/libs/core/scalar_helper.h
+++ b/displayengine/libs/core/scalar_helper.h
@@ -25,43 +25,47 @@
 #ifndef __SCALAR_HELPER_H__
 #define __SCALAR_HELPER_H__
 
-#ifdef USES_SCALAR
-
-#include <sys/types.h>
-#include <linux/msm_mdp_ext.h>
 #include <hw_interface.h>
+#ifdef USES_SCALAR
 #include <scalar.h>
-
-#define SCALAR_LIBRARY_NAME "libscalar.so"
+#endif
 
 namespace sde {
 
-class ScalarHelper {
-
+class Scalar {
  public:
-  void Init();
-  void Deinit();
-  bool ConfigureScale(HWLayers *hw_layers);
-  void UpdateSrcWidth(uint32_t index, bool left, uint32_t* src_width);
-  void SetScaleData(uint32_t index, bool left, mdp_scale_data* mdp_scale);
-  static ScalarHelper* GetInstance();
+  static DisplayError CreateScalar(Scalar **scalar);
+  static void Destroy(Scalar *scalar);
+  virtual ~Scalar() { }
+  virtual DisplayError ConfigureScale(HWLayers *hw_layers) { return kErrorNone; }
+
+ protected:
+  virtual DisplayError Init() { return kErrorNone; }
+  virtual void Deinit() { }
+};
+
+#ifdef USES_SCALAR
+class ScalarHelper : public Scalar {
+ public:
+  ScalarHelper();
+  virtual DisplayError ConfigureScale(HWLayers *hw_layers);
+
+ protected:
+  virtual DisplayError Init();
+  virtual void Deinit();
 
  private:
-  explicit ScalarHelper() { }
-  struct ScaleData {
-    scalar::Scale left_scale;
-    scalar::Scale right_scale;
-  };
-  struct ScaleData scale_data_[kMaxSDELayers];
-  void* lib_scalar_handle_;
-  int (*ScalarConfigureScale)(struct scalar::LayerInfo* layer);
-  scalar::Scale* GetScaleRef(uint32_t index, bool left) {
-    return (left ? &scale_data_[index].left_scale : &scale_data_[index].right_scale);
-  }
-  static ScalarHelper* scalar_helper_;  // Singleton Instance
+  const char *scalar_library_name_;
+  const char *configure_scale_api_;
+  void* lib_scalar_;
+  int (*configure_scale_)(scalar::LayerInfo *layer);
+  void SetPipeInfo(const HWPipeInfo &hw_pipe, scalar::PipeInfo *pipe);
+  void UpdateSrcRoi(const scalar::PipeInfo &pipe, HWPipeInfo *hw_pipe);
+  void SetScaleData(const scalar::PipeInfo &pipe, ScaleData *scale_data);
+  uint32_t GetScalarFormat(LayerBufferFormat source);
 };
+#endif
 
 }  // namespace sde
 
-#endif
 #endif  // __SCALAR_HELPER_H__
diff --git a/displayengine/libs/core/session_manager.cpp b/displayengine/libs/core/session_manager.cpp
index f87bf10..dd4c29a 100644
--- a/displayengine/libs/core/session_manager.cpp
+++ b/displayengine/libs/core/session_manager.cpp
@@ -59,23 +59,28 @@
     buffer_sync_handler_(buffer_sync_handler), active_session_count_(0) {
 }
 
-void SessionManager::Start() {
+void SessionManager::Start(const int &client_id) {
+  SCOPE_LOCK(locker_);
+
   uint32_t session_count = 0;
-  uint32_t ready_session_count = 0;
+  uint32_t acquired_session_count = 0;
 
   // Change the state of acquired session to kSessionReady
-  while ((ready_session_count < active_session_count_) && (session_count < kMaxSessionCount)) {
-    if (session_list_[session_count].state == kSessionReleased) {
-      session_count++;
-      continue;
+  while ((acquired_session_count < active_session_count_) && (session_count < kMaxSessionCount)) {
+    if (session_list_[session_count].state == kSessionAcquired) {
+      if (session_list_[session_count].client_id == client_id) {
+        session_list_[session_count].state = kSessionReady;
+      }
+      acquired_session_count++;
     }
-
-    session_list_[session_count++].state = kSessionReady;
-    ready_session_count++;
+    session_count++;
   }
 }
 
-DisplayError SessionManager::OpenSession(HWRotatorSession *hw_rotator_session) {
+DisplayError SessionManager::OpenSession(const int &client_id,
+                                         HWRotatorSession *hw_rotator_session) {
+  SCOPE_LOCK(locker_);
+
   DisplayError error = kErrorNone;
 
   const HWSessionConfig &input_config = hw_rotator_session->hw_session_config;
@@ -90,12 +95,12 @@
 
   uint32_t free_session = active_session_count_;
   uint32_t acquired_session = kMaxSessionCount;
-  uint32_t ready_session_count = 0;
+  uint32_t active_session_count = 0;
 
   // First look for a session in ready state, if no session found in ready state matching
   // with current input session config, assign a session in released state.
   for (uint32_t session_count = 0; session_count < kMaxSessionCount &&
-       ready_session_count < active_session_count_; session_count++) {
+       active_session_count < active_session_count_; session_count++) {
     HWSessionConfig &hw_session_config =
            session_list_[session_count].hw_rotator_session.hw_session_config;
 
@@ -104,17 +109,15 @@
       continue;
     }
 
-    if (session_list_[session_count].state != kSessionReady) {
-      continue;
+    if (session_list_[session_count].state == kSessionReady) {
+      if (session_list_[session_count].client_id == client_id &&
+          input_config == hw_session_config) {
+        session_list_[session_count].state = kSessionAcquired;
+        acquired_session = session_count;
+        break;
+      }
     }
-
-    if (input_config == hw_session_config) {
-      session_list_[session_count].state = kSessionAcquired;
-      acquired_session = session_count;
-      break;
-    }
-
-    ready_session_count++;
+    active_session_count++;
   }
 
   // If the input config does not match with existing config, then add new session and change the
@@ -131,31 +134,31 @@
 
     acquired_session = free_session;
     hw_rotator_session->session_id = acquired_session;
+    session_list_[acquired_session].client_id = client_id;
     active_session_count_++;
 
     DLOGV_IF(kTagRotator, "Acquire new session Output: width = %d, height = %d, format = %d, " \
-             "session_id %d", hw_rotator_session->output_buffer.width,
+             "session_id %d, client_id %d", hw_rotator_session->output_buffer.width,
              hw_rotator_session->output_buffer.height, hw_rotator_session->output_buffer.format,
-             hw_rotator_session->session_id);
+             hw_rotator_session->session_id, client_id);
 
     return kErrorNone;
   }
 
-  hw_rotator_session->output_buffer.width = input_config.dst_width;
-  hw_rotator_session->output_buffer.height = input_config.dst_height;
-  hw_rotator_session->output_buffer.format = input_config.dst_format;
-  hw_rotator_session->output_buffer.flags.secure = input_config.secure;
-  hw_rotator_session->session_id = acquired_session;
+  *hw_rotator_session = session_list_[acquired_session].hw_rotator_session;
 
   DLOGV_IF(kTagRotator, "Acquire existing session Output: width = %d, height = %d, format = %d, " \
-           "session_id %d", hw_rotator_session->output_buffer.width,
+           "session_id %d, client_id %d", hw_rotator_session->output_buffer.width,
            hw_rotator_session->output_buffer.height, hw_rotator_session->output_buffer.format,
-           hw_rotator_session->session_id);
+           hw_rotator_session->session_id, client_id);
 
   return kErrorNone;
 }
 
-DisplayError SessionManager::GetNextBuffer(HWRotatorSession *hw_rotator_session) {
+DisplayError SessionManager::GetNextBuffer(const int &client_id,
+                                           HWRotatorSession *hw_rotator_session) {
+  SCOPE_LOCK(locker_);
+
   DisplayError error = kErrorNone;
 
   int session_id = hw_rotator_session->session_id;
@@ -166,7 +169,7 @@
   Session *session = &session_list_[session_id];
   if (session->state != kSessionAcquired) {
     DLOGE("Invalid session state %d", session->state);
-    kErrorParameters;
+    return kErrorParameters;
   }
 
   uint32_t curr_index = session->curr_index;
@@ -195,33 +198,38 @@
   hw_rotator_session->output_buffer.planes[0].fd = buffer_info->alloc_buffer_info.fd;
   hw_rotator_session->output_buffer.planes[0].offset = session->offset[curr_index];
 
+  session->hw_rotator_session = *hw_rotator_session;
+
   DLOGI_IF(kTagRotator, "Output: width = %d, height = %d, format = %d, stride %d, " \
-           "curr_index = %d, offset %d, fd %d, session_id %d,",
+           "curr_index = %d, offset %d, fd %d, session_id %d, client_id %d",
            hw_rotator_session->output_buffer.width, hw_rotator_session->output_buffer.height,
            hw_rotator_session->output_buffer.format,
            hw_rotator_session->output_buffer.planes[0].stride, curr_index,
            hw_rotator_session->output_buffer.planes[0].offset,
-           hw_rotator_session->output_buffer.planes[0].fd, hw_rotator_session->session_id);
+           hw_rotator_session->output_buffer.planes[0].fd, session_id, client_id);
 
   return kErrorNone;
 }
 
-DisplayError SessionManager::Stop() {
+DisplayError SessionManager::Stop(const int &client_id) {
+  SCOPE_LOCK(locker_);
+
   DisplayError error = kErrorNone;
   uint32_t session_id = 0;
 
   // Release all the sessions which were not acquired in the current cycle and deallocate the
   // buffers associated with it.
   while ((active_session_count_ > 0) && (session_id < kMaxSessionCount)) {
-    if (session_list_[session_id].state == kSessionReady) {
+    if (session_list_[session_id].state == kSessionReady &&
+        session_list_[session_id].client_id == client_id) {
       error = ReleaseSession(&session_list_[session_id]);
       if (error != kErrorNone) {
         return error;
       }
       active_session_count_--;
 
-      DLOGI_IF(kTagRotator, "session_id = %d, active_session_count = %d", session_id,
-               active_session_count_);
+      DLOGI_IF(kTagRotator, "session_id = %d, active_session_count = %d, client_id %d", session_id,
+               active_session_count_, client_id);
     }
     session_id++;
   }
@@ -229,7 +237,10 @@
   return kErrorNone;
 }
 
-DisplayError SessionManager::SetReleaseFd(HWRotatorSession *hw_rotator_session) {
+DisplayError SessionManager::SetReleaseFd(const int &client_id,
+                                          HWRotatorSession *hw_rotator_session) {
+  SCOPE_LOCK(locker_);
+
   int session_id = hw_rotator_session->session_id;
   if (session_id > kMaxSessionCount) {
     return kErrorParameters;
@@ -238,7 +249,7 @@
   Session *session = &session_list_[session_id];
   if (session->state != kSessionAcquired) {
     DLOGE("Invalid session state %d", session->state);
-    kErrorParameters;
+    return kErrorParameters;
   }
 
   uint32_t &curr_index = session->curr_index;
@@ -251,8 +262,8 @@
 
   curr_index = (curr_index + 1) % buffer_count;
 
-  DLOGI_IF(kTagRotator, "session_id %d, curr_index = %d, release fd %d", session_id,
-           curr_index, hw_rotator_session->output_buffer.release_fence_fd);
+  DLOGI_IF(kTagRotator, "session_id %d, curr_index = %d, release fd %d, client_id %d", session_id,
+           curr_index, hw_rotator_session->output_buffer.release_fence_fd, client_id);
 
   return kErrorNone;
 }
@@ -333,7 +344,9 @@
       session->release_fd[idx] = -1;
     }
   }
+
   session->state = kSessionReleased;
+  session->client_id == -1;
 
   if (session->offset) {
     delete[] session->offset;
diff --git a/displayengine/libs/core/session_manager.h b/displayengine/libs/core/session_manager.h
index b27ba8b..3324c3e 100644
--- a/displayengine/libs/core/session_manager.h
+++ b/displayengine/libs/core/session_manager.h
@@ -43,11 +43,11 @@
   SessionManager(HWRotatorInterface *hw_intf, BufferAllocator *buffer_allocator,
                  BufferSyncHandler *buffer_sync_handler);
 
-  void Start();
-  DisplayError Stop();
-  DisplayError OpenSession(HWRotatorSession *hw_rotator_session);
-  DisplayError GetNextBuffer(HWRotatorSession *hw_rotator_session);
-  DisplayError SetReleaseFd(HWRotatorSession *hw_rotator_session);
+  void Start(const int &client_id);
+  DisplayError Stop(const int &client_id);
+  DisplayError OpenSession(const int &client_id, HWRotatorSession *hw_rotator_session);
+  DisplayError GetNextBuffer(const int &client_id, HWRotatorSession *hw_rotator_session);
+  DisplayError SetReleaseFd(const int &client_id, HWRotatorSession *hw_rotator_session);
 
  private:
   // TODO(user): Read from hw capability instead of hardcoding
@@ -66,13 +66,16 @@
     int *release_fd;
     uint32_t *offset;
     uint32_t curr_index;
+    int client_id;
 
-    Session() : state(kSessionReleased), release_fd(NULL), offset(NULL), curr_index(0) { }
+    Session() : state(kSessionReleased), release_fd(NULL), offset(NULL), curr_index(0),
+                client_id(-1) { }
   };
 
   DisplayError AcquireSession(HWRotatorSession *hw_rotator_session, Session *session);
   DisplayError ReleaseSession(Session *session);
 
+  Locker locker_;
   Session session_list_[kMaxSessionCount];
   HWRotatorInterface *hw_rotator_intf_;
   BufferAllocator *buffer_allocator_;
diff --git a/libgralloc/alloc_controller.cpp b/libgralloc/alloc_controller.cpp
index b8e6a64..e37cddd 100644
--- a/libgralloc/alloc_controller.cpp
+++ b/libgralloc/alloc_controller.cpp
@@ -49,17 +49,28 @@
 
 #define ASTC_BLOCK_SIZE 16
 
-#ifdef ION_FLAG_CP_PIXEL
-#define CP_HEAP_ID ION_SECURE_HEAP_ID
-#else
+#ifndef ION_FLAG_CP_PIXEL
 #define ION_FLAG_CP_PIXEL 0
-#define CP_HEAP_ID ION_CP_MM_HEAP_ID
 #endif
 
 #ifndef ION_FLAG_ALLOW_NON_CONTIG
 #define ION_FLAG_ALLOW_NON_CONTIG 0
 #endif
 
+#ifdef MASTER_SIDE_CP
+#define CP_HEAP_ID ION_SECURE_HEAP_ID
+/* Please Add the new SD ION Heap here */
+#define SD_HEAP_ID 0
+#define ION_CP_FLAGS (ION_SECURE | ION_FLAG_CP_PIXEL)
+/* Please Add the new SD ION Flag here */
+#define ION_SD_FLAGS ION_SECURE
+#else // SLAVE_SIDE_CP
+#define CP_HEAP_ID ION_CP_MM_HEAP_ID
+#define SD_HEAP_ID CP_HEAP_ID
+#define ION_CP_FLAGS (ION_SECURE | ION_FLAG_ALLOW_NON_CONTIG)
+#define ION_SD_FLAGS ION_SECURE
+#endif
+
 using namespace gralloc;
 using namespace qdutils;
 
@@ -108,6 +119,16 @@
         *(void **)&LINK_adreno_isUBWCSupportedByGpu =
                 ::dlsym(libadreno_utils, "isUBWCSupportedByGpu");
     }
+
+    // Check if the overriding property debug.gralloc.gfx_ubwc_disable
+    // that disables UBWC allocations for the graphics stack is set
+    gfx_ubwc_disable = 0;
+    char property[PROPERTY_VALUE_MAX];
+    property_get("debug.gralloc.gfx_ubwc_disable", property, "0");
+    if(!(strncmp(property, "1", PROPERTY_VALUE_MAX)) ||
+       !(strncmp(property, "true", PROPERTY_VALUE_MAX))) {
+        gfx_ubwc_disable = 1;
+    }
 }
 
 AdrenoMemInfo::~AdrenoMemInfo()
@@ -282,7 +303,7 @@
 
 int AdrenoMemInfo::isUBWCSupportedByGPU(int format)
 {
-    if (libadreno_utils) {
+    if (!gfx_ubwc_disable && libadreno_utils) {
         if (LINK_adreno_isUBWCSupportedByGpu) {
             ADRENOPIXELFORMAT gpu_format = getGpuPixelFormat(format);
             return LINK_adreno_isUBWCSupportedByGpu(gpu_format);
@@ -347,21 +368,16 @@
 
     if(usage & GRALLOC_USAGE_PROTECTED) {
         if (usage & GRALLOC_USAGE_PRIVATE_MM_HEAP) {
-            ionHeapId = ION_HEAP(CP_HEAP_ID);
-            ionFlags |= ION_SECURE;
             if (usage & GRALLOC_USAGE_PRIVATE_SECURE_DISPLAY) {
+                ionHeapId = ION_HEAP(SD_HEAP_ID);
                 /*
                  * There is currently no flag in ION for Secure Display
-                 * VM. Please add it here once available.
-                 *
-                   ionFlags |= <Ion flag for Secure Display>;
+                 * VM. Please add it to the define once available.
                 */
+                ionFlags |= ION_SD_FLAGS;
             } else {
-                ionFlags |= ION_FLAG_CP_PIXEL;
-            }
-
-            if (!(usage & GRALLOC_USAGE_PRIVATE_SECURE_DISPLAY)) {
-                ionFlags |= ION_FLAG_ALLOW_NON_CONTIG;
+                ionHeapId = ION_HEAP(CP_HEAP_ID);
+                ionFlags |= ION_CP_FLAGS;
             }
         } else {
             // for targets/OEMs which do not need HW level protection
@@ -912,3 +928,38 @@
     }
     return size;
 }
+
+int getRgbDataAddress(private_handle_t* hnd, void* rgb_data)
+{
+    int err = 0;
+
+    // This api is for RGB* formats
+    if (hnd->format > HAL_PIXEL_FORMAT_sRGB_X_8888) {
+        return -EINVAL;
+    }
+
+    // linear buffer
+    if (!(hnd->flags & private_handle_t::PRIV_FLAGS_UBWC_ALIGNED)) {
+        rgb_data = (void*)hnd->base;
+        return err;
+    }
+
+    unsigned int meta_size = 0;
+    switch (hnd->format) {
+        case HAL_PIXEL_FORMAT_RGB_565:
+            meta_size = getUBwcMetaBufferSize(hnd->width, hnd->height, 2);
+            break;
+        case HAL_PIXEL_FORMAT_RGBA_8888:
+        case HAL_PIXEL_FORMAT_RGBX_8888:
+        case HAL_PIXEL_FORMAT_sRGB_A_8888:
+            meta_size = getUBwcMetaBufferSize(hnd->width, hnd->height, 4);
+            break;
+        default:
+            ALOGE("%s:Unsupported RGB format: 0x%x", __FUNCTION__, hnd->format);
+            err = -EINVAL;
+            break;
+    }
+
+    rgb_data = (void*)(hnd->base + meta_size);
+    return err;
+}
diff --git a/libgralloc/gpu.cpp b/libgralloc/gpu.cpp
index 53363bb..0fd6e3b 100644
--- a/libgralloc/gpu.cpp
+++ b/libgralloc/gpu.cpp
@@ -34,7 +34,7 @@
 #define SZ_1M 0x100000
 #define SZ_4K 0x1000
 
-#ifdef ION_FLAG_CP_PIXEL
+#ifdef MASTER_SIDE_CP
 #define SECURE_ALIGN SZ_4K
 #else
 #define SECURE_ALIGN SZ_1M
@@ -308,6 +308,25 @@
             grallocFormat = HAL_PIXEL_FORMAT_RGBA_8888;
     }
 
+    bool useFbMem = false;
+    char property[PROPERTY_VALUE_MAX];
+    char isUBWC[PROPERTY_VALUE_MAX];
+    if (usage & GRALLOC_USAGE_HW_FB) {
+        if ((property_get("debug.gralloc.map_fb_memory", property, NULL) > 0) &&
+            (!strncmp(property, "1", PROPERTY_VALUE_MAX ) ||
+            (!strncasecmp(property,"true", PROPERTY_VALUE_MAX )))) {
+            useFbMem = true;
+        } else {
+            if (property_get("debug.gralloc.enable_fb_ubwc", isUBWC, NULL) > 0){
+                if ((!strncmp(isUBWC, "1", PROPERTY_VALUE_MAX)) ||
+                    (!strncasecmp(isUBWC, "true", PROPERTY_VALUE_MAX))) {
+                    // Allocate UBWC aligned framebuffer
+                    usage |= GRALLOC_USAGE_PRIVATE_ALLOC_UBWC;
+                }
+            }
+        }
+    }
+
     getGrallocInformationFromFormat(grallocFormat, &bufferType);
     size = getBufferSizeAndDimensions(w, h, grallocFormat, usage, alignedw,
                    alignedh);
@@ -316,15 +335,6 @@
         return -EINVAL;
     size = (bufferSize >= size)? bufferSize : size;
 
-    bool useFbMem = false;
-    char property[PROPERTY_VALUE_MAX];
-    if((usage & GRALLOC_USAGE_HW_FB) &&
-       (property_get("debug.gralloc.map_fb_memory", property, NULL) > 0) &&
-       (!strncmp(property, "1", PROPERTY_VALUE_MAX ) ||
-        (!strncasecmp(property,"true", PROPERTY_VALUE_MAX )))) {
-        useFbMem = true;
-    }
-
     int err = 0;
     if(useFbMem) {
         err = gralloc_alloc_framebuffer(usage, pHandle);
diff --git a/libgralloc/gr.h b/libgralloc/gr.h
index 5ee0cf8..98b4eec 100644
--- a/libgralloc/gr.h
+++ b/libgralloc/gr.h
@@ -71,6 +71,7 @@
 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);
+int getRgbDataAddress(private_handle_t* pHnd, void* rgb_data);
 
 // To query if UBWC is enabled, based on format and usage flags
 bool isUBwcEnabled(int format, int usage);
@@ -148,6 +149,8 @@
     ADRENOPIXELFORMAT getGpuPixelFormat(int hal_format);
 
     private:
+        // Overriding flag to disable UBWC alloc for graphics stack
+        int  gfx_ubwc_disable;
         // Pointer to the padding library.
         void *libadreno_utils;
 
diff --git a/libgralloc/gralloc_priv.h b/libgralloc/gralloc_priv.h
index 676c3bc..6998296 100755
--- a/libgralloc/gralloc_priv.h
+++ b/libgralloc/gralloc_priv.h
@@ -85,6 +85,7 @@
 #define GRALLOC_MODULE_PERFORM_GET_YUV_PLANE_INFO 7
 #define GRALLOC_MODULE_PERFORM_GET_MAP_SECURE_BUFFER_INFO 8
 #define GRALLOC_MODULE_PERFORM_GET_UBWC_FLAG 9
+#define GRALLOC_MODULE_PERFORM_GET_RGB_DATA_ADDRESS 10
 
 /* OEM specific HAL formats */
 
diff --git a/libgralloc/mapper.cpp b/libgralloc/mapper.cpp
index acac5b4..7d4e8ce 100644
--- a/libgralloc/mapper.cpp
+++ b/libgralloc/mapper.cpp
@@ -66,8 +66,11 @@
     unsigned int size = 0;
     int err = 0;
     IMemAlloc* memalloc = getAllocator(hnd->flags) ;
-    void *mappedAddress;
-    // Dont map FRAMEBUFFER and SECURE_BUFFERS
+    void *mappedAddress = MAP_FAILED;
+    hnd->base = 0;
+    hnd->base_metadata = 0;
+
+    // Dont map framebuffer and secure buffers
     if (!(hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER) &&
         !(hnd->flags & private_handle_t::PRIV_FLAGS_SECURE_BUFFER)) {
         size = hnd->size;
@@ -76,14 +79,14 @@
         if(err || mappedAddress == MAP_FAILED) {
             ALOGE("Could not mmap handle %p, fd=%d (%s)",
                   handle, hnd->fd, strerror(errno));
-            hnd->base = 0;
             return -errno;
         }
 
         hnd->base = uint64_t(mappedAddress) + hnd->offset;
     }
 
-    //Allow mapping of metadata for all buffers and SECURE_BUFFER
+    //Allow mapping of metadata for all buffers including secure ones, but not
+    //of framebuffer
     if (!(hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER)) {
         mappedAddress = MAP_FAILED;
         size = ROUND_UP_PAGESIZE(sizeof(MetaData_t));
@@ -92,7 +95,6 @@
         if(err || mappedAddress == MAP_FAILED) {
             ALOGE("Could not mmap handle %p, fd=%d (%s)",
                   handle, hnd->fd_metadata, strerror(errno));
-            hnd->base_metadata = 0;
             return -errno;
         }
         hnd->base_metadata = uint64_t(mappedAddress) + hnd->offset_metadata;
@@ -104,32 +106,37 @@
                          buffer_handle_t handle)
 {
     ATRACE_CALL();
+    int err = -EINVAL;
     if(!module)
-        return -EINVAL;
+        return err;
 
     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;
-        unsigned int size = hnd->size;
-        IMemAlloc* memalloc = getAllocator(hnd->flags) ;
-        if(memalloc != NULL) {
-            err = memalloc->unmap_buffer(base, size, hnd->offset);
-            if (err) {
-                ALOGE("Could not unmap memory at address %p", base);
-            }
-            base = (void*)hnd->base_metadata;
-            size = ROUND_UP_PAGESIZE(sizeof(MetaData_t));
-            err = memalloc->unmap_buffer(base, size, hnd->offset_metadata);
-            if (err) {
-                ALOGE("Could not unmap memory at address %p", base);
-            }
+    IMemAlloc* memalloc = getAllocator(hnd->flags) ;
+    if(!memalloc)
+        return err;
+
+    if(hnd->base) {
+        err = memalloc->unmap_buffer((void*)hnd->base, hnd->size, hnd->offset);
+        if (err) {
+            ALOGE("Could not unmap memory at address %p, %s", hnd->base,
+                    strerror(errno));
+            return -errno;
         }
+        hnd->base = 0;
     }
-    /* need to initialize the pointer to NULL otherwise unmapping for that
-     * buffer happens twice which leads to crash */
-    hnd->base = 0;
-    hnd->base_metadata = 0;
+
+    if(hnd->base_metadata) {
+        unsigned int size = ROUND_UP_PAGESIZE(sizeof(MetaData_t));
+        err = memalloc->unmap_buffer((void*)hnd->base_metadata,
+                size, hnd->offset_metadata);
+        if (err) {
+            ALOGE("Could not unmap memory at address %p, %s",
+                    hnd->base_metadata, strerror(errno));
+            return -errno;
+        }
+        hnd->base_metadata = 0;
+    }
+
     return 0;
 }
 
@@ -146,8 +153,6 @@
     if (!module || private_handle_t::validate(handle) < 0)
         return -EINVAL;
 
-    // In this implementation, we don't need to do anything here
-
     /* NOTE: we need to initialize the buffer as not mapped/not locked
      * because it shouldn't when this function is called the first time
      * in a new process. Ideally these flags shouldn't be part of the
@@ -155,9 +160,6 @@
      * out-of-line
      */
 
-    private_handle_t* hnd = (private_handle_t*)handle;
-    hnd->base = 0;
-    hnd->base_metadata = 0;
     int err = gralloc_map(module, handle);
     if (err) {
         ALOGE("%s: gralloc_map failed", __FUNCTION__);
@@ -178,16 +180,9 @@
      * 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.
      * NOTE: the framebuffer is handled differently and is never unmapped.
+     * Also base and base_metadata are reset.
      */
-
-    private_handle_t* hnd = (private_handle_t*)handle;
-
-    if (hnd->base != 0) {
-        gralloc_unmap(module, handle);
-    }
-    hnd->base = 0;
-    hnd->base_metadata = 0;
-    return 0;
+    return gralloc_unmap(module, handle);
 }
 
 int terminateBuffer(gralloc_module_t const* module,
@@ -200,20 +195,10 @@
     /*
      * 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.
+     * NOTE: the framebuffer is handled differently and is never unmapped.
+     * Also base and base_metadata are reset.
      */
-
-    if (hnd->base != 0) {
-        // this buffer was mapped, unmap it now
-        if (hnd->flags & private_handle_t::PRIV_FLAGS_USES_ION) {
-                gralloc_unmap(module, hnd);
-        } else {
-            ALOGE("terminateBuffer: unmapping a non pmem/ashmem buffer flags = 0x%x",
-                  hnd->flags);
-            gralloc_unmap(module, hnd);
-        }
-    }
-
-    return 0;
+    return gralloc_unmap(module, hnd);
 }
 
 static int gralloc_map_and_invalidate (gralloc_module_t const* module,
@@ -457,6 +442,15 @@
                 res = 0;
             } break;
 
+        case GRALLOC_MODULE_PERFORM_GET_RGB_DATA_ADDRESS:
+            {
+                private_handle_t* hnd = va_arg(args, private_handle_t*);
+                void* rgb_data = va_arg(args, void*);
+                if (!private_handle_t::validate(hnd)) {
+                    res = getRgbDataAddress(hnd, rgb_data);
+                }
+            } break;
+
         default:
             break;
     }
diff --git a/libhwcomposer/hwc.cpp b/libhwcomposer/hwc.cpp
index 1fa40ce..c51efba 100644
--- a/libhwcomposer/hwc.cpp
+++ b/libhwcomposer/hwc.cpp
@@ -281,13 +281,15 @@
     hwc_context_t* ctx = (hwc_context_t*)(dev);
     const int dpy = HWC_DISPLAY_PRIMARY;
     bool fbComp = false;
-
+    static int compStart = false;
     if (!ctx->mBootAnimCompleted)
         processBootAnimCompleted(ctx);
-    if (LIKELY(list && list->numHwLayers > 1) && ctx->dpyAttr[dpy].connected &&
-            (ctx->dpyAttr[dpy].isActive ||
+    if (LIKELY(list && (list->numHwLayers > 1 ||
+                    (ctx->mMDP.version < qdutils::MDP_V4_0 && compStart))) &&
+        ctx->dpyAttr[dpy].connected && (ctx->dpyAttr[dpy].isActive ||
              ctx->mHDMIDisplay->isHDMIPrimaryDisplay())
             && !ctx->dpyAttr[dpy].isPause) {
+        compStart = true;
 
         // When HDMI is primary we should rely on the first valid
         // draw call in order to activate the display
diff --git a/libhwcomposer/hwc_copybit.cpp b/libhwcomposer/hwc_copybit.cpp
index e223ff4..00bd643 100644
--- a/libhwcomposer/hwc_copybit.cpp
+++ b/libhwcomposer/hwc_copybit.cpp
@@ -174,11 +174,20 @@
     //dirty rect for same layer at least equal of number of
     //framebuffers
 
-    if ( updatingLayerCount ==  1 ) {
-       hwc_rect_t dirtyRect = list->hwLayers[changingLayerIndex].displayFrame;
+    if ( updatingLayerCount <=  1 ) {
+        hwc_rect_t dirtyRect;
+        if (updatingLayerCount == 0) {
+            dirtyRect.left = INVALID_DIMENSION;
+            dirtyRect.top = INVALID_DIMENSION;
+            dirtyRect.right = INVALID_DIMENSION;
+            dirtyRect.bottom = INVALID_DIMENSION;
+            changingLayerIndex = NO_UPDATING_LAYER;
+        } else {
+            dirtyRect = list->hwLayers[changingLayerIndex].displayFrame;
 #ifdef QCOM_BSP
-       dirtyRect = list->hwLayers[changingLayerIndex].dirtyRect;
+            dirtyRect = list->hwLayers[changingLayerIndex].dirtyRect;
 #endif
+        }
 
        for (int k = ctx->listStats[dpy].numAppLayers-1; k >= 0 ; k--) {
            //disable swap rect in case of scaling and video .
@@ -553,11 +562,13 @@
     mDirtyLayerIndex =  checkDirtyRect(ctx, list, dpy);
     ALOGD_IF (DEBUG_COPYBIT, "%s:Dirty Layer Index: %d",
                                        __FUNCTION__, mDirtyLayerIndex);
+
     hwc_rect_t clearRegion = {0,0,0,0};
     mDirtyRect = list->hwLayers[last].displayFrame;
 
-    if (CBUtils::getuiClearRegion(list, clearRegion, layerProp,
-                                                       mDirtyLayerIndex)) {
+    if (mDirtyLayerIndex != NO_UPDATING_LAYER &&
+            CBUtils::getuiClearRegion(list, clearRegion, layerProp,
+                                                    mDirtyLayerIndex)) {
        int clear_w =  clearRegion.right -  clearRegion.left;
        int clear_h =  clearRegion.bottom - clearRegion.top;
        //mdp can't handle solid fill for one line
@@ -569,8 +580,13 @@
        }else
            clear(renderBuffer, clearRegion);
     }
-    if (mDirtyLayerIndex != -1)
-           mDirtyRect = list->hwLayers[mDirtyLayerIndex].displayFrame;
+    if (mDirtyLayerIndex != -1) {
+        if (mDirtyLayerIndex == NO_UPDATING_LAYER) {
+            mDirtyRect = clearRegion;
+        } else {
+            mDirtyRect = list->hwLayers[mDirtyLayerIndex].displayFrame;
+        }
+    }
 
     // numAppLayers-1, as we iterate from 0th layer index with HWC_COPYBIT flag
     for (int i = 0; i <= (ctx->listStats[dpy].numAppLayers-1); i++) {
diff --git a/libhwcomposer/hwc_copybit.h b/libhwcomposer/hwc_copybit.h
index 4223aa0..993c790 100644
--- a/libhwcomposer/hwc_copybit.h
+++ b/libhwcomposer/hwc_copybit.h
@@ -28,6 +28,8 @@
 #define MAX_SCALE_FACTOR 16
 #define MIN_SCALE_FACTOR 0.0625
 #define MAX_LAYERS_FOR_ABC 2
+#define INVALID_DIMENSION -1
+#define NO_UPDATING_LAYER -2
 namespace qhwc {
 
 class CopyBit {
diff --git a/libhwcomposer/hwc_mdpcomp.cpp b/libhwcomposer/hwc_mdpcomp.cpp
index 5bd7931..e2c4677 100644
--- a/libhwcomposer/hwc_mdpcomp.cpp
+++ b/libhwcomposer/hwc_mdpcomp.cpp
@@ -55,6 +55,7 @@
 int (*MDPComp::sPerfLockAcquire)(int, int, int*, int) = NULL;
 int (*MDPComp::sPerfLockRelease)(int value) = NULL;
 int MDPComp::sPerfHintWindow = -1;
+float MDPComp::sDownscaleThreshold = 1.0;
 
 enum AllocOrder { FORMAT_YUV, FORMAT_RGB, FORMAT_MAX };
 
@@ -212,6 +213,10 @@
         }
     }
 
+    if(property_get("persist.hwc.downscale_threshold", property, "1.0") > 0) {
+        sDownscaleThreshold = (float)atof(property);
+    }
+
     return true;
 }
 
@@ -430,6 +435,24 @@
         //More conditions here, sRGB+Blend etc
         return false;
     }
+
+    //In targets with fewer pipes, frequent composition switch between MDP/GPU
+    //can happen for a layer due to lack of pipes. When this switch happens
+    //continuously for RGB downscaled layer with downscale greater than
+    //threshold, it appears as flicker as output
+    //of MDP and GPU are different as they use different filters for downscale.
+    //To avoid this flicker, punt RGB downscaled layer with downscale greater
+    //than threshold value to GPU always.
+    if((sDownscaleThreshold > 1.0)) {
+        if(((not isYuvBuffer(hnd))
+                and (not isDownscaleWithinThreshold(layer,
+                        sDownscaleThreshold)))) {
+            ALOGD_IF(isDebug(), "%s: required downscale is greater than \
+                    threshold %f", __FUNCTION__, sDownscaleThreshold);
+            return false;
+        }
+    }
+
     return true;
 }
 
diff --git a/libhwcomposer/hwc_mdpcomp.h b/libhwcomposer/hwc_mdpcomp.h
index db68e82..5c43aa7 100644
--- a/libhwcomposer/hwc_mdpcomp.h
+++ b/libhwcomposer/hwc_mdpcomp.h
@@ -283,6 +283,7 @@
     static int (*sPerfLockAcquire)(int, int, int*, int);
     static int (*sPerfLockRelease)(int value);
     static int sPerfHintWindow;
+    static float sDownscaleThreshold;
 
 };
 
diff --git a/libhwcomposer/hwc_utils.cpp b/libhwcomposer/hwc_utils.cpp
index aeda428..79235ff 100644
--- a/libhwcomposer/hwc_utils.cpp
+++ b/libhwcomposer/hwc_utils.cpp
@@ -972,6 +972,27 @@
 
     return false;
 }
+
+bool isDownscaleWithinThreshold(hwc_layer_1_t const* layer, float threshold) {
+    hwc_rect_t displayFrame  = layer->displayFrame;
+    hwc_rect_t sourceCrop = integerizeSourceCrop(layer->sourceCropf);
+    int dst_w, dst_h, src_w, src_h;
+    float downscale = 1.0;
+    dst_w = displayFrame.right - displayFrame.left;
+    dst_h = displayFrame.bottom - displayFrame.top;
+    src_w = sourceCrop.right - sourceCrop.left;
+    src_h = sourceCrop.bottom - sourceCrop.top;
+    if(dst_w && dst_h) {
+        float w_scale = ((float)src_w / (float)dst_w);
+        float h_scale = ((float)src_h / (float)dst_h);
+
+        if((w_scale > threshold) or (h_scale > threshold))
+            return false;
+    }
+
+    return true;
+}
+
 bool needsScaling(hwc_layer_1_t const* layer) {
     int dst_w, dst_h, src_w, src_h;
     hwc_rect_t displayFrame  = layer->displayFrame;
diff --git a/libhwcomposer/hwc_utils.h b/libhwcomposer/hwc_utils.h
index da0182b..4849baf 100644
--- a/libhwcomposer/hwc_utils.h
+++ b/libhwcomposer/hwc_utils.h
@@ -309,6 +309,7 @@
 bool isAlphaScaled(hwc_layer_1_t const* layer);
 bool needsScaling(hwc_layer_1_t const* layer);
 bool isDownscaleRequired(hwc_layer_1_t const* layer);
+bool isDownscaleWithinThreshold(hwc_layer_1_t const* layer, float threshold);
 bool needsScalingWithSplit(hwc_context_t* ctx, hwc_layer_1_t const* layer,
                            const int& dpy);
 void sanitizeSourceCrop(hwc_rect_t& cropL, hwc_rect_t& cropR,
diff --git a/liboverlay/overlay.cpp b/liboverlay/overlay.cpp
index 113bd48..da24382 100644
--- a/liboverlay/overlay.cpp
+++ b/liboverlay/overlay.cpp
@@ -153,8 +153,6 @@
         return getPipe_8x52(pipeSpecs);
     } else if(MDPVersion::getInstance().is8994()) {
         return getPipe_8994(pipeSpecs);
-    } else if(MDPVersion::getInstance().is8992()) {
-        return getPipe_8992(pipeSpecs);
     }
 
     eDest dest = OV_INVALID;
@@ -261,13 +259,6 @@
     //supported since we at least need 1 round in between where the DMA is
     //unused
     eDest dest = OV_INVALID;
-
-    // Reset format type to FORMAT_NONE to select the pipe irrespective of the
-    // format specifed by the client. This is required for the device where
-    // SMP starvation is unlikely, we need not keep track of formats
-    // programmed in the pipes to avoid potential pipe crunching.
-    resetPipeBookFormat(pipeSpecs.dpy);
-
     if(pipeSpecs.formatClass == FORMAT_YUV) {
         return nextPipe(OV_MDP_PIPE_VG, pipeSpecs);
     } else {
@@ -279,14 +270,9 @@
             dest = nextPipe(OV_MDP_PIPE_DMA, pipeSpecs);
         }
     }
-
     return dest;
 }
 
-utils::eDest Overlay::getPipe_8992(const PipeSpecs& pipeSpecs) {
-    return getPipe_8994(pipeSpecs);
-}
-
 void Overlay::endAllSessions() {
     for(int i = 0; i < PipeBook::NUM_PIPES; i++) {
         if(mPipeBook[i].valid() && mPipeBook[i].mSession==PipeBook::START)
diff --git a/liboverlay/overlay.h b/liboverlay/overlay.h
index 2782fc2..affb4db 100644
--- a/liboverlay/overlay.h
+++ b/liboverlay/overlay.h
@@ -179,9 +179,6 @@
     utils::eDest getPipe_8x39(const PipeSpecs& pipeSpecs);
     utils::eDest getPipe_8x52(const PipeSpecs& pipeSpecs);
     utils::eDest getPipe_8994(const PipeSpecs& pipeSpecs);
-    utils::eDest getPipe_8992(const PipeSpecs& pipeSpecs);
-
-    void resetPipeBookFormat(const int &dpy);
 
     /* Returns the handle to libscale.so's programScale function */
     static int (*getFnProgramScale())(struct mdp_overlay_list *);
@@ -448,14 +445,6 @@
     return "Invalid";
 }
 
-inline void Overlay::resetPipeBookFormat(const int &dpy) {
-    for(int i = 0; i < PipeBook::NUM_PIPES; i++) {
-        if (mPipeBook[i].mDisplay == dpy) {
-            mPipeBook[i].mFormatType = FORMAT_NONE;
-        }
-    }
-}
-
 }; // overlay
 
 #endif // OVERLAY_H
diff --git a/liboverlay/overlayMdp.cpp b/liboverlay/overlayMdp.cpp
index 828f4fc..95bdc23 100644
--- a/liboverlay/overlayMdp.cpp
+++ b/liboverlay/overlayMdp.cpp
@@ -399,7 +399,7 @@
     int errVal = mdp_wrapper::validateAndSet(fbFd, list);
     if(errVal) {
         /* No dump for failure due to insufficient resource */
-        if(errVal != E2BIG) {
+        if(errVal != E2BIG && errVal != EBADSLT) {
             //ENODEV is returned when the driver cannot satisfy a pipe request.
             //This could happen if previous round's UNSET hasn't been commited
             //yet, either because of a missed vsync or because of difference in