Merge "sde: Change the secure buffer alignment requirement"
diff --git a/displayengine/include/core/display_interface.h b/displayengine/include/core/display_interface.h
index c041e1a..3042eb2 100644
--- a/displayengine/include/core/display_interface.h
+++ b/displayengine/include/core/display_interface.h
@@ -95,13 +95,13 @@
   uint32_t y_pixels;          //!< Total number of pixels in Y-direction on the display panel.
   float x_dpi;                //!< Dots per inch in X-direction.
   float y_dpi;                //!< Dots per inch in Y-direction.
-  float fps;                  //!< Frame rate per second.
+  uint32_t fps;               //!< Frame rate per second.
   uint32_t vsync_period_ns;   //!< VSync period in nanoseconds.
-  uint32_t v_total;           //!< Total lines in Y-direction (vActive + vFP + vBP + vPulseWidth).
+  uint32_t v_total;           //!< Total height of panel (vActive + vFP + vBP + vPulseWidth).
   uint32_t h_total;           //!< Total width of panel (hActive + hFP + hBP + hPulseWidth).
 
   DisplayConfigVariableInfo() : x_pixels(0), y_pixels(0), x_dpi(0.0f), y_dpi(0.0f),
-                               fps(0.0f), vsync_period_ns(0), v_total(0), h_total(0) { }
+                                fps(0), vsync_period_ns(0), v_total(0), h_total(0) { }
 };
 
 /*! @brief Event data associated with VSync event.
@@ -334,6 +334,27 @@
   */
   virtual DisplayError SetDisplayMode(uint32_t mode) = 0;
 
+  /*! @brief Method to determine whether scaling for a custom resolution is valid.
+
+    @return \link DisplayError \endlink
+  */
+  virtual DisplayError IsScalingValid(const LayerRect &crop, const LayerRect &dst,
+                                      bool rotate90) = 0;
+
+  /*! @brief Method to set the refresh rate of a display.
+
+    @param[in] new refresh rate of the display.
+
+    @return \link DisplayError \endlink
+  */
+  virtual DisplayError SetRefreshRate(uint32_t refresh_rate) = 0;
+
+  /*! @brief Method to query whether scanning is support for the HDMI display.
+
+    @return \link DisplayError \endlink
+  */
+  virtual bool IsUnderscanSupported() = 0;
+
  protected:
   virtual ~DisplayInterface() { }
 };
diff --git a/displayengine/include/private/hw_info_types.h b/displayengine/include/private/hw_info_types.h
index 1740615..03a77ae 100644
--- a/displayengine/include/private/hw_info_types.h
+++ b/displayengine/include/private/hw_info_types.h
@@ -106,6 +106,24 @@
   kPortEDP,
 };
 
+/*! @brief This enumeration holds the all possible scan types. */
+enum HWScanSupport {
+  kScanNotSupported,
+  kScanAlwaysOverscanned,
+  kScanAlwaysUnderscanned,
+  kScanBoth,
+};
+
+/*! @brief This structure holds the scan support for different timing modes. */
+struct HWScanInfo {
+  HWScanSupport pt_scan_support;  //!< Scan support for preferred timing
+  HWScanSupport it_scan_support;  //!< Scan support for digital monitor or industry timings
+  HWScanSupport cea_scan_support; //!< Scan support for CEA resolution timings
+
+  HWScanInfo() : pt_scan_support(kScanNotSupported), it_scan_support(kScanNotSupported),
+                 cea_scan_support(kScanNotSupported) { }
+};
+
 /*! @brief This structure describes the split configuration of a display panel. */
 struct HWSplitInfo {
   uint32_t left_split;
@@ -113,6 +131,15 @@
   bool always_src_split;
 
   HWSplitInfo() : left_split(0), right_split(0), always_src_split(false) { }
+
+  bool operator !=(const HWSplitInfo &split_info) {
+    return ((left_split != split_info.left_split) || (right_split != split_info.right_split) ||
+            (always_src_split != split_info.always_src_split));
+  }
+
+  bool operator ==(const HWSplitInfo &split_info) {
+    return !(operator !=(split_info));
+  }
 };
 
 /*! @brief This structure describes properties of a display panel. */
@@ -136,6 +163,23 @@
   HWPanelInfo() : port(kPortDefault), mode(kModeDefault), partial_update(false), left_align(false),
     width_align(false), top_align(false), height_align(false), min_roi_width(0), min_roi_height(0),
     needs_roi_merge(false), dynamic_fps(false), min_fps(0), max_fps(0) { }
+
+  bool operator !=(const HWPanelInfo &panel_info) {
+    return ((port != panel_info.port) || (mode != panel_info.mode) ||
+            (partial_update != panel_info.partial_update) ||
+            (left_align != panel_info.left_align) || (width_align != panel_info.width_align) ||
+            (top_align != panel_info.top_align) || (height_align != panel_info.height_align) ||
+            (min_roi_width != panel_info.min_roi_width) ||
+            (min_roi_height != panel_info.min_roi_height) ||
+            (needs_roi_merge != panel_info.needs_roi_merge) ||
+            (dynamic_fps != panel_info.dynamic_fps) || (min_fps != panel_info.min_fps) ||
+            (max_fps != panel_info.max_fps) || (is_primary_panel != panel_info.is_primary_panel) ||
+            (split_info != panel_info.split_info));
+  }
+
+  bool operator ==(const HWPanelInfo &panel_info) {
+    return !(operator !=(panel_info));
+  }
 };
 
 }  // namespace sde
diff --git a/displayengine/include/private/strategy_interface.h b/displayengine/include/private/strategy_interface.h
index df01c7f..a0a52f8 100644
--- a/displayengine/include/private/strategy_interface.h
+++ b/displayengine/include/private/strategy_interface.h
@@ -96,7 +96,7 @@
   @return \link DisplayError \endlink
 */
 typedef DisplayError (*CreateStrategyInterface)(uint16_t version, DisplayType type,
-                      const HWResourceInfo *hw_resource_info, const HWPanelInfo *hw_panel_info,
+                      const HWResourceInfo &hw_resource_info, const HWPanelInfo &hw_panel_info,
                       StrategyInterface **interface);
 
 /*! @brief Function to destroy composer strategy interface.
diff --git a/displayengine/include/utils/debug.h b/displayengine/include/utils/debug.h
index 2cef5d7..1dbf0c3 100644
--- a/displayengine/include/utils/debug.h
+++ b/displayengine/include/utils/debug.h
@@ -65,7 +65,7 @@
   static uint32_t GetIdleTimeoutMs();
   static bool IsRotatorDownScaleDisabled();
   static bool IsDecimationDisabled();
-  static bool IsPartialUpdate();
+  static bool IsPartialUpdateEnabled();
 
  private:
   Debug();
diff --git a/displayengine/libs/core/comp_manager.cpp b/displayengine/libs/core/comp_manager.cpp
index 82f7b8d..fa02e94 100644
--- a/displayengine/libs/core/comp_manager.cpp
+++ b/displayengine/libs/core/comp_manager.cpp
@@ -107,7 +107,7 @@
     return kErrorMemory;
   }
 
-  if (create_strategy_intf_(STRATEGY_VERSION_TAG, type, &hw_res_info_, &hw_panel_info,
+  if (create_strategy_intf_(STRATEGY_VERSION_TAG, type, hw_res_info_, hw_panel_info,
                             &display_comp_ctx->strategy_intf) != kErrorNone) {
     DLOGW("Unable to create strategy interface");
     delete display_comp_ctx;
@@ -165,6 +165,16 @@
   return kErrorNone;
 }
 
+void CompManager::ReconfigureDisplay(Handle comp_handle, const HWDisplayAttributes &attributes,
+                                     const HWPanelInfo &hw_panel_info) {
+  DisplayCompositionContext *display_comp_ctx =
+                             reinterpret_cast<DisplayCompositionContext *>(comp_handle);
+
+  res_mgr_.ReconfigureDisplay(display_comp_ctx->display_resource_ctx, attributes, hw_panel_info);
+
+  // TODO(user): Need to reconfigure strategy with updated panel info
+}
+
 void CompManager::PrepareStrategyConstraints(Handle comp_handle, HWLayers *hw_layers) {
   DisplayCompositionContext *display_comp_ctx =
                              reinterpret_cast<DisplayCompositionContext *>(comp_handle);
@@ -351,5 +361,10 @@
   SCOPE_LOCK(locker_);
 }
 
+DisplayError CompManager::ValidateScaling(const LayerRect &crop, const LayerRect &dst,
+                                          bool rotate90) {
+  return res_mgr_.ValidateScaling(crop, dst, rotate90);
+}
+
 }  // namespace sde
 
diff --git a/displayengine/libs/core/comp_manager.h b/displayengine/libs/core/comp_manager.h
index ae638e0..88f4b3e 100644
--- a/displayengine/libs/core/comp_manager.h
+++ b/displayengine/libs/core/comp_manager.h
@@ -41,6 +41,8 @@
   DisplayError RegisterDisplay(DisplayType type, const HWDisplayAttributes &attributes,
                                const HWPanelInfo &hw_panel_info, Handle *res_mgr_hnd);
   DisplayError UnregisterDisplay(Handle res_mgr_hnd);
+  void ReconfigureDisplay(Handle display_ctx, const HWDisplayAttributes &attributes,
+                          const HWPanelInfo &hw_panel_info);
   void PrePrepare(Handle display_ctx, HWLayers *hw_layers);
   DisplayError Prepare(Handle display_ctx, HWLayers *hw_layers);
   DisplayError PostPrepare(Handle display_ctx, HWLayers *hw_layers);
@@ -49,6 +51,7 @@
   bool ProcessIdleTimeout(Handle display_ctx);
   void ProcessThermalEvent(Handle display_ctx, int64_t thermal_level);
   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);
diff --git a/displayengine/libs/core/display_base.cpp b/displayengine/libs/core/display_base.cpp
index 47beac0..b64eae7 100644
--- a/displayengine/libs/core/display_base.cpp
+++ b/displayengine/libs/core/display_base.cpp
@@ -41,7 +41,7 @@
     buffer_sync_handler_(buffer_sync_handler), comp_manager_(comp_manager),
     rotator_ctrl_(rotator_ctrl), state_(kStateOff), hw_device_(0), display_comp_ctx_(0),
     display_attributes_(NULL), num_modes_(0), active_mode_index_(0), pending_commit_(false),
-    vsync_enable_(false) {
+    vsync_enable_(false), underscan_supported_(false) {
 }
 
 DisplayError DisplayBase::Init() {
@@ -290,6 +290,10 @@
   return kErrorNone;
 }
 
+bool DisplayBase::IsUnderscanSupported() {
+  return underscan_supported_;
+}
+
 DisplayError DisplayBase::SetDisplayState(DisplayState state) {
   DisplayError error = kErrorNone;
 
@@ -339,36 +343,6 @@
   return error;
 }
 
-DisplayError DisplayBase::SetActiveConfig(DisplayConfigVariableInfo *variable_info) {
-  DisplayError error = kErrorNone;
-
-  if (!variable_info) {
-    return kErrorParameters;
-  }
-
-  HWDisplayAttributes display_attributes = display_attributes_[active_mode_index_];
-
-  display_attributes.x_pixels = variable_info->x_pixels;
-  display_attributes.y_pixels = variable_info->y_pixels;
-  display_attributes.fps = variable_info->fps;
-
-  // if display is already connected, unregister display from composition manager and register
-  // the display with new configuration.
-  if (display_comp_ctx_) {
-    comp_manager_->UnregisterDisplay(display_comp_ctx_);
-  }
-
-  error = comp_manager_->RegisterDisplay(display_type_, display_attributes, hw_panel_info_,
-                                         &display_comp_ctx_);
-  if (error != kErrorNone) {
-    return error;
-  }
-
-  display_attributes_[active_mode_index_] = display_attributes;
-
-  return kErrorNone;
-}
-
 DisplayError DisplayBase::SetActiveConfig(uint32_t index) {
   DisplayError error = kErrorNone;
 
@@ -407,6 +381,11 @@
   return kErrorNotSupported;
 }
 
+DisplayError DisplayBase::IsScalingValid(const LayerRect &crop, const LayerRect &dst,
+                                         bool rotate90) {
+  return comp_manager_->ValidateScaling(crop, dst, rotate90);
+}
+
 void DisplayBase::AppendDump(char *buffer, uint32_t length) {
   DumpImpl::AppendString(buffer, length, "\n-----------------------");
   DumpImpl::AppendString(buffer, length, "\ndevice type: %u", display_type_);
diff --git a/displayengine/libs/core/display_base.h b/displayengine/libs/core/display_base.h
index 0a33011..ef1ea1f 100644
--- a/displayengine/libs/core/display_base.h
+++ b/displayengine/libs/core/display_base.h
@@ -55,10 +55,11 @@
   virtual DisplayError GetActiveConfig(uint32_t *index);
   virtual DisplayError GetVSyncState(bool *enabled);
   virtual DisplayError SetDisplayState(DisplayState state);
-  virtual DisplayError SetActiveConfig(DisplayConfigVariableInfo *variable_info);
   virtual DisplayError SetActiveConfig(uint32_t index);
   virtual DisplayError SetMaxMixerStages(uint32_t max_mixer_stages);
   virtual DisplayError SetDisplayMode(uint32_t mode);
+  virtual DisplayError IsScalingValid(const LayerRect &crop, const LayerRect &dst, bool rotate90);
+  virtual bool IsUnderscanSupported();
 
  protected:
   // DumpImpl method
@@ -87,6 +88,7 @@
   HWLayers hw_layers_;
   bool pending_commit_;
   bool vsync_enable_;
+  bool underscan_supported_;
 };
 
 }  // namespace sde
diff --git a/displayengine/libs/core/display_hdmi.cpp b/displayengine/libs/core/display_hdmi.cpp
index 65ea21f..a36f2f2 100644
--- a/displayengine/libs/core/display_hdmi.cpp
+++ b/displayengine/libs/core/display_hdmi.cpp
@@ -60,6 +60,9 @@
     HWHDMIInterface::Destroy(hw_hdmi_intf_);
   }
 
+  GetScanSupport();
+  underscan_supported_ = (scan_support_ == kScanAlwaysUnderscanned) || (scan_support_ == kScanBoth);
+
   return error;
 }
 
@@ -127,7 +130,7 @@
 
 DisplayError DisplayHDMI::SetActiveConfig(DisplayConfigVariableInfo *variable_info) {
   SCOPE_LOCK(locker_);
-  return DisplayBase::SetActiveConfig(variable_info);
+  return kErrorNotSupported;
 }
 
 DisplayError DisplayHDMI::SetActiveConfig(uint32_t index) {
@@ -152,6 +155,22 @@
   return DisplayBase::SetDisplayMode(mode);
 }
 
+DisplayError DisplayHDMI::IsScalingValid(const LayerRect &crop, const LayerRect &dst,
+                                         bool rotate90) {
+  SCOPE_LOCK(locker_);
+  return DisplayBase::IsScalingValid(crop, dst, rotate90);
+}
+
+DisplayError DisplayHDMI::SetRefreshRate(uint32_t refresh_rate) {
+  SCOPE_LOCK(locker_);
+  return kErrorNotSupported;
+}
+
+bool DisplayHDMI::IsUnderscanSupported() {
+  SCOPE_LOCK(locker_);
+  return DisplayBase::IsUnderscanSupported();
+}
+
 int DisplayHDMI::GetBestConfig() {
   uint32_t best_config_mode = 0;
   HWDisplayAttributes *best = &display_attributes_[0];
@@ -193,6 +212,36 @@
   return best_config_mode;
 }
 
+void DisplayHDMI::GetScanSupport() {
+  DisplayError error = kErrorNone;
+  uint32_t video_format = -1;
+  uint32_t max_cea_format = -1;
+  HWScanInfo scan_info = HWScanInfo();
+  hw_hdmi_intf_->GetHWScanInfo(&scan_info);
+
+  error = hw_hdmi_intf_->GetVideoFormat(active_mode_index_, &video_format);
+  if (error != kErrorNone) {
+    return;
+  }
+
+  error = hw_hdmi_intf_->GetMaxCEAFormat(&max_cea_format);
+  if (error != kErrorNone) {
+    return;
+  }
+
+  // The scan support for a given HDMI TV must be read from scan info corresponding to
+  // Preferred Timing if the preferred timing of the display is currently active, and if it is
+  // valid. In all other cases, we must read the scan support from CEA scan info if
+  // the resolution is a CEA resolution, or from IT scan info for all other resolutions.
+  if (active_mode_index_ == 0 && scan_info.pt_scan_support != kScanNotSupported) {
+    scan_support_ = scan_info.pt_scan_support;
+  } else if (video_format < max_cea_format) {
+    scan_support_ = scan_info.cea_scan_support;
+  } else {
+    scan_support_ = scan_info.it_scan_support;
+  }
+}
+
 void DisplayHDMI::AppendDump(char *buffer, uint32_t length) {
   SCOPE_LOCK(locker_);
   DisplayBase::AppendDump(buffer, length);
diff --git a/displayengine/libs/core/display_hdmi.h b/displayengine/libs/core/display_hdmi.h
index ea1b80c..b5a25cc 100644
--- a/displayengine/libs/core/display_hdmi.h
+++ b/displayengine/libs/core/display_hdmi.h
@@ -56,14 +56,19 @@
   virtual void SetIdleTimeoutMs(uint32_t timeout_ms);
   virtual DisplayError SetMaxMixerStages(uint32_t max_mixer_stages);
   virtual DisplayError SetDisplayMode(uint32_t mode);
+  virtual DisplayError IsScalingValid(const LayerRect &crop, const LayerRect &dst, bool rotate90);
+  virtual DisplayError SetRefreshRate(uint32_t refresh_rate);
+  virtual bool IsUnderscanSupported();
   virtual void AppendDump(char *buffer, uint32_t length);
 
  private:
   virtual int GetBestConfig();
+  virtual void GetScanSupport();
 
   Locker locker_;
   HWHDMIInterface *hw_hdmi_intf_;
   HWInfoInterface *hw_info_intf_;
+  HWScanSupport scan_support_;
 };
 
 }  // namespace sde
diff --git a/displayengine/libs/core/display_primary.cpp b/displayengine/libs/core/display_primary.cpp
index 0fa5d2b..faea0da 100644
--- a/displayengine/libs/core/display_primary.cpp
+++ b/displayengine/libs/core/display_primary.cpp
@@ -88,14 +88,25 @@
 DisplayError DisplayPrimary::Commit(LayerStack *layer_stack) {
   SCOPE_LOCK(locker_);
   DisplayError error = kErrorNone;
+  HWPanelInfo panel_info;
+  HWDisplayAttributes display_attributes;
 
   error = DisplayBase::Commit(layer_stack);
   if (error != kErrorNone) {
     return error;
   }
 
-  hw_primary_intf_->GetHWPanelInfo(&hw_panel_info_);
-  // TODO(user): Update panel info in composition manager and resource manager
+  hw_primary_intf_->GetHWPanelInfo(&panel_info);
+
+  hw_primary_intf_->GetDisplayAttributes(&display_attributes, active_mode_index_);
+
+  if (panel_info != hw_panel_info_ ||
+      display_attributes != display_attributes_[active_mode_index_]) {
+    comp_manager_->ReconfigureDisplay(display_comp_ctx_, display_attributes, panel_info);
+
+    hw_panel_info_ = panel_info;
+    display_attributes_[active_mode_index_] = display_attributes;
+  }
 
   return error;
 }
@@ -135,6 +146,11 @@
   return DisplayBase::GetVSyncState(enabled);
 }
 
+bool DisplayPrimary::IsUnderscanSupported() {
+  SCOPE_LOCK(locker_);
+  return DisplayBase::IsUnderscanSupported();
+}
+
 DisplayError DisplayPrimary::SetDisplayState(DisplayState state) {
   SCOPE_LOCK(locker_);
   return DisplayBase::SetDisplayState(state);
@@ -142,7 +158,7 @@
 
 DisplayError DisplayPrimary::SetActiveConfig(DisplayConfigVariableInfo *variable_info) {
   SCOPE_LOCK(locker_);
-  return DisplayBase::SetActiveConfig(variable_info);
+  return kErrorNotSupported;
 }
 
 DisplayError DisplayPrimary::SetActiveConfig(uint32_t index) {
@@ -214,13 +230,37 @@
   return error;
 }
 
+DisplayError DisplayPrimary::IsScalingValid(const LayerRect &crop, const LayerRect &dst,
+                                            bool rotate90) {
+  SCOPE_LOCK(locker_);
+  return DisplayBase::IsScalingValid(crop, dst, rotate90);
+}
+
+DisplayError DisplayPrimary::SetRefreshRate(uint32_t refresh_rate) {
+  SCOPE_LOCK(locker_);
+
+  DisplayError error = kErrorNone;
+
+  if (!hw_panel_info_.dynamic_fps) {
+    DLOGW("Dynamic fps feature is not supported");
+    return kErrorNotSupported;
+  }
+
+  if (refresh_rate > hw_panel_info_.max_fps) {
+    refresh_rate = hw_panel_info_.max_fps;
+  } else if (refresh_rate < hw_panel_info_.min_fps) {
+    refresh_rate = hw_panel_info_.min_fps;
+  }
+
+  return hw_primary_intf_->SetRefreshRate(refresh_rate);
+}
+
 void DisplayPrimary::AppendDump(char *buffer, uint32_t length) {
   SCOPE_LOCK(locker_);
   DisplayBase::AppendDump(buffer, length);
 }
 
 DisplayError DisplayPrimary::VSync(int64_t timestamp) {
-  SCOPE_LOCK(locker_);
   if (vsync_enable_) {
     DisplayEventVSync vsync;
     vsync.timestamp = timestamp;
diff --git a/displayengine/libs/core/display_primary.h b/displayengine/libs/core/display_primary.h
index 1ed28b2..11f9687 100644
--- a/displayengine/libs/core/display_primary.h
+++ b/displayengine/libs/core/display_primary.h
@@ -56,6 +56,9 @@
   virtual void SetIdleTimeoutMs(uint32_t timeout_ms);
   virtual DisplayError SetMaxMixerStages(uint32_t max_mixer_stages);
   virtual DisplayError SetDisplayMode(uint32_t mode);
+  virtual DisplayError IsScalingValid(const LayerRect &crop, const LayerRect &dst, bool rotate90);
+  virtual DisplayError SetRefreshRate(uint32_t refresh_rate);
+  virtual bool IsUnderscanSupported();
   virtual void AppendDump(char *buffer, uint32_t length);
 
   // Implement the HWEventHandlers
diff --git a/displayengine/libs/core/display_virtual.cpp b/displayengine/libs/core/display_virtual.cpp
index 5480f0e..30588dc 100644
--- a/displayengine/libs/core/display_virtual.cpp
+++ b/displayengine/libs/core/display_virtual.cpp
@@ -120,6 +120,11 @@
   return DisplayBase::GetVSyncState(enabled);
 }
 
+bool DisplayVirtual::IsUnderscanSupported() {
+  SCOPE_LOCK(locker_);
+  return DisplayBase::IsUnderscanSupported();
+}
+
 DisplayError DisplayVirtual::SetDisplayState(DisplayState state) {
   SCOPE_LOCK(locker_);
   return DisplayBase::SetDisplayState(state);
@@ -127,7 +132,33 @@
 
 DisplayError DisplayVirtual::SetActiveConfig(DisplayConfigVariableInfo *variable_info) {
   SCOPE_LOCK(locker_);
-  return DisplayBase::SetActiveConfig(variable_info);
+  DisplayError error = kErrorNone;
+
+  if (!variable_info) {
+    return kErrorParameters;
+  }
+
+  HWDisplayAttributes display_attributes = display_attributes_[active_mode_index_];
+
+  display_attributes.x_pixels = variable_info->x_pixels;
+  display_attributes.y_pixels = variable_info->y_pixels;
+  display_attributes.fps = variable_info->fps;
+
+  // if display is already connected, unregister display from composition manager and register
+  // the display with new configuration.
+  if (display_comp_ctx_) {
+    comp_manager_->UnregisterDisplay(display_comp_ctx_);
+  }
+
+  error = comp_manager_->RegisterDisplay(display_type_, display_attributes, hw_panel_info_,
+                                         &display_comp_ctx_);
+  if (error != kErrorNone) {
+    return error;
+  }
+
+  display_attributes_[active_mode_index_] = display_attributes;
+
+  return error;
 }
 
 DisplayError DisplayVirtual::SetActiveConfig(uint32_t index) {
@@ -152,6 +183,17 @@
   return DisplayBase::SetDisplayMode(mode);
 }
 
+DisplayError DisplayVirtual::IsScalingValid(const LayerRect &crop, const LayerRect &dst,
+                                            bool rotate90) {
+  SCOPE_LOCK(locker_);
+  return DisplayBase::IsScalingValid(crop, dst, rotate90);
+}
+
+DisplayError DisplayVirtual::SetRefreshRate(uint32_t refresh_rate) {
+  SCOPE_LOCK(locker_);
+  return kErrorNotSupported;
+}
+
 void DisplayVirtual::AppendDump(char *buffer, uint32_t length) {
   SCOPE_LOCK(locker_);
   DisplayBase::AppendDump(buffer, length);
diff --git a/displayengine/libs/core/display_virtual.h b/displayengine/libs/core/display_virtual.h
index f868612..6350e26 100644
--- a/displayengine/libs/core/display_virtual.h
+++ b/displayengine/libs/core/display_virtual.h
@@ -56,6 +56,9 @@
   virtual void SetIdleTimeoutMs(uint32_t timeout_ms);
   virtual DisplayError SetMaxMixerStages(uint32_t max_mixer_stages);
   virtual DisplayError SetDisplayMode(uint32_t mode);
+  virtual DisplayError IsScalingValid(const LayerRect &crop, const LayerRect &dst, bool rotate90);
+  virtual DisplayError SetRefreshRate(uint32_t refresh_rate);
+  virtual bool IsUnderscanSupported();
   virtual void AppendDump(char *buffer, uint32_t length);
 
  private:
diff --git a/displayengine/libs/core/fb/hw_device.cpp b/displayengine/libs/core/fb/hw_device.cpp
index d96820f..809e817 100644
--- a/displayengine/libs/core/fb/hw_device.cpp
+++ b/displayengine/libs/core/fb/hw_device.cpp
@@ -194,7 +194,6 @@
   DTRACE_SCOPED();
 
   DisplayError error = kErrorNone;
-  ResetDisplayParams();
 
   HWLayersInfo &hw_layer_info = hw_layers->info;
   LayerStack *stack = hw_layer_info.stack;
@@ -206,6 +205,12 @@
   mdp_layer_commit_v1 &mdp_commit = mdp_disp_commit_.commit_v1;
   uint32_t &mdp_layer_count = mdp_commit.input_layer_cnt;
 
+  DLOGI("left_roi: x = %d, y = %d, w = %d, h = %d", mdp_commit.left_roi.x, mdp_commit.left_roi.y,
+                                                    mdp_commit.left_roi.w, mdp_commit.left_roi.h);
+  DLOGI("right_roi: x = %d, y = %d, w = %d, h = %d", mdp_commit.right_roi.x,
+                                                     mdp_commit.right_roi.y, mdp_commit.right_roi.w,
+                                                     mdp_commit.right_roi.h);
+
   for (uint32_t i = 0; i < hw_layer_info.count; i++) {
     uint32_t layer_index = hw_layer_info.index[i];
     Layer &layer = stack->layers[layer_index];
diff --git a/displayengine/libs/core/fb/hw_device.h b/displayengine/libs/core/fb/hw_device.h
index 18c6652..e25709e 100644
--- a/displayengine/libs/core/fb/hw_device.h
+++ b/displayengine/libs/core/fb/hw_device.h
@@ -29,7 +29,6 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <linux/msm_mdp_ext.h>
-#include <video/msm_hdmi_modes.h>
 #include <linux/mdss_rotator.h>
 #include <poll.h>
 #include <pthread.h>
diff --git a/displayengine/libs/core/fb/hw_hdmi.cpp b/displayengine/libs/core/fb/hw_hdmi.cpp
index d258df3..f8279b2 100644
--- a/displayengine/libs/core/fb/hw_hdmi.cpp
+++ b/displayengine/libs/core/fb/hw_hdmi.cpp
@@ -105,7 +105,7 @@
 }
 
 HWHDMI::HWHDMI(BufferSyncHandler *buffer_sync_handler,  HWInfoInterface *hw_info_intf)
-  : HWDevice(buffer_sync_handler) {
+  : HWDevice(buffer_sync_handler), hw_scan_info_() {
   HWDevice::device_type_ = kDeviceHDMI;
   HWDevice::device_name_ = "HDMI Display Device";
   HWDevice::hw_info_intf_ = hw_info_intf;
@@ -129,6 +129,7 @@
   MSM_HDMI_MODES_INIT_TIMINGS(supported_video_modes_);
   MSM_HDMI_MODES_SET_SUPP_TIMINGS(supported_video_modes_, MSM_HDMI_MODES_ALL);
 
+  ReadScanInfo();
   return kErrorNone;
 
 CleanupOnError:
@@ -227,7 +228,7 @@
   display_attributes->h_total = timing_mode->active_h + h_blanking;
   display_attributes->x_dpi = 0;
   display_attributes->y_dpi = 0;
-  display_attributes->fps = FLOAT(timing_mode->refresh_rate) / 1000.0f;
+  display_attributes->fps = timing_mode->refresh_rate / 1000;
   display_attributes->vsync_period_ns = UINT32(1000000000L / display_attributes->fps);
   display_attributes->split_left = display_attributes->x_pixels;
   if (display_attributes->x_pixels > hw_resource_.max_mixer_width) {
@@ -325,6 +326,7 @@
 }
 
 DisplayError HWHDMI::Validate(HWLayers *hw_layers) {
+  HWDevice::ResetDisplayParams();
   return HWDevice::Validate(hw_layers);
 }
 
@@ -340,5 +342,80 @@
   return HWDevice::GetHWPanelInfo(panel_info);
 }
 
+DisplayError HWHDMI::GetHWScanInfo(HWScanInfo *scan_info) {
+  if (!scan_info) {
+    return kErrorParameters;
+  }
+  *scan_info = hw_scan_info_;
+  return kErrorNone;
+}
+
+DisplayError HWHDMI::GetVideoFormat(uint32_t config_index, uint32_t *video_format) {
+  *video_format = hdmi_modes_[config_index];
+
+  return kErrorNone;
+}
+
+DisplayError HWHDMI::GetMaxCEAFormat(uint32_t *max_cea_format) {
+  *max_cea_format = HDMI_VFRMT_END;
+
+  return kErrorNone;
+}
+
+HWScanSupport HWHDMI::MapHWScanSupport(uint32_t value) {
+  switch (value) {
+  // TODO(user): Read the scan type from driver defined values instead of hardcoding
+  case 0:
+    return kScanNotSupported;
+  case 1:
+    return kScanAlwaysOverscanned;
+  case 2:
+    return kScanAlwaysUnderscanned;
+  case 3:
+    return kScanBoth;
+  default:
+    return kScanNotSupported;
+    break;
+  }
+}
+
+void HWHDMI::ReadScanInfo() {
+  int scan_info_file = -1;
+  ssize_t len = -1;
+  char data[PAGE_SIZE] = {'\0'};
+
+  snprintf(data, sizeof(data), "%s%d/scan_info", fb_path_, fb_node_index_);
+  scan_info_file = open_(data, O_RDONLY);
+  if (scan_info_file < 0) {
+    DLOGW("File '%s' not found.", data);
+    return;
+  }
+
+  memset(&data[0], 0, sizeof(data));
+  len = read(scan_info_file, data, sizeof(data) - 1);
+  if (len <= 0) {
+    close_(scan_info_file);
+    DLOGW("File %s%d/scan_info is empty.", fb_path_, fb_node_index_);
+    return;
+  }
+  data[len] = '\0';
+  close_(scan_info_file);
+
+  const uint32_t scan_info_max_count = 3;
+  uint32_t scan_info_count = 0;
+  char *tokens[scan_info_max_count] = { NULL };
+  ParseLine(data, tokens, scan_info_max_count, &scan_info_count);
+  if (scan_info_count != scan_info_max_count) {
+    DLOGW("Failed to parse scan info string %s", data);
+    return;
+  }
+
+  hw_scan_info_.pt_scan_support = MapHWScanSupport(atoi(tokens[0]));
+  hw_scan_info_.it_scan_support = MapHWScanSupport(atoi(tokens[1]));
+  hw_scan_info_.cea_scan_support = MapHWScanSupport(atoi(tokens[2]));
+  DLOGI("PT %d IT %d CEA %d", hw_scan_info_.pt_scan_support, hw_scan_info_.it_scan_support,
+        hw_scan_info_.cea_scan_support);
+}
+
 }  // namespace sde
 
diff --git a/displayengine/libs/core/fb/hw_hdmi.h b/displayengine/libs/core/fb/hw_hdmi.h
index 322e664..adfa1e2 100644
--- a/displayengine/libs/core/fb/hw_hdmi.h
+++ b/displayengine/libs/core/fb/hw_hdmi.h
@@ -25,6 +25,7 @@
 #ifndef __HW_HDMI_H__
 #define __HW_HDMI_H__
 
+#include <video/msm_hdmi_modes.h>
 #include "hw_device.h"
 #include "hw_hdmi_interface.h"
 
@@ -41,6 +42,9 @@
   virtual DisplayError GetDisplayAttributes(HWDisplayAttributes *display_attributes,
                                             uint32_t index);
   virtual DisplayError GetHWPanelInfo(HWPanelInfo *panel_info);
+  virtual DisplayError GetHWScanInfo(HWScanInfo *scan_info);
+  virtual DisplayError GetVideoFormat(uint32_t config_index, uint32_t *video_format);
+  virtual DisplayError GetMaxCEAFormat(uint32_t *max_cea_format);
   virtual DisplayError SetDisplayAttributes(uint32_t index);
   virtual DisplayError GetConfigIndex(uint32_t mode, uint32_t *index);
   virtual DisplayError PowerOn();
@@ -54,11 +58,14 @@
 
  private:
   int GetHDMIModeCount();
+  void ReadScanInfo();
+  HWScanSupport MapHWScanSupport(uint32_t value);
 
   uint32_t hdmi_mode_count_;
   uint32_t hdmi_modes_[256];
   // Holds the hdmi timing information. Ex: resolution, fps etc.,
   msm_hdmi_mode_timing_info *supported_video_modes_;
+  HWScanInfo hw_scan_info_;
 };
 
 }  // namespace sde
diff --git a/displayengine/libs/core/fb/hw_primary.cpp b/displayengine/libs/core/fb/hw_primary.cpp
index 87de5d4..1fa4b4e 100644
--- a/displayengine/libs/core/fb/hw_primary.cpp
+++ b/displayengine/libs/core/fb/hw_primary.cpp
@@ -65,7 +65,7 @@
 
 HWPrimary::HWPrimary(BufferSyncHandler *buffer_sync_handler, HWInfoInterface *hw_info_intf)
   : HWDevice(buffer_sync_handler), event_thread_name_("SDE_EventThread"), fake_vsync_(false),
-    exit_threads_(false) {
+    exit_threads_(false), config_changed_(true) {
   HWDevice::device_type_ = kDevicePrimary;
   HWDevice::device_name_ = "Primary Display Device";
   HWDevice::hw_info_intf_ = hw_info_intf;
@@ -163,6 +163,21 @@
 
 DisplayError HWPrimary::GetDisplayAttributes(HWDisplayAttributes *display_attributes,
                                              uint32_t index) {
+  if (!display_attributes) {
+    return kErrorParameters;
+  }
+
+  if (config_changed_) {
+    PopulateDisplayAttributes();
+    config_changed_ = false;
+  }
+
+  *display_attributes = display_attributes_;
+
+  return kErrorNone;
+}
+
+DisplayError HWPrimary::PopulateDisplayAttributes() {
   DTRACE_SCOPED();
 
   // Variable screen info
@@ -187,25 +202,26 @@
     var_screeninfo.height = INT(((FLOAT(var_screeninfo.yres) * 25.4f)/160.0f) + 0.5f);
   }
 
-  display_attributes->x_pixels = var_screeninfo.xres;
-  display_attributes->y_pixels = var_screeninfo.yres;
-  display_attributes->v_total = var_screeninfo.yres + var_screeninfo.lower_margin +
+  display_attributes_.x_pixels = var_screeninfo.xres;
+  display_attributes_.y_pixels = var_screeninfo.yres;
+  display_attributes_.v_total = var_screeninfo.yres + var_screeninfo.lower_margin +
       var_screeninfo.upper_margin + var_screeninfo.vsync_len;
   uint32_t h_blanking = var_screeninfo.right_margin + var_screeninfo.left_margin +
       var_screeninfo.hsync_len;
-  display_attributes->h_total = var_screeninfo.xres + h_blanking;
-  display_attributes->x_dpi =
+  display_attributes_.h_total = var_screeninfo.xres + var_screeninfo.right_margin +
+      var_screeninfo.left_margin + var_screeninfo.hsync_len;
+  display_attributes_.x_dpi =
       (FLOAT(var_screeninfo.xres) * 25.4f) / FLOAT(var_screeninfo.width);
-  display_attributes->y_dpi =
+  display_attributes_.y_dpi =
       (FLOAT(var_screeninfo.yres) * 25.4f) / FLOAT(var_screeninfo.height);
-  display_attributes->fps = FLOAT(meta_data.data.panel_frame_rate);
-  display_attributes->vsync_period_ns = UINT32(1000000000L / display_attributes->fps);
-  display_attributes->is_device_split = (hw_panel_info_.split_info.left_split ||
+  display_attributes_.fps = meta_data.data.panel_frame_rate;
+  display_attributes_.vsync_period_ns = UINT32(1000000000L / display_attributes_.fps);
+  display_attributes_.is_device_split = (hw_panel_info_.split_info.left_split ||
       (var_screeninfo.xres > hw_resource_.max_mixer_width)) ? true : false;
-  display_attributes->split_left = hw_panel_info_.split_info.left_split ?
-      hw_panel_info_.split_info.left_split : display_attributes->x_pixels / 2;
-  display_attributes->always_src_split = hw_panel_info_.split_info.always_src_split;
-  display_attributes->h_total += display_attributes->is_device_split ? h_blanking : 0;
+  display_attributes_.split_left = hw_panel_info_.split_info.left_split ?
+      hw_panel_info_.split_info.left_split : display_attributes_.x_pixels / 2;
+  display_attributes_.always_src_split = hw_panel_info_.split_info.always_src_split;
+  display_attributes_.h_total += display_attributes_.is_device_split ? h_blanking : 0;
 
   return kErrorNone;
 }
@@ -214,6 +230,35 @@
   return HWDevice::SetDisplayAttributes(index);
 }
 
+DisplayError HWPrimary::SetRefreshRate(uint32_t refresh_rate) {
+  char node_path[kMaxStringLength] = {0};
+
+  DLOGI("Setting refresh rate to = %d fps", refresh_rate);
+
+  snprintf(node_path, sizeof(node_path), "%s%d/dynamic_fps", fb_path_, fb_node_index_);
+
+  int fd = open_(node_path, O_WRONLY);
+  if (fd < 0) {
+    DLOGE("Failed to open %s with error %s", node_path, strerror(errno));
+    return kErrorFileDescriptor;
+  }
+
+  char refresh_rate_string[kMaxStringLength];
+  snprintf(refresh_rate_string, sizeof(refresh_rate_string), "%d", refresh_rate);
+  ssize_t len = pwrite_(fd, refresh_rate_string, strlen(refresh_rate_string), 0);
+  if (len < 0) {
+    DLOGE("Failed to write %d with error %s", refresh_rate, strerror(errno));
+    close_(fd);
+    return kErrorUndefined;
+  }
+  close_(fd);
+
+  config_changed_ = true;
+  synchronous_commit_ = true;
+
+  return kErrorNone;
+}
+
 DisplayError HWPrimary::GetConfigIndex(uint32_t mode, uint32_t *index) {
   return HWDevice::GetConfigIndex(mode, index);
 }
@@ -254,6 +299,27 @@
 }
 
 DisplayError HWPrimary::Validate(HWLayers *hw_layers) {
+  HWDevice::ResetDisplayParams();
+
+  mdp_layer_commit_v1 &mdp_commit = mdp_disp_commit_.commit_v1;
+
+  LayerRect left_roi = hw_layers->info.left_partial_update;
+  LayerRect right_roi = hw_layers->info.right_partial_update;
+  mdp_commit.left_roi.x = INT(left_roi.left);
+  mdp_commit.left_roi.y = INT(left_roi.top);
+  mdp_commit.left_roi.w = INT(left_roi.right - left_roi.left);
+  mdp_commit.left_roi.h = INT(left_roi.bottom - left_roi.top);
+
+  // SDE treats ROI as one full coordinate system.
+  // In case source split is disabled, However, Driver assumes Mixer to operate in
+  // different co-ordinate system.
+  if (!hw_resource_.is_src_split) {
+    mdp_commit.right_roi.x = INT(right_roi.left) - hw_panel_info_.split_info.left_split;
+    mdp_commit.right_roi.y = INT(right_roi.top);
+    mdp_commit.right_roi.w = INT(right_roi.right - right_roi.left);
+    mdp_commit.right_roi.h = INT(right_roi.bottom - right_roi.top);
+  }
+
   return HWDevice::Validate(hw_layers);
 }
 
@@ -357,7 +423,7 @@
     thermal_level = strtoull(data + strlen("thermal_level="), NULL, 0);
   }
 
-  DLOGI("Received thermal notification with thermal level = %d",thermal_level);
+  DLOGI("Received thermal notification with thermal level = %d", thermal_level);
 
   event_handler_->ThermalEvent(thermal_level);
 }
diff --git a/displayengine/libs/core/fb/hw_primary.h b/displayengine/libs/core/fb/hw_primary.h
index c41f387..fdf27b3 100644
--- a/displayengine/libs/core/fb/hw_primary.h
+++ b/displayengine/libs/core/fb/hw_primary.h
@@ -54,6 +54,7 @@
   virtual void SetIdleTimeoutMs(uint32_t timeout_ms);
   virtual DisplayError SetVSyncState(bool enable);
   virtual DisplayError SetDisplayMode(const HWDisplayMode hw_display_mode);
+  virtual DisplayError SetRefreshRate(uint32_t refresh_rate);
 
  private:
   // Panel modes for the MSMFB_LPM_ENABLE ioctl
@@ -70,12 +71,15 @@
   void HandleBlank(char *data);
   void HandleIdleTimeout(char *data);
   void HandleThermal(char *data);
+  DisplayError PopulateDisplayAttributes();
 
   pollfd poll_fds_[kNumDisplayEvents];
   pthread_t event_thread_;
   const char *event_thread_name_;
   bool fake_vsync_;
   bool exit_threads_;
+  HWDisplayAttributes display_attributes_;
+  bool config_changed_;
 };
 
 }  // namespace sde
diff --git a/displayengine/libs/core/fb/hw_rotator.cpp b/displayengine/libs/core/fb/hw_rotator.cpp
index c698445..99b6a2e 100644
--- a/displayengine/libs/core/fb/hw_rotator.cpp
+++ b/displayengine/libs/core/fb/hw_rotator.cpp
@@ -264,7 +264,7 @@
   }
 }
 
- void HWRotator::SetMDPFlags(const Layer &layer, uint32_t *mdp_flags) {
+void HWRotator::SetMDPFlags(const Layer &layer, uint32_t *mdp_flags) {
   LayerTransform transform = layer.transform;
   bool rot90 = (transform.rotation == 90.0f);
 
diff --git a/displayengine/libs/core/fb/hw_virtual.cpp b/displayengine/libs/core/fb/hw_virtual.cpp
index 374cc45..f108cfa 100644
--- a/displayengine/libs/core/fb/hw_virtual.cpp
+++ b/displayengine/libs/core/fb/hw_virtual.cpp
@@ -119,6 +119,7 @@
 }
 
 DisplayError HWVirtual::Validate(HWLayers *hw_layers) {
+  HWDevice::ResetDisplayParams();
   return HWDevice::Validate(hw_layers);
 }
 
diff --git a/displayengine/libs/core/hw_hdmi_interface.h b/displayengine/libs/core/hw_hdmi_interface.h
index 36ca991..276fefd 100644
--- a/displayengine/libs/core/hw_hdmi_interface.h
+++ b/displayengine/libs/core/hw_hdmi_interface.h
@@ -36,6 +36,9 @@
   static DisplayError Create(HWHDMIInterface **intf, HWInfoInterface *hw_info_intf,
                              BufferSyncHandler *buffer_sync_handler);
   static DisplayError Destroy(HWHDMIInterface *intf);
+  virtual DisplayError GetHWScanInfo(HWScanInfo *scan_info) = 0;
+  virtual DisplayError GetVideoFormat(uint32_t config_index, uint32_t *video_format) = 0;
+  virtual DisplayError GetMaxCEAFormat(uint32_t *max_cea_format) = 0;
 
  protected:
   virtual ~HWHDMIInterface() { }
diff --git a/displayengine/libs/core/hw_interface.h b/displayengine/libs/core/hw_interface.h
index 5610ccd..0c8288f 100644
--- a/displayengine/libs/core/hw_interface.h
+++ b/displayengine/libs/core/hw_interface.h
@@ -174,6 +174,19 @@
   HWDisplayAttributes() : is_device_split(false), split_left(0), always_src_split(false) { }
 
   void Reset() { *this = HWDisplayAttributes(); }
+
+  bool operator !=(const HWDisplayAttributes &attributes) {
+    return ((is_device_split != attributes.is_device_split) ||
+            (split_left != attributes.split_left) ||
+            (always_src_split != attributes.always_src_split) ||
+            (x_pixels != attributes.x_pixels) || (y_pixels != attributes.y_pixels) ||
+            (x_dpi != attributes.x_dpi) || (y_dpi != attributes.y_dpi) || (fps != attributes.fps) ||
+            (vsync_period_ns != attributes.vsync_period_ns) || (v_total != attributes.v_total));
+  }
+
+  bool operator ==(const HWDisplayAttributes &attributes) {
+    return !(operator !=(attributes));
+  }
 };
 
 // HWEventHandler - Implemented in DisplayBase and HWInterface implementation
diff --git a/displayengine/libs/core/hw_primary_interface.h b/displayengine/libs/core/hw_primary_interface.h
index d195348..edc1795 100644
--- a/displayengine/libs/core/hw_primary_interface.h
+++ b/displayengine/libs/core/hw_primary_interface.h
@@ -38,6 +38,7 @@
   virtual DisplayError SetVSyncState(bool enable) = 0;
   virtual void SetIdleTimeoutMs(uint32_t timeout_ms) = 0;
   virtual DisplayError SetDisplayMode(const HWDisplayMode hw_display_mode) = 0;
+  virtual DisplayError SetRefreshRate(uint32_t refresh_rate) = 0;
 
  protected:
   virtual ~HWPrimaryInterface() { }
diff --git a/displayengine/libs/core/res_config.cpp b/displayengine/libs/core/res_config.cpp
index c5a8a06..a8f9017 100644
--- a/displayengine/libs/core/res_config.cpp
+++ b/displayengine/libs/core/res_config.cpp
@@ -142,31 +142,39 @@
 DisplayError ResManager::DisplaySplitConfig(DisplayResourceContext *display_resource_ctx,
                                             const LayerTransform &transform,
                                             const LayerRect &src_rect, const LayerRect &dst_rect,
-                                            HWLayerConfig *layer_config, uint32_t align_x) {
+                                            const HWLayers &hw_layers, HWLayerConfig *layer_config,
+                                            uint32_t align_x) {
   LayerRect scissor_dst_left, scissor_dst_right;
   HWDisplayAttributes &display_attributes = display_resource_ctx->display_attributes;
 
   // for display split case
   HWPipeInfo *left_pipe = &layer_config->left_pipe;
   HWPipeInfo *right_pipe = &layer_config->right_pipe;
-  LayerRect scissor, dst_left, crop_left, crop_right, dst_right;
-  scissor.right = FLOAT(display_attributes.split_left);
-  scissor.bottom = FLOAT(display_attributes.y_pixels);
+  LayerRect scissor_left, scissor_right, dst_left, crop_left, crop_right, dst_right;
+
+  scissor_left.right = FLOAT(display_attributes.split_left);
+  scissor_left.bottom = FLOAT(display_attributes.y_pixels);
+
+  scissor_right.left = FLOAT(display_attributes.split_left);
+  scissor_right.top = 0.0f;
+  scissor_right.right = FLOAT(display_attributes.x_pixels);
+  scissor_right.bottom = FLOAT(display_attributes.y_pixels);
+
+  if (IsValid(hw_layers.info.left_partial_update) ||
+      IsValid(hw_layers.info.right_partial_update)) {
+    scissor_left = hw_layers.info.left_partial_update;
+    scissor_right = hw_layers.info.right_partial_update;
+  }
 
   crop_left = src_rect;
   dst_left = dst_rect;
   crop_right = crop_left;
   dst_right = dst_left;
-  bool crop_left_valid = CalculateCropRects(scissor, transform, &crop_left, &dst_left);
-
-  scissor.left = FLOAT(display_attributes.split_left);
-  scissor.top = 0.0f;
-  scissor.right = FLOAT(display_attributes.x_pixels);
-  scissor.bottom = FLOAT(display_attributes.y_pixels);
+  bool crop_left_valid = CalculateCropRects(scissor_left, transform, &crop_left, &dst_left);
   bool crop_right_valid = false;
 
-  if (IsValid(scissor)) {
-    crop_right_valid = CalculateCropRects(scissor, transform, &crop_right, &dst_right);
+  if (IsValid(scissor_right)) {
+    crop_right_valid = CalculateCropRects(scissor_right, transform, &crop_right, &dst_right);
   }
 
   if (crop_left_valid && (crop_left.right - crop_left.left) > hw_res_info_.max_pipe_width) {
@@ -248,6 +256,10 @@
     scissor.right = FLOAT(display_attributes.x_pixels);
     scissor.bottom = FLOAT(display_attributes.y_pixels);
 
+    if (IsValid(hw_layers->info.left_partial_update)) {
+      scissor = hw_layers->info.left_partial_update;
+    }
+
     struct HWLayerConfig *layer_config = &hw_layers->config[i];
     HWPipeInfo &left_pipe = layer_config->left_pipe;
     HWPipeInfo &right_pipe = layer_config->right_pipe;
@@ -295,19 +307,21 @@
       transform = LayerTransform();
     }
 
+    // TODO(user): need to revisit this logic
     if (hw_res_info_.is_src_split) {
-      error = SrcSplitConfig(display_resource_ctx, transform, src_rect,
-                             dst_rect, layer_config, align_x);
+      error = SrcSplitConfig(display_resource_ctx, transform, src_rect, dst_rect, layer_config,
+                             align_x);
     } else {
-      error = DisplaySplitConfig(display_resource_ctx, transform, src_rect,
-                                 dst_rect, layer_config, align_x);
+      error = DisplaySplitConfig(display_resource_ctx, transform, src_rect, dst_rect, *hw_layers,
+                                 layer_config, align_x);
     }
 
     if (error != kErrorNone) {
       break;
     }
 
-    error = AlignPipeConfig(layer, transform, &left_pipe, &right_pipe, align_x, align_y);
+    error = AlignPipeConfig(layer, transform, *hw_layers, &left_pipe, &right_pipe, align_x,
+                            align_y);
     if (error != kErrorNone) {
       break;
     }
@@ -742,8 +756,9 @@
 }
 
 DisplayError ResManager::AlignPipeConfig(const Layer &layer, const LayerTransform &transform,
-                                         HWPipeInfo *left_pipe, HWPipeInfo *right_pipe,
-                                         uint32_t align_x, uint32_t align_y) {
+                                         const HWLayers &hw_layers, HWPipeInfo *left_pipe,
+                                         HWPipeInfo *right_pipe, uint32_t align_x,
+                                         uint32_t align_y) {
   DisplayError error = kErrorNone;
   if (!left_pipe->valid) {
     DLOGE_IF(kTagResources, "left_pipe should not be invalid");
@@ -753,7 +768,6 @@
   //    rectangle of video layer to be even.
   // 2. Normalize source and destination rect of a layer to multiple of 1.
   // TODO(user) Check buffer format and check if rotate is involved.
-
   Normalize(align_x, align_y, &left_pipe->src_roi);
   Normalize(1, 1, &left_pipe->dst_roi);
 
@@ -762,8 +776,10 @@
     Normalize(1, 1, &right_pipe->dst_roi);
   }
 
-  if (right_pipe->valid) {
-    // Make sure the  left and right ROI are conjunct
+  // Make sure the  left and right ROI are conjunct, then make pipes ROI conjunct.
+  if (right_pipe->valid &&
+      (!IsValid(hw_layers.info.right_partial_update) ||
+      (hw_layers.info.left_partial_update.right == hw_layers.info.right_partial_update.left))) {
     if (transform.flip_horizontal) {
       left_pipe->src_roi.left = right_pipe->src_roi.right;
     } else {
diff --git a/displayengine/libs/core/res_manager.cpp b/displayengine/libs/core/res_manager.cpp
index 7344c21..b5b8db1 100644
--- a/displayengine/libs/core/res_manager.cpp
+++ b/displayengine/libs/core/res_manager.cpp
@@ -197,6 +197,17 @@
   return kErrorNone;
 }
 
+void ResManager::ReconfigureDisplay(Handle display_ctx, const HWDisplayAttributes &attributes,
+                                    const HWPanelInfo &hw_panel_info) {
+  SCOPE_LOCK(locker_);
+
+  DisplayResourceContext *display_resource_ctx =
+                          reinterpret_cast<DisplayResourceContext *>(display_ctx);
+
+  display_resource_ctx->display_attributes = attributes;
+  display_resource_ctx->hw_panel_info_ = hw_panel_info;
+}
+
 DisplayError ResManager::Start(Handle display_ctx) {
   locker_.Lock();
 
@@ -492,7 +503,7 @@
   float decimation = powf(2.0f, pipe->vertical_decimation);
   src_h /= decimation;
 
-  float bw = src_w * src_h * bpp * display_attributes.fps;
+  float bw = src_w * src_h * bpp * FLOAT(display_attributes.fps);
 
   // Consider panel dimension
   // (v_total / v_active) * (v_active / dst_h)
@@ -522,7 +533,7 @@
 float ResManager::GetClockForPipe(DisplayResourceContext *display_ctx, HWPipeInfo *pipe) {
   HWDisplayAttributes &display_attributes = display_ctx->display_attributes;
   float v_total = FLOAT(display_attributes.v_total);
-  float fps = display_attributes.fps;
+  float fps = FLOAT(display_attributes.fps);
 
   float src_h = pipe->src_roi.bottom - pipe->src_roi.top;
   float dst_h = pipe->dst_roi.bottom - pipe->dst_roi.top;
@@ -619,6 +630,8 @@
     case kFormatXRGB8888:
     case kFormatRGBX8888:
     case kFormatBGRX8888:
+    case kFormatRGBA8888Ubwc:
+    case kFormatRGBX8888Ubwc:
       return 4.0f;
     case kFormatRGB888:
     case kFormatBGR888:
@@ -626,6 +639,7 @@
     case kFormatRGB565:
     case kFormatRGBA5551:
     case kFormatRGBA4444:
+    case kFormatRGB565Ubwc:
     case kFormatYCbCr422H2V1Packed:
     case kFormatYCrCb422H2V1SemiPlanar:
     case kFormatYCrCb422H1V2SemiPlanar:
diff --git a/displayengine/libs/core/res_manager.h b/displayengine/libs/core/res_manager.h
index 32eb6ea..1f8f48e 100644
--- a/displayengine/libs/core/res_manager.h
+++ b/displayengine/libs/core/res_manager.h
@@ -43,6 +43,8 @@
   DisplayError RegisterDisplay(DisplayType type, const HWDisplayAttributes &attributes,
                                const HWPanelInfo &hw_panel_info, Handle *display_ctx);
   DisplayError UnregisterDisplay(Handle display_ctx);
+  void ReconfigureDisplay(Handle display_ctx, const HWDisplayAttributes &attributes,
+                          const HWPanelInfo &hw_panel_info);
   DisplayError Start(Handle display_ctx);
   DisplayError Stop(Handle display_ctx);
   DisplayError Acquire(Handle display_ctx, HWLayers *hw_layers);
@@ -162,9 +164,12 @@
   DisplayError Config(DisplayResourceContext *display_resource_ctx, HWLayers *hw_layers,
                       uint32_t *rotate_count);
   DisplayError DisplaySplitConfig(DisplayResourceContext *display_resource_ctx,
-                                  const LayerTransform &transform, const LayerRect &src_rect,
-                                  const LayerRect &dst_rect, HWLayerConfig *layer_config,
+                                  const LayerTransform &transform,
+                                  const LayerRect &src_rect, const LayerRect &dst_rect,
+                                  const HWLayers &hw_layers, 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,
@@ -208,8 +213,8 @@
                               const bool &rot90, const bool &downscale,
                               LayerBufferFormat *output_format);
   DisplayError AlignPipeConfig(const Layer &layer, const LayerTransform &transform,
-                               HWPipeInfo *left_pipe, HWPipeInfo *right_pipe,
-                               uint32_t align_x, uint32_t align_y);
+                               const HWLayers &hw_layers, HWPipeInfo *left_pipe,
+                               HWPipeInfo *right_pipe, uint32_t align_x, uint32_t align_y);
   void ResourceStateLog(void);
   DisplayError CalculateDecimation(float downscale, uint8_t *decimation);
 
diff --git a/displayengine/libs/core/scalar_helper.h b/displayengine/libs/core/scalar_helper.h
old mode 100755
new mode 100644
diff --git a/displayengine/libs/core/strategy_default.cpp b/displayengine/libs/core/strategy_default.cpp
index 48fc79d..4aab34d 100644
--- a/displayengine/libs/core/strategy_default.cpp
+++ b/displayengine/libs/core/strategy_default.cpp
@@ -31,14 +31,17 @@
 
 namespace sde {
 
-StrategyDefault::StrategyDefault() : hw_layers_info_(NULL) {
+StrategyDefault::StrategyDefault(DisplayType type, const HWResourceInfo &hw_resource_info,
+                                 const HWPanelInfo &hw_panel_info) : type_(type),
+                                 hw_resource_info_(hw_resource_info),
+                                 hw_panel_info_(hw_panel_info), hw_layers_info_(NULL) {
 }
 
 DisplayError StrategyDefault::CreateStrategyInterface(uint16_t version, DisplayType type,
-                                                      const HWResourceInfo *hw_resource_info,
-                                                      const HWPanelInfo *hw_panel_info,
+                                                      const HWResourceInfo &hw_resource_info,
+                                                      const HWPanelInfo &hw_panel_info,
                                                       StrategyInterface **interface) {
-  StrategyDefault *strategy_default  = new StrategyDefault();
+  StrategyDefault *strategy_default  = new StrategyDefault(type, hw_resource_info, hw_panel_info);
 
   if (!strategy_default) {
     return kErrorMemory;
@@ -61,6 +64,18 @@
   return kErrorNone;
 }
 
+bool StrategyDefault::IsDisplaySplit(uint32_t fb_x_res) {
+  if (fb_x_res > hw_resource_info_.max_mixer_width) {
+    return true;
+  }
+
+  if ((type_ == kPrimary) && hw_panel_info_.split_info.right_split) {
+    return true;
+  }
+
+  return false;
+}
+
 DisplayError StrategyDefault::Start(HWLayersInfo *hw_layers_info, uint32_t *max_attempts) {
   if (!hw_layers_info) {
     return kErrorParameters;
@@ -69,6 +84,29 @@
   hw_layers_info_ = hw_layers_info;
   *max_attempts = 1;
 
+  const LayerStack *layer_stack = hw_layers_info_->stack;
+  for (uint32_t i = 0; i < layer_stack->layer_count; i++) {
+    LayerComposition &composition = layer_stack->layers[i].composition;
+    if (composition == kCompositionGPUTarget) {
+      fb_layer_index_ = i;
+      break;
+    }
+  }
+
+  const LayerRect &src_rect = hw_layers_info_->stack->layers[fb_layer_index_].src_rect;
+  // TODO(user): read panels x_pixels and y_pixels instead of fb_x_res and fb_y_res
+  const float fb_x_res = src_rect.right - src_rect.left;
+  const float fb_y_res = src_rect.bottom - src_rect.top;
+
+  if (IsDisplaySplit(INT(fb_x_res))) {
+    float left_split = FLOAT(hw_panel_info_.split_info.left_split);
+    hw_layers_info->left_partial_update = (LayerRect) {0.0, 0.0, left_split, fb_y_res};
+    hw_layers_info->right_partial_update = (LayerRect) {left_split, 0.0, fb_x_res, fb_y_res};
+  } else {
+    hw_layers_info->left_partial_update = (LayerRect) {0.0, 0.0, fb_x_res, fb_y_res};
+    hw_layers_info->right_partial_update = (LayerRect) {0.0, 0.0, 0.0, 0.0};
+  }
+
   return kErrorNone;
 }
 
diff --git a/displayengine/libs/core/strategy_default.h b/displayengine/libs/core/strategy_default.h
index 7b6f594..37d5f9d 100644
--- a/displayengine/libs/core/strategy_default.h
+++ b/displayengine/libs/core/strategy_default.h
@@ -32,11 +32,11 @@
 
 class StrategyDefault : public StrategyInterface {
  public:
-  StrategyDefault();
-
+  StrategyDefault(DisplayType type, const HWResourceInfo &hw_resource_info,
+                  const HWPanelInfo &hw_panel_info);
   static DisplayError CreateStrategyInterface(uint16_t version, DisplayType type,
-                                              const HWResourceInfo *hw_resource_info,
-                                              const HWPanelInfo *hw_panel_info,
+                                              const HWResourceInfo &hw_resource_info,
+                                              const HWPanelInfo &hw_panel_info,
                                               StrategyInterface **interface);
   static DisplayError DestroyStrategyInterface(StrategyInterface *interface);
 
@@ -45,7 +45,12 @@
   virtual DisplayError Stop();
 
  private:
+  bool IsDisplaySplit(uint32_t fb_x_res);
+  DisplayType type_;
+  HWResourceInfo hw_resource_info_;
+  HWPanelInfo hw_panel_info_;
   HWLayersInfo *hw_layers_info_;
+  int fb_layer_index_;
 };
 
 }  // namespace sde
diff --git a/displayengine/libs/hwc/hwc_display.cpp b/displayengine/libs/hwc/hwc_display.cpp
index 724b720..7794731 100644
--- a/displayengine/libs/hwc/hwc_display.cpp
+++ b/displayengine/libs/hwc/hwc_display.cpp
@@ -46,7 +46,8 @@
                        int id)
   : core_intf_(core_intf), hwc_procs_(hwc_procs), type_(type), id_(id), display_intf_(NULL),
     flush_(false), output_buffer_(NULL), dump_frame_count_(0), dump_frame_index_(0),
-    dump_input_layers_(false), swap_interval_zero_(false) {
+    dump_input_layers_(false), swap_interval_zero_(false), framebuffer_config_(NULL),
+    display_paused_(false), use_metadata_refresh_rate_(false),metadata_refresh_rate_(0) {
 }
 
 int HWCDisplay::Init() {
@@ -64,6 +65,13 @@
     }
   }
 
+  framebuffer_config_ = new DisplayConfigVariableInfo();
+  if (!framebuffer_config_) {
+    DLOGV("Failed to allocate memory for custom framebuffer config.");
+    core_intf_->DestroyDisplay(display_intf_);
+    return -EINVAL;
+  }
+
   return 0;
 }
 
@@ -79,6 +87,8 @@
     layer_stack_memory_.raw = NULL;
   }
 
+  delete framebuffer_config_;
+
   return 0;
 }
 
@@ -150,10 +160,15 @@
   DisplayError error = kErrorNone;
 
   DisplayConfigVariableInfo variable_config;
-  error = display_intf_->GetConfig(config, &variable_config);
-  if (error != kErrorNone) {
-    DLOGE("GetConfig variable info failed. Error = %d", error);
-    return -EINVAL;
+  uint32_t active_config = UINT32(GetActiveConfig());
+  if (IsFrameBufferScaled() && config == active_config) {
+    variable_config = *framebuffer_config_;
+  } else {
+    error = display_intf_->GetConfig(config, &variable_config);
+    if (error != kErrorNone) {
+      DLOGE("GetConfig variable info failed. Error = %d", error);
+      return -EINVAL;
+    }
   }
 
   for (int i = 0; attributes[i] != HWC_DISPLAY_NO_ATTRIBUTE; i++) {
@@ -327,6 +342,12 @@
     return 0;
   }
 
+  DisplayConfigVariableInfo active_config;
+  uint32_t active_config_index = 0;
+  display_intf_->GetActiveConfig(&active_config_index);
+
+  display_intf_->GetConfig(active_config_index, &active_config);
+
   // Configure each layer
   for (size_t i = 0; i < num_hw_layers; i++) {
     hwc_layer_1_t &hwc_layer = content_list->hwLayers[i];
@@ -352,11 +373,10 @@
         layer_buffer->flags.secure = true;
       }
 
-      // TODO(user) : Initialize it to display refresh rate
-      layer.frame_rate = 60;
+      layer.frame_rate = UINT32(active_config.fps);
       MetaData_t *meta_data = reinterpret_cast<MetaData_t *>(pvt_handle->base_metadata);
       if (meta_data && meta_data->operation & UPDATE_REFRESH_RATE) {
-        layer.frame_rate = meta_data->refreshrate;
+        layer.frame_rate = RoundToStandardFPS(meta_data->refreshrate);
       }
 
       if (meta_data && meta_data->operation == PP_PARAM_INTERLACED && meta_data->interlaced) {
@@ -368,7 +388,11 @@
       }
     }
 
-    SetRect(hwc_layer.displayFrame, &layer.dst_rect);
+    hwc_rect_t scaled_display_frame = hwc_layer.displayFrame;
+    ScaleDisplayFrame(&scaled_display_frame);
+    ApplyScanAdjustment(&scaled_display_frame);
+
+    SetRect(scaled_display_frame, &layer.dst_rect);
     SetRect(hwc_layer.sourceCropf, &layer.src_rect);
     for (size_t j = 0; j < hwc_layer.visibleRegionScreen.numRects; j++) {
         SetRect(hwc_layer.visibleRegionScreen.rects[j], &layer.visible_regions.rect[j]);
@@ -412,6 +436,8 @@
 
   bool needs_fb_refresh = NeedsFrameBufferRefresh(content_list);
 
+  metadata_refresh_rate_ = 0;
+
   for (size_t i = 0; i < num_hw_layers; i++) {
     hwc_layer_1_t &hwc_layer = content_list->hwLayers[i];
     Layer &layer = layer_stack_.layers[i];
@@ -419,6 +445,10 @@
 
     if (composition == kCompositionSDE) {
       hwc_layer.hints |= HWC_HINT_CLEAR_FB;
+
+      if (use_metadata_refresh_rate_ && layer.frame_rate > metadata_refresh_rate_) {
+        metadata_refresh_rate_ = layer.frame_rate;
+      }
     }
 
     // If current layer does not need frame buffer redraw, then mark it as HWC_OVERLAY
@@ -810,5 +840,169 @@
   }
 }
 
+int HWCDisplay::SetFrameBufferResolution(uint32_t x_pixels, uint32_t y_pixels) {
+  if (x_pixels <= 0 || y_pixels <= 0) {
+    DLOGV("Unsupported config: x_pixels=%d, y_pixels=%d", x_pixels, y_pixels);
+    return -EINVAL;
+  }
+
+  if (framebuffer_config_->x_pixels == x_pixels && framebuffer_config_->y_pixels == y_pixels) {
+    return 0;
+  }
+
+  DisplayConfigVariableInfo active_config;
+  int active_config_index = GetActiveConfig();
+  DisplayError error = display_intf_->GetConfig(active_config_index, &active_config);
+  if (error != kErrorNone) {
+    DLOGV("GetConfig variable info failed. Error = %d", error);
+    return -EINVAL;
+  }
+
+  if (active_config.x_pixels <= 0 || active_config.y_pixels <= 0) {
+    DLOGV("Invalid panel resolution (%dx%d)", active_config.x_pixels, active_config.y_pixels);
+    return -EINVAL;
+  }
+
+  // Create rects to represent the new source and destination crops
+  LayerRect crop = LayerRect(0, 0, FLOAT(x_pixels), FLOAT(y_pixels));
+  LayerRect dst = LayerRect(0, 0, FLOAT(active_config.x_pixels), FLOAT(active_config.y_pixels));
+  // Set rotate90 to false since this is taken care of during regular composition.
+  bool rotate90 = false;
+  error = display_intf_->IsScalingValid(crop, dst, rotate90);
+  if (error != kErrorNone) {
+    DLOGV("Unsupported resolution: (%dx%d)", x_pixels, y_pixels);
+    return -EINVAL;
+  }
+
+  uint32_t panel_width =
+          UINT32((FLOAT(active_config.x_pixels) * 25.4f) / FLOAT(active_config.x_dpi));
+  uint32_t panel_height =
+          UINT32((FLOAT(active_config.y_pixels) * 25.4f) / FLOAT(active_config.y_dpi));
+  framebuffer_config_->x_pixels = x_pixels;
+  framebuffer_config_->y_pixels = y_pixels;
+  framebuffer_config_->vsync_period_ns = active_config.vsync_period_ns;
+  framebuffer_config_->x_dpi =
+          (FLOAT(framebuffer_config_->x_pixels) * 25.4f) / FLOAT(panel_width);
+  framebuffer_config_->y_dpi =
+          (FLOAT(framebuffer_config_->y_pixels) * 25.4f) / FLOAT(panel_height);
+
+  DLOGI("New framebuffer resolution (%dx%d)", framebuffer_config_->x_pixels,
+        framebuffer_config_->y_pixels);
+
+  return 0;
+}
+
+void HWCDisplay::GetFrameBufferResolution(uint32_t *x_pixels, uint32_t *y_pixels) {
+  *x_pixels = framebuffer_config_->x_pixels;
+  *y_pixels = framebuffer_config_->y_pixels;
+}
+
+void HWCDisplay::ScaleDisplayFrame(hwc_rect_t *display_frame) {
+  if (!IsFrameBufferScaled()) {
+    return;
+  }
+
+  int active_config_index = GetActiveConfig();
+  DisplayConfigVariableInfo active_config;
+  DisplayError error = display_intf_->GetConfig(active_config_index, &active_config);
+  if (error != kErrorNone) {
+    DLOGE("GetConfig variable info failed. Error = %d", error);
+    return;
+  }
+
+  float custom_x_pixels = FLOAT(framebuffer_config_->x_pixels);
+  float custom_y_pixels = FLOAT(framebuffer_config_->y_pixels);
+  float active_x_pixels = FLOAT(active_config.x_pixels);
+  float active_y_pixels = FLOAT(active_config.y_pixels);
+  float x_pixels_ratio = active_x_pixels / custom_x_pixels;
+  float y_pixels_ratio = active_y_pixels / custom_y_pixels;
+  float layer_width = FLOAT(display_frame->right - display_frame->left);
+  float layer_height = FLOAT(display_frame->bottom - display_frame->top);
+
+  display_frame->left = INT(x_pixels_ratio * FLOAT(display_frame->left));
+  display_frame->top = INT(y_pixels_ratio * FLOAT(display_frame->top));
+  display_frame->right = INT(FLOAT(display_frame->left) + layer_width * x_pixels_ratio);
+  display_frame->bottom = INT(FLOAT(display_frame->top) + layer_height * y_pixels_ratio);
+}
+
+bool HWCDisplay::IsFrameBufferScaled() {
+  if (framebuffer_config_->x_pixels == 0 || framebuffer_config_->y_pixels == 0) {
+    return false;
+  }
+  uint32_t panel_x_pixels = 0;
+  uint32_t panel_y_pixels = 0;
+  GetPanelResolution(&panel_x_pixels, &panel_y_pixels);
+  return (framebuffer_config_->x_pixels != panel_x_pixels) ||
+          (framebuffer_config_->y_pixels != panel_y_pixels);
+}
+
+void HWCDisplay::GetPanelResolution(uint32_t *x_pixels, uint32_t *y_pixels) {
+  DisplayConfigVariableInfo active_config;
+  int active_config_index = GetActiveConfig();
+  DisplayError error = display_intf_->GetConfig(active_config_index, &active_config);
+  if (error != kErrorNone) {
+    DLOGE("GetConfig variable info failed. Error = %d", error);
+    return;
+  }
+  *x_pixels = active_config.x_pixels;
+  *y_pixels = active_config.y_pixels;
+}
+
+int HWCDisplay::SetDisplayStatus(uint32_t display_status) {
+  int status = 0;
+
+  switch (display_status) {
+  case kDisplayStatusResume:
+    display_paused_ = false;
+  case kDisplayStatusOnline:
+    status = SetPowerMode(HWC_POWER_MODE_NORMAL);
+    break;
+  case kDisplayStatusPause:
+    display_paused_ = true;
+  case kDisplayStatusOffline:
+    status = SetPowerMode(HWC_POWER_MODE_OFF);
+    break;
+  default:
+    DLOGW("Invalid display status %d", display_status);
+    return -EINVAL;
+  }
+
+  return status;
+}
+
+void HWCDisplay::MarkLayersForGPUBypass(hwc_display_contents_1_t *content_list) {
+  for (size_t i = 0 ; i < (content_list->numHwLayers - 1); i++) {
+    hwc_layer_1_t *layer = &content_list->hwLayers[i];
+    layer->compositionType = HWC_OVERLAY;
+  }
+}
+
+void HWCDisplay::CloseAcquireFences(hwc_display_contents_1_t *content_list) {
+  for (size_t i = 0; i < content_list->numHwLayers; i++) {
+    if (content_list->hwLayers[i].acquireFenceFd >= 0) {
+      close(content_list->hwLayers[i].acquireFenceFd);
+      content_list->hwLayers[i].acquireFenceFd = -1;
+    }
+  }
+}
+
+uint32_t HWCDisplay::RoundToStandardFPS(uint32_t fps) {
+  static const uint32_t standard_fps[4] = {30, 24, 48, 60};
+
+  int count = INT(sizeof(standard_fps) / sizeof(standard_fps[0]));
+  for (int i = 0; i < count; i++) {
+    if (abs(standard_fps[i] - fps) < 2) {
+      // Most likely used for video, the fps can fluctuate
+      // Ex: b/w 29 and 30 for 30 fps clip
+      return standard_fps[i];
+    }
+  }
+
+  return fps;
+}
+
+void HWCDisplay::ApplyScanAdjustment(hwc_rect_t *display_frame) {
+}
+
 }  // namespace sde
 
diff --git a/displayengine/libs/hwc/hwc_display.h b/displayengine/libs/hwc/hwc_display.h
index d14699f..8a68619 100644
--- a/displayengine/libs/hwc/hwc_display.h
+++ b/displayengine/libs/hwc/hwc_display.h
@@ -42,13 +42,24 @@
   virtual int GetDisplayAttributes(uint32_t config, const uint32_t *attributes, int32_t *values);
   virtual int GetActiveConfig();
   virtual int SetActiveConfig(int index);
-  virtual void SetIdleTimeoutMs(uint32_t timeout_ms);
   virtual int SetActiveConfig(hwc_display_contents_1_t *content_list);
+  virtual void SetIdleTimeoutMs(uint32_t timeout_ms);
   virtual void SetFrameDumpConfig(uint32_t count, uint32_t bit_mask_layer_type);
   virtual DisplayError SetMaxMixerStages(uint32_t max_mixer_stages);
   virtual uint32_t GetLastPowerMode();
+  virtual int SetFrameBufferResolution(uint32_t x_pixels, uint32_t y_pixels);
+  virtual void GetFrameBufferResolution(uint32_t *x_pixels, uint32_t *y_pixels);
+  virtual void GetPanelResolution(uint32_t *x_pixels, uint32_t *y_pixels);
+  virtual int SetDisplayStatus(uint32_t display_status);
 
  protected:
+  enum DisplayStatus {
+    kDisplayStatusOffline = 0,
+    kDisplayStatusOnline,
+    kDisplayStatusPause,
+    kDisplayStatusResume,
+  };
+
   // Maximum number of layers supported by display engine.
   static const uint32_t kMaxLayerCount = 32;
 
@@ -99,6 +110,12 @@
   void DumpInputBuffers(hwc_display_contents_1_t *content_list);
   const char *GetHALPixelFormatString(int format);
   const char *GetDisplayString();
+  void ScaleDisplayFrame(hwc_rect_t *display_frame);
+  bool IsFrameBufferScaled();
+  void MarkLayersForGPUBypass(hwc_display_contents_1_t *content_list);
+  void CloseAcquireFences(hwc_display_contents_1_t *content_list);
+  uint32_t RoundToStandardFPS(uint32_t fps);
+  virtual void ApplyScanAdjustment(hwc_rect_t *display_frame);
 
   enum {
     INPUT_LAYER_DUMP,
@@ -120,6 +137,10 @@
   bool dump_input_layers_;
   uint32_t last_power_mode_;
   bool swap_interval_zero_;
+  DisplayConfigVariableInfo *framebuffer_config_;
+  bool display_paused_;
+  bool use_metadata_refresh_rate_;
+  uint32_t metadata_refresh_rate_;
 };
 
 }  // namespace sde
diff --git a/displayengine/libs/hwc/hwc_display_external.cpp b/displayengine/libs/hwc/hwc_display_external.cpp
index 2758e3a..9e57114 100644
--- a/displayengine/libs/hwc/hwc_display_external.cpp
+++ b/displayengine/libs/hwc/hwc_display_external.cpp
@@ -27,6 +27,7 @@
 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
+#include <cutils/properties.h>
 #include <utils/constants.h>
 
 #include "hwc_display_external.h"
@@ -40,6 +41,17 @@
   : HWCDisplay(core_intf, hwc_procs, kHDMI, HWC_DISPLAY_EXTERNAL) {
 }
 
+int HWCDisplayExternal::Init() {
+  int status = 0;
+
+  status = HWCDisplay::Init();
+  if (status != 0) {
+    return status;
+  }
+
+  return status;
+}
+
 int HWCDisplayExternal::Prepare(hwc_display_contents_1_t *content_list) {
   int status = 0;
 
@@ -91,5 +103,39 @@
   return 0;
 }
 
+void HWCDisplayExternal::ApplyScanAdjustment(hwc_rect_t *display_frame) {
+  if (display_intf_->IsUnderscanSupported()) {
+    return;
+  }
+
+  // Read user defined width and height ratio
+  char property[PROPERTY_VALUE_MAX];
+  property_get("persist.sys.actionsafe.width", property, "0");
+  float width_ratio = FLOAT(atoi(property)) / 100.0f;
+  property_get("persist.sys.actionsafe.height", property, "0");
+  float height_ratio = FLOAT(atoi(property)) / 100.0f;
+
+  if (width_ratio == 0.0f ||  height_ratio == 0.0f) {
+    return;
+  }
+
+  uint32_t panel_width = 0;
+  uint32_t panel_height = 0;
+  GetPanelResolution(&panel_width, &panel_height);
+
+  if (panel_width == 0 || panel_height == 0) {
+    DLOGV("Invalid panel dimensions (%d, %d)", panel_width, panel_height);
+    return;
+  }
+
+  int x_offset = INT((FLOAT(panel_width) * width_ratio) / 2.0f);
+  int y_offset = INT((FLOAT(panel_height) * height_ratio) / 2.0f);
+
+  display_frame->left = display_frame->left + x_offset;
+  display_frame->top = display_frame->top + y_offset;
+  display_frame->right = display_frame->right - x_offset;
+  display_frame->bottom = display_frame->bottom - y_offset;
+}
+
 }  // namespace sde
 
diff --git a/displayengine/libs/hwc/hwc_display_external.h b/displayengine/libs/hwc/hwc_display_external.h
index e268621..6795761 100644
--- a/displayengine/libs/hwc/hwc_display_external.h
+++ b/displayengine/libs/hwc/hwc_display_external.h
@@ -32,9 +32,12 @@
 class HWCDisplayExternal : public HWCDisplay {
  public:
   explicit HWCDisplayExternal(CoreInterface *core_intf, hwc_procs_t const **hwc_procs);
+  virtual int Init();
   virtual int Prepare(hwc_display_contents_1_t *content_list);
   virtual int Commit(hwc_display_contents_1_t *content_list);
   virtual int GetDisplayConfigs(uint32_t *configs, size_t *num_configs);
+ private:
+  virtual void ApplyScanAdjustment(hwc_rect_t *display_frame);
 };
 
 }  // namespace sde
diff --git a/displayengine/libs/hwc/hwc_display_primary.cpp b/displayengine/libs/hwc/hwc_display_primary.cpp
index d1cd2d2..751162e 100644
--- a/displayengine/libs/hwc/hwc_display_primary.cpp
+++ b/displayengine/libs/hwc/hwc_display_primary.cpp
@@ -53,6 +53,10 @@
     return status;
   }
 
+  if (use_metadata_refresh_rate_) {
+    SetRefreshRate(metadata_refresh_rate_);
+  }
+
   return 0;
 }
 
@@ -82,5 +86,29 @@
   return error;
 }
 
+int HWCDisplayPrimary::SetActiveConfig(uint32_t index) {
+  DisplayError error = kErrorNone;
+
+  if (display_intf_) {
+    error = display_intf_->SetActiveConfig(index);
+  }
+
+  return error;
+}
+
+int HWCDisplayPrimary::SetRefreshRate(uint32_t refresh_rate) {
+  DisplayError error = kErrorNone;
+
+  if (display_intf_) {
+    error = display_intf_->SetRefreshRate(refresh_rate);
+  }
+
+  return error;
+}
+
+void HWCDisplayPrimary::SetMetaDataRefreshRateFlag(bool enable) {
+  use_metadata_refresh_rate_ = enable;
+}
+
 }  // namespace sde
 
diff --git a/displayengine/libs/hwc/hwc_display_primary.h b/displayengine/libs/hwc/hwc_display_primary.h
index 5015fff..cabedc2 100644
--- a/displayengine/libs/hwc/hwc_display_primary.h
+++ b/displayengine/libs/hwc/hwc_display_primary.h
@@ -35,6 +35,9 @@
   virtual int Prepare(hwc_display_contents_1_t *content_list);
   virtual int Commit(hwc_display_contents_1_t *content_list);
   virtual DisplayError SetDisplayMode(uint32_t mode);
+  virtual int SetActiveConfig(uint32_t index);
+  virtual int SetRefreshRate(uint32_t refresh_rate);
+  virtual void SetMetaDataRefreshRateFlag(bool enable);
 };
 
 }  // namespace sde
diff --git a/displayengine/libs/hwc/hwc_display_virtual.cpp b/displayengine/libs/hwc/hwc_display_virtual.cpp
index 9601e63..acd7948 100644
--- a/displayengine/libs/hwc/hwc_display_virtual.cpp
+++ b/displayengine/libs/hwc/hwc_display_virtual.cpp
@@ -28,7 +28,6 @@
 */
 
 #include <utils/constants.h>
-#include <gralloc_priv.h>
 #include <sync/sync.h>
 
 #include "hwc_display_virtual.h"
@@ -71,6 +70,11 @@
 
 int HWCDisplayVirtual::Prepare(hwc_display_contents_1_t *content_list) {
   int status = 0;
+  if (display_paused_) {
+    MarkLayersForGPUBypass(content_list);
+    return status;
+  }
+
   status = AllocateLayerStack(content_list);
   if (status) {
     return status;
@@ -91,6 +95,22 @@
 
 int HWCDisplayVirtual::Commit(hwc_display_contents_1_t *content_list) {
   int status = 0;
+  if (display_paused_) {
+    if (content_list->outbufAcquireFenceFd >= 0) {
+      // If we do not handle the frame set retireFenceFd to outbufAcquireFenceFd,
+      // which will make sure the framework waits on it and closes it.
+      content_list->retireFenceFd = dup(content_list->outbufAcquireFenceFd);
+      close(content_list->outbufAcquireFenceFd);
+      content_list->outbufAcquireFenceFd = -1;
+    }
+    CloseAcquireFences(content_list);
+
+    DisplayError error = display_intf_->Flush();
+    if (error != kErrorNone) {
+      DLOGE("Flush failed. Error = %d", error);
+    }
+    return status;
+  }
 
   status = HWCDisplay::CommitLayerStack(content_list);
   if (status) {
@@ -124,13 +144,15 @@
       return -EINVAL;
     }
 
-    if ((output_handle->width != INT(output_buffer_->width)) ||
-        (output_handle->height != INT(output_buffer_->height)) ||
+    int active_width = GetWidth(output_handle);
+    int active_height = GetHeight(output_handle);
+
+    if ((active_width != INT(output_buffer_->width)) ||
+        (active_height!= INT(output_buffer_->height)) ||
         (format != output_buffer_->format)) {
       DisplayConfigVariableInfo variable_info;
-
-      variable_info.x_pixels = output_handle->width;
-      variable_info.y_pixels = output_handle->height;
+      variable_info.x_pixels = active_width;
+      variable_info.y_pixels = active_height;
       // TODO(user): Need to get the framerate of primary display and update it.
       variable_info.fps = 60;
 
@@ -164,8 +186,8 @@
       return -EINVAL;
     }
 
-    output_buffer_->width = output_handle->width;
-    output_buffer_->height = output_handle->height;
+    output_buffer_->width = GetWidth(output_handle);
+    output_buffer_->height = GetHeight(output_handle);
     output_buffer_->flags.secure = 0;
     output_buffer_->flags.video = 0;
 
@@ -234,5 +256,23 @@
   DLOGI("output_layer_dump_enable %d", dump_output_layer_);
 }
 
+int HWCDisplayVirtual::GetWidth(const private_handle_t* handle) {
+  MetaData_t *metadata = reinterpret_cast<MetaData_t *>(handle->base_metadata);
+  if (metadata && metadata->operation & UPDATE_BUFFER_GEOMETRY) {
+    return metadata->bufferDim.sliceWidth;
+  }
+
+  return handle->width;
+}
+
+int HWCDisplayVirtual::GetHeight(const private_handle_t* handle) {
+  MetaData_t *metadata = reinterpret_cast<MetaData_t *>(handle->base_metadata);
+  if (metadata && metadata->operation & UPDATE_BUFFER_GEOMETRY) {
+    return metadata->bufferDim.sliceHeight;
+  }
+
+  return handle->height;
+}
+
 }  // namespace sde
 
diff --git a/displayengine/libs/hwc/hwc_display_virtual.h b/displayengine/libs/hwc/hwc_display_virtual.h
index 7ac7c22..3042b12 100644
--- a/displayengine/libs/hwc/hwc_display_virtual.h
+++ b/displayengine/libs/hwc/hwc_display_virtual.h
@@ -25,6 +25,8 @@
 #ifndef __HWC_DISPLAY_VIRTUAL_H__
 #define __HWC_DISPLAY_VIRTUAL_H__
 
+#include <qdMetaData.h>
+#include <gralloc_priv.h>
 #include "hwc_display.h"
 
 namespace sde {
@@ -42,6 +44,8 @@
  private:
   int SetOutputBuffer(hwc_display_contents_1_t *content_list);
   void DumpOutputBuffer(hwc_display_contents_1_t *content_list);
+  int GetWidth(const private_handle_t* handle);
+  int GetHeight(const private_handle_t* handle);
 
   bool dump_output_layer_;
 };
diff --git a/displayengine/libs/hwc/hwc_session.cpp b/displayengine/libs/hwc/hwc_session.cpp
index 2201aa6..f69ddfa 100644
--- a/displayengine/libs/hwc/hwc_session.cpp
+++ b/displayengine/libs/hwc/hwc_session.cpp
@@ -28,14 +28,19 @@
 */
 
 #include <core/dump_interface.h>
+#include <core/buffer_allocator.h>
 #include <utils/constants.h>
 #include <utils/String16.h>
+#include <cutils/properties.h>
 #include <hardware_legacy/uevent.h>
 #include <sys/resource.h>
 #include <sys/prctl.h>
 #include <binder/Parcel.h>
 #include <QService.h>
+#include <gr.h>
+#include <gralloc_priv.h>
 #include <core/buffer_allocator.h>
+#include <display_config.h>
 
 #include "hwc_buffer_allocator.h"
 #include "hwc_buffer_sync_handler.h"
@@ -153,6 +158,8 @@
     return -errno;
   }
 
+  SetFrameBufferResolution(HWC_DISPLAY_PRIMARY, NULL);
+
   return 0;
 }
 
@@ -240,10 +247,13 @@
       }
       break;
     case HWC_DISPLAY_VIRTUAL:
+      if (hwc_session->display_external_) {
+        break;
+      }
       if (hwc_session->ValidateContentList(content_list)) {
-        hwc_session->CreateVirtualDisplay(hwc_session, content_list);
+        hwc_session->CreateVirtualDisplay(content_list);
       } else {
-        hwc_session->DestroyVirtualDisplay(hwc_session);
+        hwc_session->DestroyVirtualDisplay();
       }
 
       if (hwc_session->display_virtual_) {
@@ -284,6 +294,21 @@
       }
       break;
     case HWC_DISPLAY_VIRTUAL:
+      if (hwc_session->display_external_) {
+        if (content_list) {
+          for (size_t i = 0; i < content_list->numHwLayers; i++) {
+            if (content_list->hwLayers[i].acquireFenceFd >= 0) {
+              close(content_list->hwLayers[i].acquireFenceFd);
+              content_list->hwLayers[i].acquireFenceFd = -1;
+            }
+          }
+          if (content_list->outbufAcquireFenceFd >= 0) {
+            close(content_list->outbufAcquireFenceFd);
+            content_list->outbufAcquireFenceFd = -1;
+          }
+          content_list->retireFenceFd = -1;
+        }
+      }
       if (hwc_session->display_virtual_) {
         hwc_session->display_virtual_->Commit(content_list);
       }
@@ -514,49 +539,50 @@
   return (content_list && content_list->numHwLayers > 0 && content_list->outbuf);
 }
 
-int HWCSession::CreateVirtualDisplay(HWCSession *hwc_session,
-                                     hwc_display_contents_1_t *content_list) {
+int HWCSession::CreateVirtualDisplay(hwc_display_contents_1_t *content_list) {
   int status = 0;
 
-  if (!hwc_session->display_virtual_) {
+  if (!display_virtual_) {
     // Create virtual display device
-    hwc_session->display_virtual_ = new HWCDisplayVirtual(hwc_session->core_intf_,
-                                                          &hwc_session->hwc_procs_);
-    if (!hwc_session->display_virtual_) {
+    display_virtual_ = new HWCDisplayVirtual(core_intf_, &hwc_procs_);
+    if (!display_virtual_) {
       // This is not catastrophic. Leave a warning message for now.
       DLOGW("Virtual Display creation failed");
       return -ENOMEM;
     }
 
-    status = hwc_session->display_virtual_->Init();
+    status = display_virtual_->Init();
     if (status) {
       goto CleanupOnError;
     }
 
-    status = hwc_session->display_virtual_->SetPowerMode(HWC_POWER_MODE_NORMAL);
+    status = display_virtual_->SetPowerMode(HWC_POWER_MODE_NORMAL);
     if (status) {
       goto CleanupOnError;
     }
   }
 
-  if (hwc_session->display_virtual_) {
-    status = hwc_session->display_virtual_->SetActiveConfig(content_list);
+  if (display_virtual_) {
+    SetFrameBufferResolution(HWC_DISPLAY_VIRTUAL, content_list);
+    status = display_virtual_->SetActiveConfig(content_list);
   }
 
   return status;
 
 CleanupOnError:
-  return hwc_session->DestroyVirtualDisplay(hwc_session);
+  return DestroyVirtualDisplay();
 }
 
-int HWCSession::DestroyVirtualDisplay(HWCSession *hwc_session) {
+int HWCSession::DestroyVirtualDisplay() {
   int status = 0;
 
-  if (hwc_session->display_virtual_) {
-    status = hwc_session->display_virtual_->Deinit();
+  if (display_virtual_) {
+    status = display_virtual_->Deinit();
     if (!status) {
-      delete hwc_session->display_virtual_;
-      hwc_session->display_virtual_ = NULL;
+      delete display_virtual_;
+      display_virtual_ = NULL;
+      // Signal the HotPlug thread to continue with the external display connection
+      locker_.Signal();
     }
   }
 
@@ -600,6 +626,13 @@
   case qService::IQService::SET_DISPLAY_MODE:
     status = SetDisplayMode(input_parcel);
     break;
+  case qService::IQService::SET_SECONDARY_DISPLAY_STATUS:
+    status = SetSecondaryDisplayStatus(input_parcel);
+    break;
+
+  case qService::IQService::CONFIGURE_DYN_REFRESH_RATE:
+    status = ConfigureRefreshRate(input_parcel);
+    break;
 
   default:
     DLOGW("QService command = %d is not supported", command);
@@ -609,6 +642,55 @@
   return status;
 }
 
+android::status_t HWCSession::SetSecondaryDisplayStatus(const android::Parcel *input_parcel) {
+  uint32_t display_id = UINT32(input_parcel->readInt32());
+  uint32_t display_status = UINT32(input_parcel->readInt32());
+  HWCDisplay *display = NULL;
+
+  DLOGI("Display %d Status %d", display_id, display_status);
+  switch (display_id) {
+  case HWC_DISPLAY_EXTERNAL:
+    display = display_external_;
+    break;
+  case HWC_DISPLAY_VIRTUAL:
+    display = display_virtual_;
+    break;
+  default:
+    DLOGW("Not supported for display %d", display_id);
+    return -EINVAL;
+  }
+
+  return display->SetDisplayStatus(display_status);
+}
+
+android::status_t HWCSession::ConfigureRefreshRate(const android::Parcel *input_parcel) {
+  uint32_t operation = UINT32(input_parcel->readInt32());
+
+  switch (operation) {
+  case qdutils::DISABLE_METADATA_DYN_REFRESH_RATE:
+    display_primary_->SetMetaDataRefreshRateFlag(false);
+    break;
+
+  case qdutils::ENABLE_METADATA_DYN_REFRESH_RATE:
+    display_primary_->SetMetaDataRefreshRateFlag(true);
+    break;
+
+  case qdutils::SET_BINDER_DYN_REFRESH_RATE:
+  {
+    uint32_t refresh_rate = UINT32(input_parcel->readInt32());
+
+    display_primary_->SetRefreshRate(refresh_rate);
+    break;
+  }
+
+  default:
+    DLOGW("Invalid operation %d", operation);
+    return -EINVAL;
+  }
+
+  return 0;
+}
+
 android::status_t HWCSession::SetDisplayMode(const android::Parcel *input_parcel) {
   DisplayError error = kErrorNone;
   uint32_t mode = UINT32(input_parcel->readInt32());
@@ -753,8 +835,9 @@
         if (hwc_procs_) {
           reset_panel_ = true;
           hwc_procs_->invalidate(hwc_procs_);
-        } else
+        } else {
           DLOGW("Ignore resetpanel - hwc_proc not registered");
+        }
       }
     }
   }
@@ -782,19 +865,19 @@
   DLOGI("Powering off primary");
   status = display_primary_->SetPowerMode(HWC_POWER_MODE_OFF);
   if (status) {
-    DLOGE("power-off on primary failed with error = %d",status);
+    DLOGE("power-off on primary failed with error = %d", status);
   }
 
   DLOGI("Restoring power mode on primary");
   uint32_t mode = display_primary_->GetLastPowerMode();
   status = display_primary_->SetPowerMode(mode);
   if (status) {
-    DLOGE("Setting power mode = %d on primary failed with error = %d", mode,status);
+    DLOGE("Setting power mode = %d on primary failed with error = %d", mode, status);
   }
 
   status = display_primary_->EventControl(HWC_EVENT_VSYNC, 1);
   if (status) {
-    DLOGE("enabling vsync failed for primary with error = %d",status);
+    DLOGE("enabling vsync failed for primary with error = %d", status);
   }
 
   reset_panel_ = false;
@@ -808,6 +891,14 @@
 
   if (connected) {
     SEQUENCE_WAIT_SCOPE_LOCK(locker_);
+    if (display_virtual_) {
+      // Wait for the virtual display to tear down
+      int status = locker_.WaitFinite(kExternalConnectionTimeoutMs);
+      if (status != 0) {
+        DLOGE("Timed out while waiting for virtual display to tear down.");
+        return -1;
+      }
+    }
     if (display_external_) {
      DLOGE("HDMI already connected");
      return -1;
@@ -823,6 +914,7 @@
       display_external_ = NULL;
       return -1;
     }
+    SetFrameBufferResolution(HWC_DISPLAY_EXTERNAL, NULL);
   } else {
     SEQUENCE_WAIT_SCOPE_LOCK(locker_);
     if (!display_external_) {
@@ -842,5 +934,72 @@
   return 0;
 }
 
+void HWCSession::SetFrameBufferResolution(int disp, hwc_display_contents_1_t *content_list) {
+  char property[PROPERTY_VALUE_MAX];
+  uint32_t primary_width = 0;
+  uint32_t primary_height = 0;
+
+  switch (disp) {
+  case HWC_DISPLAY_PRIMARY:
+  {
+    display_primary_->GetPanelResolution(&primary_width, &primary_height);
+    if (property_get("debug.hwc.fbsize", property, NULL) > 0) {
+      char *yptr = strcasestr(property, "x");
+      primary_width = atoi(property);
+      primary_height = atoi(yptr + 1);
+    }
+    display_primary_->SetFrameBufferResolution(primary_width, primary_height);
+    break;
+  }
+
+  case HWC_DISPLAY_EXTERNAL:
+  {
+    uint32_t external_width = 0;
+    uint32_t external_height = 0;
+    display_external_->GetPanelResolution(&external_width, &external_height);
+
+    if (property_get("sys.hwc.mdp_downscale_enabled", property, "false") &&
+        !strcmp(property, "true")) {
+      display_primary_->GetFrameBufferResolution(&primary_width, &primary_height);
+      uint32_t primary_area = primary_width * primary_height;
+      uint32_t external_area = external_width * external_height;
+
+      if (primary_area > external_area) {
+        if (primary_height > primary_width) {
+          Swap(primary_height, primary_width);
+        }
+        AdjustSourceResolution(primary_width, primary_height,
+                               &external_width, &external_height);
+      }
+    }
+    display_external_->SetFrameBufferResolution(external_width, external_height);
+    break;
+  }
+
+  case HWC_DISPLAY_VIRTUAL:
+  {
+    if (ValidateContentList(content_list)) {
+      const private_handle_t *output_handle =
+              static_cast<const private_handle_t *>(content_list->outbuf);
+      int virtual_width = 0;
+      int virtual_height = 0;
+      getBufferSizeAndDimensions(output_handle->width, output_handle->height, output_handle->format,
+                                 virtual_width, virtual_height);
+      display_virtual_->SetFrameBufferResolution(virtual_width, virtual_height);
+    }
+    break;
+  }
+
+  default:
+    break;
+  }
+}
+
+void HWCSession::AdjustSourceResolution(uint32_t dst_width, uint32_t dst_height,
+                                        uint32_t *src_width, uint32_t *src_height) {
+  *src_height = (dst_width * (*src_height)) / (*src_width);
+  *src_width = dst_width;
+}
+
 }  // namespace sde
 
diff --git a/displayengine/libs/hwc/hwc_session.h b/displayengine/libs/hwc/hwc_session.h
index dffa864..fbb3f43 100644
--- a/displayengine/libs/hwc/hwc_session.h
+++ b/displayengine/libs/hwc/hwc_session.h
@@ -49,6 +49,8 @@
   int Deinit();
 
  private:
+  static const int kExternalConnectionTimeoutMs = 500;
+
   // hwc methods
   static int Open(const hw_module_t *module, const char* name, hw_device_t **device);
   static int Close(hw_device_t *device);
@@ -75,8 +77,8 @@
   int HotPlugHandler(bool connected);
   void ResetPanel();
   bool ValidateContentList(hwc_display_contents_1_t *content_list);
-  int CreateVirtualDisplay(HWCSession *hwc_session, hwc_display_contents_1_t *content_list);
-  int DestroyVirtualDisplay(HWCSession *hwc_session);
+  int CreateVirtualDisplay(hwc_display_contents_1_t *content_list);
+  int DestroyVirtualDisplay();
 
   // CoreEventHandler methods
   virtual DisplayError Hotplug(const CoreEventHotplug &hotplug);
@@ -88,6 +90,11 @@
   void SetFrameDumpConfig(const android::Parcel *input_parcel);
   android::status_t SetMaxMixerStages(const android::Parcel *input_parcel);
   android::status_t SetDisplayMode(const android::Parcel *input_parcel);
+  android::status_t SetSecondaryDisplayStatus(const android::Parcel *input_parcel);
+  void SetFrameBufferResolution(int disp, hwc_display_contents_1_t *content_list);
+  void AdjustSourceResolution(uint32_t dst_width, uint32_t dst_height,
+                              uint32_t *src_width, uint32_t *src_height);
+  android::status_t ConfigureRefreshRate(const android::Parcel *input_parcel);
 
   static Locker locker_;
   CoreInterface *core_intf_;
diff --git a/displayengine/libs/utils/debug_android.cpp b/displayengine/libs/utils/debug_android.cpp
index 77c82b0..779c441 100644
--- a/displayengine/libs/utils/debug_android.cpp
+++ b/displayengine/libs/utils/debug_android.cpp
@@ -90,7 +90,7 @@
 }
 
 // This property serves to disable/enable partial update
-bool Debug::IsPartialUpdate() {
+bool Debug::IsPartialUpdateEnabled() {
   char property[PROPERTY_VALUE_MAX];
   if (property_get("sde.hwc.partial_update", property, NULL) > 0) {
     return (atoi(property) ? 1 : true, false);
diff --git a/displayengine/libs/utils/rect.cpp b/displayengine/libs/utils/rect.cpp
index 9b05951..630cebb 100644
--- a/displayengine/libs/utils/rect.cpp
+++ b/displayengine/libs/utils/rect.cpp
@@ -122,11 +122,11 @@
     return LayerRect();
   }
 
-  if(!IsValid(rect1)){
+  if (!IsValid(rect1)) {
     return rect2;
   }
 
-  if(!IsValid(rect2)){
+  if (!IsValid(rect2)) {
     return rect1;
   }
 
diff --git a/libgralloc/alloc_controller.cpp b/libgralloc/alloc_controller.cpp
index 3ed4934..695de9b 100644
--- a/libgralloc/alloc_controller.cpp
+++ b/libgralloc/alloc_controller.cpp
@@ -153,15 +153,17 @@
                             int usage, int& aligned_w, int& aligned_h)
 {
 
+    bool ubwc_enabled = isUBwcEnabled(format, usage);
+
     // Currently surface padding is only computed for RGB* surfaces.
     if (format <= HAL_PIXEL_FORMAT_sRGB_X_8888) {
-        int tileEnabled = isMacroTileEnabled(format, usage);
+        int tileEnabled = ubwc_enabled || isMacroTileEnabled(format, usage);
         AdrenoMemInfo::getInstance().getGpuAlignedWidthHeight(width,
             height, format, tileEnabled, aligned_w, aligned_h);
         return;
     }
 
-    if (isUBwcEnabled(format, usage)) {
+    if (ubwc_enabled) {
         getUBwcWidthAndHeight(width, height, format, aligned_w, aligned_h);
         return;
     }
@@ -172,9 +174,11 @@
     {
         case HAL_PIXEL_FORMAT_YCrCb_420_SP:
         case HAL_PIXEL_FORMAT_YCrCb_420_SP_ADRENO:
-        case HAL_PIXEL_FORMAT_RAW_SENSOR:
             aligned_w = ALIGN(width, 32);
             break;
+        case HAL_PIXEL_FORMAT_RAW_SENSOR:
+            aligned_w = ALIGN(width, 16);
+            break;
         case HAL_PIXEL_FORMAT_RAW10:
             aligned_w = ALIGN(width * 10 /8, 16);
             break;
@@ -627,9 +631,9 @@
 
 
 void getBufferAttributes(int width, int height, int format, int usage,
-        int& alignedw, int &alignedh, int& tileEnabled, unsigned int& size)
+        int& alignedw, int &alignedh, int& tiled, unsigned int& size)
 {
-    tileEnabled = isMacroTileEnabled(format, usage);
+    tiled = isUBwcEnabled(format, usage) || isMacroTileEnabled(format, usage);
 
     AdrenoMemInfo::getInstance().getAlignedWidthAndHeight(width,
             height,
diff --git a/libgralloc/gpu.cpp b/libgralloc/gpu.cpp
index 11d8f1f..256b023 100644
--- a/libgralloc/gpu.cpp
+++ b/libgralloc/gpu.cpp
@@ -148,6 +148,7 @@
         if (isUBwcEnabled(format, usage) &&
             AdrenoMemInfo::getInstance().isUBWCSupportedByGPU(format)) {
             flags |= private_handle_t::PRIV_FLAGS_UBWC_ALIGNED;
+            flags |= private_handle_t::PRIV_FLAGS_TILE_RENDERED;
         }
 
         if(usage & (GRALLOC_USAGE_SW_READ_MASK | GRALLOC_USAGE_SW_WRITE_MASK)) {
diff --git a/libgralloc/mapper.cpp b/libgralloc/mapper.cpp
index 30f606e..cf365ce 100644
--- a/libgralloc/mapper.cpp
+++ b/libgralloc/mapper.cpp
@@ -386,7 +386,8 @@
                 int *alignedWidth = va_arg(args, int *);
                 int *alignedHeight = va_arg(args, int *);
                 int *tileEnabled = va_arg(args,int *);
-                *tileEnabled = isMacroTileEnabled(format, usage);
+                *tileEnabled = isUBwcEnabled(format, usage) ||
+                               isMacroTileEnabled(format, usage);
                 AdrenoMemInfo::getInstance().getAlignedWidthAndHeight(width,
                         height, format, usage, *alignedWidth, *alignedHeight);
                 res = 0;
diff --git a/libhwcomposer/hwc_copybit.cpp b/libhwcomposer/hwc_copybit.cpp
index 00bd643..e7c2928 100644
--- a/libhwcomposer/hwc_copybit.cpp
+++ b/libhwcomposer/hwc_copybit.cpp
@@ -82,6 +82,29 @@
     return true;
 }
 
+bool CopyBit::isSmartBlitPossible(const hwc_display_contents_1_t *list){
+    if(list->numHwLayers > 2) {
+        hwc_rect_t displayFrame0 = {0, 0, 0, 0};
+        hwc_rect_t displayFrame1 = {0, 0, 0, 0};
+        for (unsigned int i=0; i<list->numHwLayers -1; i++) {
+            hwc_rect_t displayFrame = getIntersection(mDirtyRect,
+                                                list->hwLayers[i].displayFrame);
+            if (isValidRect(displayFrame) && !isValidRect(displayFrame0)) {
+                displayFrame0 = displayFrame;
+            } else if(isValidRect(displayFrame)) {
+                displayFrame1 = displayFrame;
+                break;
+            }
+        }
+        if((displayFrame0 == displayFrame1) &&
+            not (list->flags & (MDP_ROT_90 | MDP_FLIP_UD | MDP_FLIP_LR))) {
+            ALOGD_IF (DEBUG_COPYBIT, "%s:Smart Bilt Possible",__FUNCTION__);
+            return true;
+        }
+    }
+    return false;
+}
+
 bool CopyBit::canUseCopybitForRGB(hwc_context_t *ctx,
                                         hwc_display_contents_1_t *list,
                                         int dpy) {
@@ -99,7 +122,11 @@
         unsigned int renderArea = getRGBRenderingArea(ctx, list);
             ALOGD_IF (DEBUG_COPYBIT, "%s:renderArea %u, fbArea %u",
                                   __FUNCTION__, renderArea, fbArea);
-        if (renderArea < (mDynThreshold * fbArea)) {
+        double dynThreshold = mDynThreshold;
+        if(not isSmartBlitPossible(list))
+            dynThreshold -= 1;
+
+        if (renderArea < (dynThreshold * fbArea)) {
             return true;
         }
     } else if ((compositionType & qdutils::COMPOSITION_TYPE_MDP)) {
@@ -148,16 +175,19 @@
     return 0;
 }
 
-int CopyBit::getLayersChanging(hwc_context_t *ctx,
-                      hwc_display_contents_1_t *list,
-                      int dpy){
-
-   int changingLayerIndex = -1;
-   if(mLayerCache.layerCount != ctx->listStats[dpy].numAppLayers) {
+bool CopyBit::prepareSwapRect(hwc_context_t *ctx,
+                           hwc_display_contents_1_t *list,
+                           int dpy) {
+   bool canUseSwapRect = 0;
+   hwc_rect_t dirtyRect = {0, 0, 0, 0};
+   hwc_rect_t displayRect = {0, 0, 0, 0};
+   if((mLayerCache.layerCount != ctx->listStats[dpy].numAppLayers) ||
+                                                        not mSwapRectEnable) {
         mLayerCache.reset();
         mFbCache.reset();
         mLayerCache.updateCounts(ctx,list,dpy);
-        return -1;
+        mDirtyRect = displayRect;
+        return 0;
     }
 
     int updatingLayerCount = 0;
@@ -165,8 +195,10 @@
        //swap rect will kick in only for single updating layer
        if(isLayerChanging(ctx, list, k)) {
            updatingLayerCount ++;
-           if(updatingLayerCount == 1)
-             changingLayerIndex = k;
+           hwc_layer_1_t layer = list->hwLayers[k];
+           canUseSwapRect = 1;
+           dirtyRect = getUnion(dirtyRect, layer.dirtyRect);
+           displayRect = getUnion(displayRect, layer.displayFrame);
        }
     }
     //since we are using more than one framebuffers,we have to
@@ -174,19 +206,13 @@
     //dirty rect for same layer at least equal of number of
     //framebuffers
 
-    if ( updatingLayerCount <=  1 ) {
-        hwc_rect_t dirtyRect;
+      if (canUseSwapRect || updatingLayerCount == 0) {
         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;
-#endif
+            canUseSwapRect = 1;
         }
 
        for (int k = ctx->listStats[dpy].numAppLayers-1; k >= 0 ; k--) {
@@ -195,34 +221,36 @@
            if(needsScaling(&list->hwLayers[k])||( hnd && isYuvBuffer(hnd)) ||
                    (list->hwLayers[k].transform & HAL_TRANSFORM_ROT_90)) {
                mFbCache.reset();
-               return -1;
+               displayRect.bottom = 0;
+               displayRect.top = 0;
+               displayRect.right = 0;
+               displayRect.bottom = 0;
+               mDirtyRect = displayRect;
+               return 0;
            }
        }
-       hwc_rect_t displayRect = list->hwLayers[changingLayerIndex].displayFrame;
+
        if(mFbCache.getUnchangedFbDRCount(dirtyRect, displayRect) <
                                              NUM_RENDER_BUFFERS) {
               mFbCache.insertAndUpdateFbCache(dirtyRect, displayRect);
-              changingLayerIndex =  -1;
+              canUseSwapRect =  0;
+              displayRect.bottom = 0;
+              displayRect.top = 0;
+              displayRect.right = 0;
+              displayRect.bottom = 0;
        }
     } else {
        mFbCache.reset();
-       changingLayerIndex =  -1;
+       canUseSwapRect =  0;
+       displayRect.bottom = 0;
+       displayRect.top = 0;
+       displayRect.right = 0;
+       displayRect.bottom = 0;
+
     }
+    mDirtyRect = displayRect;
     mLayerCache.updateCounts(ctx,list,dpy);
-    return changingLayerIndex;
-}
-
-int CopyBit::checkDirtyRect(hwc_context_t *ctx,
-                           hwc_display_contents_1_t *list,
-                           int dpy) {
-
-   //dirty rect will enable only if
-   //1.Only single layer is updating.
-   //2.No scaling
-   //3.No video layer
-   if(mSwapRectEnable == false)
-      return -1;
-   return getLayersChanging(ctx, list, dpy);
+    return canUseSwapRect;
 }
 
 bool CopyBit::prepareOverlap(hwc_context_t *ctx,
@@ -326,6 +354,13 @@
         return false;
     }
 
+    int last = (uint32_t)list->numHwLayers - 1;
+    mDirtyRect = list->hwLayers[last].displayFrame;
+    mSwapRect =  prepareSwapRect(ctx, list, dpy);
+    ALOGD_IF (DEBUG_COPYBIT, "%s: mSwapRect: %d mDirtyRect: [%d, %d, %d, %d]",
+                           __FUNCTION__, mSwapRect, mDirtyRect.left,
+                           mDirtyRect.top, mDirtyRect.right, mDirtyRect.bottom);
+
     bool useCopybitForYUV = canUseCopybitForYUV(ctx);
     bool useCopybitForRGB = canUseCopybitForRGB(ctx, list, dpy);
     LayerProp *layerProp = ctx->layerProp[dpy];
@@ -498,7 +533,7 @@
              list->hwLayers[abcRenderBufIdx].acquireFenceFd);
           }
           for(int i = abcRenderBufIdx + 1; i < layerCount; i++){
-             mDirtyLayerIndex = -1;
+             mSwapRect = 0;
              int retVal = drawLayerUsingCopybit(ctx,
                &(list->hwLayers[i]),renderBuffer, 0);
              if(retVal < 0) {
@@ -559,33 +594,9 @@
         }
     }
 
-    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 (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
-       //making solid fill as full in this case
-       //disable swap rect if presents
-       if ((clear_w == 1) || (clear_h ==1)) {
-           clear(renderBuffer, mDirtyRect);
-           mDirtyLayerIndex = -1;
-       }else
-           clear(renderBuffer, clearRegion);
-    }
-    if (mDirtyLayerIndex != -1) {
-        if (mDirtyLayerIndex == NO_UPDATING_LAYER) {
-            mDirtyRect = clearRegion;
-        } else {
-            mDirtyRect = list->hwLayers[mDirtyLayerIndex].displayFrame;
-        }
+    if (not CBUtils::uiClearRegion(list, ctx->mMDP.version, layerProp,
+                                   mDirtyRect, mEngine, renderBuffer)){
+        mSwapRect = 0;
     }
 
     // numAppLayers-1, as we iterate from 0th layer index with HWC_COPYBIT flag
@@ -648,10 +659,10 @@
     }
 
     //Clear the transparent or left out region on the render buffer
-    hwc_rect_t clearRegion = {0,0,0,0};
     LayerProp *layerProp = ctx->layerProp[0];
-    if(CBUtils::getuiClearRegion(list, clearRegion, layerProp))
-        clear(renderBuffer, clearRegion);
+    hwc_rect_t clearRegion = {0, 0, 0, 0};
+    CBUtils::uiClearRegion(list, ctx->mMDP.version, layerProp, clearRegion,
+                                                    mEngine, renderBuffer);
 
     int copybitLayerCount = 0;
     for(int j = 0; j < ptorInfo->count; j++) {
@@ -901,7 +912,7 @@
                               displayFrame.bottom};
 #ifdef QCOM_BSP
     //change src and dst with dirtyRect
-    if(mDirtyLayerIndex != -1) {
+    if(mSwapRect) {
       hwc_rect_t result = getIntersection(displayFrame, mDirtyRect);
       if(!isValidRect(result))
              return true;
@@ -1147,9 +1158,10 @@
                                  unsigned int& width, unsigned int& height)
 {
     hwc_rect_t displayFrame  = layer->displayFrame;
+    hwc_rect_t result = getIntersection(mDirtyRect, displayFrame);
 
-    width = displayFrame.right - displayFrame.left;
-    height = displayFrame.bottom - displayFrame.top;
+    width = result.right - result.left;
+    height = result.bottom - result.top;
 }
 
 bool CopyBit::validateParams(hwc_context_t *ctx,
@@ -1238,7 +1250,7 @@
 
     property_get("debug.sf.swaprect", value, "0");
     mSwapRectEnable = atoi(value) ? true:false ;
-    mDirtyLayerIndex = -1;
+    mSwapRect = 0;
     if (hw_get_module(COPYBIT_HARDWARE_MODULE_ID, &module) == 0) {
         if(copybit_open(module, &mEngine) < 0) {
             ALOGE("FATAL ERROR: copybit open failed.");
diff --git a/libhwcomposer/hwc_copybit.h b/libhwcomposer/hwc_copybit.h
index 993c790..a1601cc 100644
--- a/libhwcomposer/hwc_copybit.h
+++ b/libhwcomposer/hwc_copybit.h
@@ -131,16 +131,15 @@
     bool mSwapRectEnable;
     int mAlignedWidth;
     int mAlignedHeight;
-    int mDirtyLayerIndex;
+    int mSwapRect;
     LayerCache mLayerCache;
     FbCache mFbCache;
     hwc_rect_t mDirtyRect;
-    int getLayersChanging(hwc_context_t *ctx, hwc_display_contents_1_t *list,
-                  int dpy);
-    int checkDirtyRect(hwc_context_t *ctx, hwc_display_contents_1_t *list,
+    bool prepareSwapRect(hwc_context_t *ctx, hwc_display_contents_1_t *list,
                   int dpy);
     bool isLayerChanging(hwc_context_t *ctx,
                             hwc_display_contents_1_t *list, int k);
+    bool isSmartBlitPossible(const hwc_display_contents_1_t *list);
 };
 
 }; //namespace qhwc
diff --git a/libhwcomposer/hwc_utils.cpp b/libhwcomposer/hwc_utils.cpp
index 79235ff..5de3081 100644
--- a/libhwcomposer/hwc_utils.cpp
+++ b/libhwcomposer/hwc_utils.cpp
@@ -967,6 +967,9 @@
     src_w = sourceCrop.right - sourceCrop.left;
     src_h = sourceCrop.bottom - sourceCrop.top;
 
+    if(layer->transform & HWC_TRANSFORM_ROT_90)
+        swap(src_w, src_h);
+
     if(((src_w > dst_w) || (src_h > dst_h)))
         return true;
 
@@ -982,6 +985,10 @@
     dst_h = displayFrame.bottom - displayFrame.top;
     src_w = sourceCrop.right - sourceCrop.left;
     src_h = sourceCrop.bottom - sourceCrop.top;
+
+    if(layer->transform & HWC_TRANSFORM_ROT_90)
+        swap(src_w, src_h);
+
     if(dst_w && dst_h) {
         float w_scale = ((float)src_w / (float)dst_w);
         float h_scale = ((float)src_h / (float)dst_h);
diff --git a/liblight/lights.c b/liblight/lights.c
index 615ddd8..12af384 100644
--- a/liblight/lights.c
+++ b/liblight/lights.c
@@ -162,7 +162,16 @@
     blue = colorRGB & 0xFF;
 
     if (onMS > 0 && offMS > 0) {
-        blink = 1;
+        /*
+         * if ON time == OFF time
+         *   use blink mode 2
+         * else
+         *   use blink mode 1
+         */
+        if (onMS == offMS)
+            blink = 2;
+        else
+            blink = 1;
     } else {
         blink = 0;
     }
diff --git a/libqdutils/cb_utils.cpp b/libqdutils/cb_utils.cpp
index c17842a..b85b901 100644
--- a/libqdutils/cb_utils.cpp
+++ b/libqdutils/cb_utils.cpp
@@ -36,37 +36,39 @@
     irect.bottom = max(rect1.bottom, rect2.bottom);
 }
 
+int clear (copybit_device_t *copybit, private_handle_t* hnd, hwc_rect_t& rect)
+{
+    int ret = 0;
+    copybit_rect_t clear_rect = {rect.left, rect.top,rect.right,rect.bottom};
+
+    copybit_image_t buf;
+    buf.w = ALIGN(getWidth(hnd),32);
+    buf.h = getHeight(hnd);
+    buf.format = hnd->format;
+    buf.base = (void *)hnd->base;
+    buf.handle = (native_handle_t *)hnd;
+
+    ret = copybit->clear(copybit, &buf, &clear_rect);
+    return ret;
+}
 using namespace android;
 using namespace qhwc;
 namespace qdutils {
 
-int CBUtils::getuiClearRegion(hwc_display_contents_1_t* list,
-          hwc_rect_t &clearWormholeRect, LayerProp *layerProp, int dirtyIndex) {
+int CBUtils::uiClearRegion(hwc_display_contents_1_t* list,
+        int version, LayerProp *layerProp,  hwc_rect_t dirtyRect,
+            copybit_device_t *copybit, private_handle_t *renderBuffer) {
 
     size_t last = list->numHwLayers - 1;
     hwc_rect_t fbFrame = list->hwLayers[last].displayFrame;
     Rect fbFrameRect(fbFrame.left,fbFrame.top,fbFrame.right,fbFrame.bottom);
     Region wormholeRegion(fbFrameRect);
 
-   if (dirtyIndex != -1) {
+   if ((dirtyRect.right - dirtyRect.left > 0) &&
+                               (dirtyRect.bottom - dirtyRect.top > 0)) {
 #ifdef QCOM_BSP
-      /*
-       * 1. Map dirty rect of updating layer to its display frame.
-       * 2. Use this display frame as wormholeRegion instead of full Frame
-       * */
-      hwc_rect_t dirtyRect = list->hwLayers[dirtyIndex].dirtyRect;
-      hwc_rect_t displayFrame = list->hwLayers[dirtyIndex].displayFrame;
-      hwc_frect_t sCropF = list->hwLayers[dirtyIndex].sourceCropf;
-      hwc_rect_t srcRect = {int(ceilf(sCropF.left)), int(ceilf(sCropF.top)),
-                           int(ceilf(sCropF.right)), int(ceilf(sCropF.bottom))};
-
-      displayFrame.left += dirtyRect.left - srcRect.left;
-      displayFrame.top += dirtyRect.top - srcRect.top;
-      displayFrame.right -= srcRect.right - dirtyRect.right;
-      displayFrame.bottom -= srcRect.bottom - dirtyRect.bottom;
-
-      Rect tmpRect(displayFrame.left,displayFrame.top,displayFrame.right,
-            displayFrame.bottom);
+      Rect tmpRect(dirtyRect.left,dirtyRect.top,dirtyRect.right,
+            dirtyRect.bottom);
       Region tmpRegion(tmpRect);
       wormholeRegion = wormholeRegion.intersect(tmpRegion);
 #endif
@@ -100,7 +102,7 @@
      }
    }
    if(wormholeRegion.isEmpty()){
-        return 0;
+        return 1;
    }
    //TO DO :- 1. remove union and call clear for each rect.
    Region::const_iterator it = wormholeRegion.begin();
@@ -108,14 +110,22 @@
    while (it != end) {
        const Rect& r = *it++;
        hwc_rect_t tmpWormRect = {r.left,r.top,r.right,r.bottom};
-       int dst_w =  clearWormholeRect.right -  clearWormholeRect.left;
-       int dst_h =  clearWormholeRect.bottom -  clearWormholeRect.top;
-
-       if (!(dst_w || dst_h))
-             clearWormholeRect = tmpWormRect;
-       else
-             getUnion(clearWormholeRect, tmpWormRect, clearWormholeRect);
-
+       if (version == qdutils::MDP_V3_0_4 ||
+               version == qdutils::MDP_V3_0_5) {
+           int clear_w =  tmpWormRect.right - tmpWormRect.left;
+           int clear_h =  tmpWormRect.bottom - tmpWormRect.top;
+           //mdp can't handle solid fill for one line
+           //making solid fill as full in this case
+           //disable swap rect if presents
+           if ((clear_w == 1) || (clear_h ==1)) {
+               clear(copybit, renderBuffer, fbFrame);
+               return 0;
+           } else {
+               clear(copybit, renderBuffer, tmpWormRect);
+           }
+       } else {
+           clear(copybit, renderBuffer, tmpWormRect);
+       }
    }
    return 1;
 }
diff --git a/libqdutils/cb_utils.h b/libqdutils/cb_utils.h
index 59f452b..55225b6 100644
--- a/libqdutils/cb_utils.h
+++ b/libqdutils/cb_utils.h
@@ -31,14 +31,15 @@
 
 #include <ui/Region.h>
 #include "hwc_utils.h"
+#include "copybit.h"
 
 using namespace qhwc;
 namespace qdutils {
 class CBUtils {
 public:
-static int getuiClearRegion(hwc_display_contents_1_t* list,
-                              hwc_rect_t &clearWormholeRec,
-                              LayerProp *layerProp, int dirtyIndex = -1);
+    static int uiClearRegion(hwc_display_contents_1_t* list,
+            int version, LayerProp *layerProp, hwc_rect_t dirtyIndex,
+            copybit_device_t *copybit, private_handle_t *renderBuffer);
 };
 }//namespace qdutils
 #endif /* end of include guard: CB_UTIL_H*/