Merge "sde: Implement rotator session management in rotator controller"
diff --git a/displayengine/include/core/display_interface.h b/displayengine/include/core/display_interface.h
index f4c4415..c041e1a 100644
--- a/displayengine/include/core/display_interface.h
+++ b/displayengine/include/core/display_interface.h
@@ -63,8 +63,11 @@
 
   kStateOn,         //!< Display is ON. Contents are rendered in this state.
 
-  kStateDoze,       //!< Display is ON but not updating contents. Client shall not push any contents
-                    //!< in this state.
+  kStateDoze,       //!< Display is ON and it is configured in a low power state.
+
+  kStateDozeSuspend,
+                    //!< Display is ON in a low power state and continue showing its current
+                    //!< contents indefinitely until the mode changes.
 
   kStateStandby,    //!< Display is OFF. Client will continue to receive VSync events in this state
                     //!< if VSync is enabled. Contents are not rendered in this state.
@@ -95,9 +98,10 @@
   float 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 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) { }
+                               fps(0.0f), vsync_period_ns(0), v_total(0), h_total(0) { }
 };
 
 /*! @brief Event data associated with VSync event.
diff --git a/displayengine/libs/core/comp_manager.cpp b/displayengine/libs/core/comp_manager.cpp
index a694297..82f7b8d 100644
--- a/displayengine/libs/core/comp_manager.cpp
+++ b/displayengine/libs/core/comp_manager.cpp
@@ -182,7 +182,7 @@
     constraints->safe_mode = true;
   }
 
-  if (display_comp_ctx->idle_fallback) {
+  if (display_comp_ctx->idle_fallback || display_comp_ctx->fallback_) {
     constraints->safe_mode = true;
   }
 }
@@ -320,6 +320,19 @@
   return false;
 }
 
+void CompManager::ProcessThermalEvent(Handle display_ctx, int64_t thermal_level) {
+  SCOPE_LOCK(locker_);
+
+  DisplayCompositionContext *display_comp_ctx =
+          reinterpret_cast<DisplayCompositionContext *>(display_ctx);
+
+  if (thermal_level >= kMaxThermalLevel) {
+    display_comp_ctx->fallback_ = true;
+  } else {
+    display_comp_ctx->fallback_ = false;
+  }
+}
+
 DisplayError CompManager::SetMaxMixerStages(Handle display_ctx, uint32_t max_mixer_stages) {
   SCOPE_LOCK(locker_);
 
diff --git a/displayengine/libs/core/comp_manager.h b/displayengine/libs/core/comp_manager.h
index 951019b..ae638e0 100644
--- a/displayengine/libs/core/comp_manager.h
+++ b/displayengine/libs/core/comp_manager.h
@@ -47,12 +47,15 @@
   DisplayError PostCommit(Handle display_ctx, HWLayers *hw_layers);
   void Purge(Handle display_ctx);
   bool ProcessIdleTimeout(Handle display_ctx);
+  void ProcessThermalEvent(Handle display_ctx, int64_t thermal_level);
   DisplayError SetMaxMixerStages(Handle display_ctx, uint32_t max_mixer_stages);
 
   // DumpImpl method
   virtual void AppendDump(char *buffer, uint32_t length);
 
  private:
+  static const int kMaxThermalLevel = 3;
+
   void PrepareStrategyConstraints(Handle display_ctx, HWLayers *hw_layers);
 
   struct DisplayCompositionContext {
@@ -64,10 +67,12 @@
     uint32_t remaining_strategies;
     bool idle_fallback;
     bool handle_idle_timeout;
+    bool fallback_;
 
     DisplayCompositionContext()
       : display_resource_ctx(NULL), display_type(kPrimary), max_strategies(0),
-        remaining_strategies(0), idle_fallback(false), handle_idle_timeout(true) { }
+        remaining_strategies(0), idle_fallback(false), handle_idle_timeout(true),
+        fallback_(false) { }
   };
 
   Locker locker_;
diff --git a/displayengine/libs/core/display_base.cpp b/displayengine/libs/core/display_base.cpp
index 964ad16..8725a7b 100644
--- a/displayengine/libs/core/display_base.cpp
+++ b/displayengine/libs/core/display_base.cpp
@@ -313,6 +313,10 @@
     error = hw_intf_->Doze();
     break;
 
+  case kStateDozeSuspend:
+    error = hw_intf_->DozeSuspend();
+    break;
+
   case kStateStandby:
     error = hw_intf_->Standby();
     break;
diff --git a/displayengine/libs/core/display_primary.cpp b/displayengine/libs/core/display_primary.cpp
index de5b2d0..d6116fa 100644
--- a/displayengine/libs/core/display_primary.cpp
+++ b/displayengine/libs/core/display_primary.cpp
@@ -243,5 +243,10 @@
   }
 }
 
+void DisplayPrimary::ThermalEvent(int64_t thermal_level) {
+  SCOPE_LOCK(locker_);
+  comp_manager_->ProcessThermalEvent(display_comp_ctx_, thermal_level);
+}
+
 }  // namespace sde
 
diff --git a/displayengine/libs/core/display_primary.h b/displayengine/libs/core/display_primary.h
index a09975d..be422de 100644
--- a/displayengine/libs/core/display_primary.h
+++ b/displayengine/libs/core/display_primary.h
@@ -61,6 +61,7 @@
   virtual DisplayError VSync(int64_t timestamp);
   virtual DisplayError Blank(bool blank);
   virtual void IdleTimeout();
+  virtual void ThermalEvent(int64_t thermal_level);
 
  private:
   Locker locker_;
diff --git a/displayengine/libs/core/fb/hw_device.cpp b/displayengine/libs/core/fb/hw_device.cpp
index 184dc64..230092a 100644
--- a/displayengine/libs/core/fb/hw_device.cpp
+++ b/displayengine/libs/core/fb/hw_device.cpp
@@ -183,6 +183,10 @@
   return kErrorNone;
 }
 
+DisplayError HWDevice::DozeSuspend() {
+  return kErrorNone;
+}
+
 DisplayError HWDevice::Standby() {
   return kErrorNone;
 }
diff --git a/displayengine/libs/core/fb/hw_device.h b/displayengine/libs/core/fb/hw_device.h
index 07d9e4d..8dca6f9 100644
--- a/displayengine/libs/core/fb/hw_device.h
+++ b/displayengine/libs/core/fb/hw_device.h
@@ -57,6 +57,7 @@
   DisplayError PowerOn();
   DisplayError PowerOff();
   DisplayError Doze();
+  DisplayError DozeSuspend();
   DisplayError Standby();
   DisplayError Validate(HWLayers *hw_layers);
   DisplayError Commit(HWLayers *hw_layers);
@@ -69,7 +70,7 @@
 
   static const int kMaxStringLength = 1024;
   static const int kNumPhysicalDisplays = 2;
-  static const int kNumDisplayEvents = 3;
+  static const int kNumDisplayEvents = 4;
 
   void DumpLayerCommit(mdp_layer_commit &layer_commit);
   DisplayError SetFormat(const LayerBufferFormat &source, uint32_t *target);
diff --git a/displayengine/libs/core/fb/hw_hdmi.cpp b/displayengine/libs/core/fb/hw_hdmi.cpp
index bc97cf6..67fa2c6 100644
--- a/displayengine/libs/core/fb/hw_hdmi.cpp
+++ b/displayengine/libs/core/fb/hw_hdmi.cpp
@@ -222,6 +222,8 @@
   display_attributes->y_pixels = timing_mode->active_v;
   display_attributes->v_total = timing_mode->active_v + timing_mode->front_porch_v +
       timing_mode->back_porch_v + timing_mode->pulse_width_v;
+  display_attributes->h_total = timing_mode->active_h + timing_mode->front_porch_h +
+      timing_mode->back_porch_h + timing_mode->pulse_width_h;
   display_attributes->x_dpi = 0;
   display_attributes->y_dpi = 0;
   display_attributes->fps = FLOAT(timing_mode->refresh_rate) / 1000.0f;
@@ -312,6 +314,10 @@
   return HWDevice::Doze();
 }
 
+DisplayError HWHDMI::DozeSuspend() {
+  return HWDevice::DozeSuspend();
+}
+
 DisplayError HWHDMI::Standby() {
   return HWDevice::Standby();
 }
diff --git a/displayengine/libs/core/fb/hw_hdmi.h b/displayengine/libs/core/fb/hw_hdmi.h
index 8fc3c47..322e664 100644
--- a/displayengine/libs/core/fb/hw_hdmi.h
+++ b/displayengine/libs/core/fb/hw_hdmi.h
@@ -46,6 +46,7 @@
   virtual DisplayError PowerOn();
   virtual DisplayError PowerOff();
   virtual DisplayError Doze();
+  virtual DisplayError DozeSuspend();
   virtual DisplayError Standby();
   virtual DisplayError Validate(HWLayers *hw_layers);
   virtual DisplayError Commit(HWLayers *hw_layers);
diff --git a/displayengine/libs/core/fb/hw_primary.cpp b/displayengine/libs/core/fb/hw_primary.cpp
index 3b22054..7b9cbe0 100644
--- a/displayengine/libs/core/fb/hw_primary.cpp
+++ b/displayengine/libs/core/fb/hw_primary.cpp
@@ -75,7 +75,8 @@
   DisplayError error = kErrorNone;
   char node_path[kMaxStringLength] = {0};
   char data[kMaxStringLength] = {0};
-  const char* event_name[kNumDisplayEvents] = {"vsync_event", "show_blank_event", "idle_notify"};
+  const char* event_name[kNumDisplayEvents] = {"vsync_event", "show_blank_event", "idle_notify",
+                                              "msm_fb_thermal_level"};
 
   error = HWDevice::Init();
   if (error != kErrorNone) {
@@ -190,6 +191,8 @@
   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;
+  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 =
@@ -222,11 +225,26 @@
     IOCTL_LOGE(FB_BLANK_POWERDOWN, device_type_);
     return kErrorHardware;
   }
+
   return kErrorNone;
 }
 
 DisplayError HWPrimary::Doze() {
-  return HWDevice::Doze();
+  if (ioctl_(device_fd_, FBIOBLANK, FB_BLANK_NORMAL) < 0) {
+    IOCTL_LOGE(FB_BLANK_NORMAL, device_type_);
+    return kErrorHardware;
+  }
+
+  return kErrorNone;
+}
+
+DisplayError HWPrimary::DozeSuspend() {
+  if (ioctl_(device_fd_, FBIOBLANK, FB_BLANK_VSYNC_SUSPEND) < 0) {
+    IOCTL_LOGE(FB_BLANK_VSYNC_SUSPEND, device_type_);
+    return kErrorHardware;
+  }
+
+  return kErrorNone;
 }
 
 DisplayError HWPrimary::Standby() {
@@ -285,7 +303,8 @@
   typedef void (HWPrimary::*EventHandler)(char*);
   EventHandler event_handler[kNumDisplayEvents] = { &HWPrimary::HandleVSync,
                                                     &HWPrimary::HandleBlank,
-                                                    &HWPrimary::HandleIdleTimeout };
+                                                    &HWPrimary::HandleIdleTimeout,
+                                                    &HWPrimary::HandleThermal };
 
   while (!exit_threads_) {
     int error = poll_(poll_fds_, kNumDisplayEvents, -1);
@@ -330,6 +349,17 @@
   event_handler_->IdleTimeout();
 }
 
+void HWPrimary::HandleThermal(char *data) {
+  int64_t thermal_level = 0;
+  if (!strncmp(data, "thermal_level=", strlen("thermal_level="))) {
+    thermal_level = strtoull(data + strlen("thermal_level="), NULL, 0);
+  }
+
+  DLOGI("Received thermal notification with thermal level = %d",thermal_level);
+
+  event_handler_->ThermalEvent(thermal_level);
+}
+
 void HWPrimary::SetIdleTimeoutMs(uint32_t timeout_ms) {
   char node_path[kMaxStringLength] = {0};
 
diff --git a/displayengine/libs/core/fb/hw_primary.h b/displayengine/libs/core/fb/hw_primary.h
index b008c92..c41f387 100644
--- a/displayengine/libs/core/fb/hw_primary.h
+++ b/displayengine/libs/core/fb/hw_primary.h
@@ -46,6 +46,7 @@
   virtual DisplayError PowerOn();
   virtual DisplayError PowerOff();
   virtual DisplayError Doze();
+  virtual DisplayError DozeSuspend();
   virtual DisplayError Standby();
   virtual DisplayError Validate(HWLayers *hw_layers);
   virtual DisplayError Commit(HWLayers *hw_layers);
@@ -68,6 +69,7 @@
   void HandleVSync(char *data);
   void HandleBlank(char *data);
   void HandleIdleTimeout(char *data);
+  void HandleThermal(char *data);
 
   pollfd poll_fds_[kNumDisplayEvents];
   pthread_t event_thread_;
diff --git a/displayengine/libs/core/fb/hw_virtual.cpp b/displayengine/libs/core/fb/hw_virtual.cpp
index 81b31d0..374cc45 100644
--- a/displayengine/libs/core/fb/hw_virtual.cpp
+++ b/displayengine/libs/core/fb/hw_virtual.cpp
@@ -110,6 +110,10 @@
   return HWDevice::Doze();
 }
 
+DisplayError HWVirtual::DozeSuspend() {
+  return HWDevice::DozeSuspend();
+}
+
 DisplayError HWVirtual::Standby() {
   return HWDevice::Standby();
 }
diff --git a/displayengine/libs/core/fb/hw_virtual.h b/displayengine/libs/core/fb/hw_virtual.h
index fb7c784..509f1c5 100644
--- a/displayengine/libs/core/fb/hw_virtual.h
+++ b/displayengine/libs/core/fb/hw_virtual.h
@@ -46,6 +46,7 @@
   virtual DisplayError PowerOn();
   virtual DisplayError PowerOff();
   virtual DisplayError Doze();
+  virtual DisplayError DozeSuspend();
   virtual DisplayError Standby();
   virtual DisplayError Validate(HWLayers *hw_layers);
   virtual DisplayError Commit(HWLayers *hw_layers);
diff --git a/displayengine/libs/core/hw_interface.h b/displayengine/libs/core/hw_interface.h
index 44ac367..36cb85e 100644
--- a/displayengine/libs/core/hw_interface.h
+++ b/displayengine/libs/core/hw_interface.h
@@ -149,6 +149,7 @@
   virtual DisplayError VSync(int64_t timestamp) = 0;
   virtual DisplayError Blank(bool blank) = 0;
   virtual void IdleTimeout() = 0;
+  virtual void ThermalEvent(int64_t thermal_level) = 0;
  protected:
   virtual ~HWEventHandler() { }
 };
@@ -166,6 +167,7 @@
   virtual DisplayError PowerOn() = 0;
   virtual DisplayError PowerOff() = 0;
   virtual DisplayError Doze() = 0;
+  virtual DisplayError DozeSuspend() = 0;
   virtual DisplayError Standby() = 0;
   virtual DisplayError Validate(HWLayers *hw_layers) = 0;
   virtual DisplayError Commit(HWLayers *hw_layers) = 0;
diff --git a/displayengine/libs/core/res_manager.cpp b/displayengine/libs/core/res_manager.cpp
index 418e78f..08b055b 100644
--- a/displayengine/libs/core/res_manager.cpp
+++ b/displayengine/libs/core/res_manager.cpp
@@ -115,6 +115,8 @@
 #ifdef USES_SCALAR
   ScalarHelper::GetInstance()->Init();
 #endif
+
+  max_system_bw_ = FLOAT(hw_res_info_.max_bandwidth_high);
   return kErrorNone;
 }
 
@@ -427,7 +429,9 @@
     right_pipe_bw[i] = right_pipe->valid ? GetPipeBw(display_ctx, right_pipe, bpp) : 0;
 
     if ((left_pipe_bw[i] > max_pipe_bw) || (right_pipe_bw[i] > max_pipe_bw)) {
-      DLOGV_IF(kTagResources, "Pipe bandwidth exceeds limit for layer index = %d", i);
+      DLOGV_IF(kTagResources, "Pipe bandwidth exceeds limit for layer index=%d !" \
+               " left_pipe_bw=%f, right_pipe_bw=%f, max_pipe_bw=%f",
+               i, left_pipe_bw[i], right_pipe_bw[i], max_pipe_bw);
       return false;
     }
 
@@ -448,9 +452,14 @@
     last_primary_bw_ = left_mixer_bw + right_mixer_bw;
   }
 
-  // If system has Video mode panel, use max_bandwidth_low, else use max_bandwidth_high
-  if ((display_bw + bw_claimed_) > (hw_res_info_.max_bandwidth_low / 1000000)) {
-    DLOGV_IF(kTagResources, "Overlap bandwidth exceeds limit!");
+  // If system has Video mode panel, then bw limit is max_bandwidth_low
+  if (display_ctx->hw_panel_info_.mode == kModeVideo) {
+    max_system_bw_ = FLOAT(hw_res_info_.max_bandwidth_low);
+  }
+
+  if ((display_bw + bw_claimed_) > (max_system_bw_ / 1000000)) {
+    DLOGV_IF(kTagResources, "Overlap bandwidth: %f exceeds system limit: %f (GBps)!",
+             (display_bw + bw_claimed_), (max_system_bw_ / 1000000));
     return false;
   }
 
@@ -462,7 +471,8 @@
 
   // Apply fudge factor to consider in-efficieny
   if ((system_clk * hw_res_info_.clk_fudge_factor) > max_sde_clk) {
-    DLOGV_IF(kTagResources, "Clock requirement exceeds limit!");
+    DLOGV_IF(kTagResources, "Clock requirement: %f exceeds system limit: %f (MHz)!",
+             (system_clk * hw_res_info_.clk_fudge_factor), max_sde_clk);
     return false;
   }
 
@@ -494,6 +504,15 @@
   // (v_total / v_active) * (v_active / dst_h)
   bw *= FLOAT(display_attributes.v_total) / dst_h;
 
+  // Bandwidth is the rate at which data needs to be fetched from source to MDP (bytes/time).
+  // On Video mode panel, there is no transfer of data from MDP to panel in horizontal blanking
+  // time (hBP + hFP + hPW). So MDP gets this extra time to fetch data from source. But on the
+  // Command mode panel, data gets transferred from MDP to panel during blanking time as well,
+  // which means MDP needs to fetch the data faster. So pipe bandwidth needs to be adjusted.
+  if (display_ctx->hw_panel_info_.mode == kModeCommand) {
+    bw *= FLOAT(display_attributes.h_total) / FLOAT(display_attributes.x_pixels);
+  }
+
   // Bandwidth in GBps
   return (bw / 1000000000.0f);
 }
@@ -1015,12 +1034,12 @@
   case kFormatRGBX8888:
     *output_format = kFormatRGB888;
     break;
+  case kFormatYCrCb420SemiPlanar:
   case kFormatYCbCr420SemiPlanar:
   case kFormatYCbCr420SemiPlanarVenus:
     *output_format = kFormatYCbCr420SemiPlanar;
     break;
   default:
-    *output_format = input_format;
     break;
   }
 
@@ -1036,6 +1055,7 @@
   } else {
     if (hw_res_info_.has_ubwc) {
       switch (input_format) {
+      case kFormatYCrCb420SemiPlanar:
       case kFormatYCbCr420SemiPlanar:
       case kFormatYCbCr420SemiPlanarVenus:
         *output_format = kFormatYCbCr420SPVenusUbwc;
diff --git a/displayengine/libs/core/res_manager.h b/displayengine/libs/core/res_manager.h
index 2219eba..a127645 100644
--- a/displayengine/libs/core/res_manager.h
+++ b/displayengine/libs/core/res_manager.h
@@ -214,6 +214,7 @@
   float bw_claimed_;  // Bandwidth claimed by other display
   float clk_claimed_;  // Clock claimed by other display
   float last_primary_bw_;
+  float max_system_bw_;
   uint32_t virtual_count_;
   struct HWRotator rotators_[kMaxNumRotator];
   BufferAllocator *buffer_allocator_;
diff --git a/displayengine/libs/hwc/hwc_display.cpp b/displayengine/libs/hwc/hwc_display.cpp
index cd21c8a..124310a 100644
--- a/displayengine/libs/hwc/hwc_display.cpp
+++ b/displayengine/libs/hwc/hwc_display.cpp
@@ -27,6 +27,7 @@
 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
+#include <math.h>
 #include <errno.h>
 #include <gralloc_priv.h>
 #include <utils/constants.h>
@@ -108,10 +109,13 @@
     last_power_mode_ = HWC_POWER_MODE_NORMAL;
     break;
   case HWC_POWER_MODE_DOZE:
-  case HWC_POWER_MODE_DOZE_SUSPEND:
     state = kStateDoze;
     last_power_mode_ = HWC_POWER_MODE_DOZE;
     break;
+  case HWC_POWER_MODE_DOZE_SUSPEND:
+    state = kStateDozeSuspend;
+    last_power_mode_ = HWC_POWER_MODE_DOZE_SUSPEND;
+    break;
   default:
     return -EINVAL;
   }
@@ -571,10 +575,10 @@
 }
 
 void HWCDisplay::SetRect(const hwc_frect_t &source, LayerRect *target) {
-  target->left = source.left;
-  target->top = source.top;
-  target->right = source.right;
-  target->bottom = source.bottom;
+  target->left = floorf(source.left);
+  target->top = floorf(source.top);
+  target->right = ceilf(source.right);
+  target->bottom = ceilf(source.bottom);
 }
 
 void HWCDisplay::SetComposition(const int32_t &source, LayerComposition *target) {
diff --git a/libgralloc/alloc_controller.cpp b/libgralloc/alloc_controller.cpp
index 4f342db..3e17061 100644
--- a/libgralloc/alloc_controller.cpp
+++ b/libgralloc/alloc_controller.cpp
@@ -49,6 +49,17 @@
 
 #define ASTC_BLOCK_SIZE 16
 
+#ifdef ION_FLAG_CP_PIXEL
+#define CP_HEAP_ID ION_SECURE_HEAP_ID
+#else
+#define ION_FLAG_CP_PIXEL 0
+#define CP_HEAP_ID ION_CP_MM_HEAP_ID
+#endif
+
+#ifndef ION_FLAG_ALLOW_NON_CONTIG
+#define ION_FLAG_ALLOW_NON_CONTIG 0
+#endif
+
 using namespace gralloc;
 using namespace qdutils;
 
@@ -334,13 +345,22 @@
 
     if(usage & GRALLOC_USAGE_PROTECTED) {
         if (usage & GRALLOC_USAGE_PRIVATE_MM_HEAP) {
-            ionHeapId |= ION_HEAP(ION_CP_MM_HEAP_ID);
+            ionHeapId = ION_HEAP(CP_HEAP_ID);
             ionFlags |= ION_SECURE;
-#ifdef ION_FLAG_ALLOW_NON_CONTIG
+            if (usage & GRALLOC_USAGE_PRIVATE_SECURE_DISPLAY) {
+                /*
+                 * There is currently no flag in ION for Secure Display
+                 * VM. Please add it here once available.
+                 *
+                   ionFlags |= <Ion flag for Secure Display>;
+                */
+            } else {
+                ionFlags |= ION_FLAG_CP_PIXEL;
+            }
+
             if (!(usage & GRALLOC_USAGE_PRIVATE_SECURE_DISPLAY)) {
                 ionFlags |= ION_FLAG_ALLOW_NON_CONTIG;
             }
-#endif
         } else {
             // for targets/OEMs which do not need HW level protection
             // do not set ion secure flag & MM heap. Fallback to system heap.
diff --git a/libgralloc/gpu.cpp b/libgralloc/gpu.cpp
index 9be93d6..a6f7874 100644
--- a/libgralloc/gpu.cpp
+++ b/libgralloc/gpu.cpp
@@ -26,10 +26,19 @@
 #include "memalloc.h"
 #include "alloc_controller.h"
 #include <qdMetaData.h>
+#include <linux/msm_ion.h>
 
 using namespace gralloc;
 
+#define SZ_2M 0x200000
 #define SZ_1M 0x100000
+#define SZ_4K 0x1000
+
+#ifdef ION_FLAG_CP_PIXEL
+#define SECURE_ALIGN SZ_4K
+#else
+#define SECURE_ALIGN SZ_1M
+#endif
 
 gpu_context_t::gpu_context_t(const private_module_t* module,
                              IAllocController* alloc_ctrl ) :
@@ -64,10 +73,14 @@
     else
         data.align = getpagesize();
 
-    /* force 1MB alignment selectively for secure buffers, MDP5 onwards */
     if ((usage & GRALLOC_USAGE_PROTECTED) &&
         (usage & GRALLOC_USAGE_PRIVATE_MM_HEAP)) {
-        data.align = ALIGN((int) data.align, SZ_1M);
+            if (usage & GRALLOC_USAGE_PRIVATE_SECURE_DISPLAY) {
+                /* The alignment here reflects qsee mmu V7L/V8L requirement */
+                data.align = SZ_2M;
+            } else {
+                data.align = SECURE_ALIGN;
+            }
         size = ALIGN(size, data.align);
     }
 
diff --git a/libgralloc/mapper.cpp b/libgralloc/mapper.cpp
index 8b38952..acac5b4 100644
--- a/libgralloc/mapper.cpp
+++ b/libgralloc/mapper.cpp
@@ -328,18 +328,20 @@
                 native_handle_t** handle = va_arg(args, native_handle_t**);
                 private_handle_t* hnd = (private_handle_t*)native_handle_create(
                     private_handle_t::sNumFds, private_handle_t::sNumInts());
-                hnd->magic = private_handle_t::sMagic;
-                hnd->fd = fd;
-                hnd->flags =  private_handle_t::PRIV_FLAGS_USES_ION;
-                hnd->size = size;
-                hnd->offset = offset;
-                hnd->base = uint64_t(base) + offset;
-                hnd->gpuaddr = 0;
-                hnd->width = width;
-                hnd->height = height;
-                hnd->format = format;
-                *handle = (native_handle_t *)hnd;
-                res = 0;
+                if (hnd) {
+                  hnd->magic = private_handle_t::sMagic;
+                  hnd->fd = fd;
+                  hnd->flags =  private_handle_t::PRIV_FLAGS_USES_ION;
+                  hnd->size = size;
+                  hnd->offset = offset;
+                  hnd->base = uint64_t(base) + offset;
+                  hnd->gpuaddr = 0;
+                  hnd->width = width;
+                  hnd->height = height;
+                  hnd->format = format;
+                  *handle = (native_handle_t *)hnd;
+                  res = 0;
+                }
                 break;
 
             }
diff --git a/libhwcomposer/hwc.cpp b/libhwcomposer/hwc.cpp
index 7423c29..1fa40ce 100644
--- a/libhwcomposer/hwc.cpp
+++ b/libhwcomposer/hwc.cpp
@@ -623,7 +623,8 @@
             supported |= HWC_DISPLAY_VIRTUAL_BIT;
             if(!(qdutils::MDPVersion::getInstance().is8x26() ||
                         qdutils::MDPVersion::getInstance().is8x16() ||
-                        qdutils::MDPVersion::getInstance().is8x39()))
+                        qdutils::MDPVersion::getInstance().is8x39() ||
+                        qdutils::MDPVersion::getInstance().is8x52()))
                 supported |= HWC_DISPLAY_EXTERNAL_BIT;
         }
         value[0] = supported;
diff --git a/libhwcomposer/hwc_copybit.cpp b/libhwcomposer/hwc_copybit.cpp
index d7b6278..208fd3e 100644
--- a/libhwcomposer/hwc_copybit.cpp
+++ b/libhwcomposer/hwc_copybit.cpp
@@ -1071,7 +1071,8 @@
     copybit->set_parameter(copybit, COPYBIT_DITHER,
                              (dst.format == HAL_PIXEL_FORMAT_RGB_565)?
                                              COPYBIT_ENABLE : COPYBIT_DISABLE);
-    copybit->set_parameter(copybit, COPYBIT_FG_LAYER, isFG ?
+    copybit->set_parameter(copybit, COPYBIT_FG_LAYER,
+                           (layer->blending == HWC_BLENDING_NONE || isFG ) ?
                                              COPYBIT_ENABLE : COPYBIT_DISABLE);
 
     copybit->set_parameter(copybit, COPYBIT_BLIT_TO_FRAMEBUFFER,
@@ -1200,12 +1201,6 @@
 }
 
 void CopyBit::setReleaseFd(int fd) {
-    if(mRelFd[mCurRenderBufferIndex] >=0)
-        close(mRelFd[mCurRenderBufferIndex]);
-    mRelFd[mCurRenderBufferIndex] = dup(fd);
-}
-
-void CopyBit::setReleaseFdSync(int fd) {
     if (mRelFd[mCurRenderBufferIndex] >=0) {
         int ret = -1;
         ret = sync_wait(mRelFd[mCurRenderBufferIndex], 1000);
diff --git a/libhwcomposer/hwc_copybit.h b/libhwcomposer/hwc_copybit.h
index b67e1b8..993c790 100644
--- a/libhwcomposer/hwc_copybit.h
+++ b/libhwcomposer/hwc_copybit.h
@@ -51,8 +51,6 @@
 
     void setReleaseFd(int fd);
 
-    void setReleaseFdSync(int fd);
-
     bool prepareOverlap(hwc_context_t *ctx, hwc_display_contents_1_t *list);
 
     int drawOverlap(hwc_context_t *ctx, hwc_display_contents_1_t *list);
diff --git a/libhwcomposer/hwc_mdpcomp.cpp b/libhwcomposer/hwc_mdpcomp.cpp
index 087fe1e..3743a8b 100644
--- a/libhwcomposer/hwc_mdpcomp.cpp
+++ b/libhwcomposer/hwc_mdpcomp.cpp
@@ -177,10 +177,11 @@
 
     bool defaultPTOR = false;
     //Enable PTOR when "persist.hwc.ptor.enable" is not defined for
-    //8x16 and 8x39 targets by default
+    //Bear family targets by default
     if((property_get("persist.hwc.ptor.enable", property, NULL) <= 0) &&
             (qdutils::MDPVersion::getInstance().is8x16() ||
-                qdutils::MDPVersion::getInstance().is8x39())) {
+             qdutils::MDPVersion::getInstance().is8x39() ||
+             qdutils::MDPVersion::getInstance().is8x52())) {
         defaultPTOR = true;
     }
 
@@ -532,7 +533,8 @@
         ret = false;
     } else if((qdutils::MDPVersion::getInstance().is8x26() ||
                qdutils::MDPVersion::getInstance().is8x16() ||
-               qdutils::MDPVersion::getInstance().is8x39()) &&
+               qdutils::MDPVersion::getInstance().is8x39() ||
+               qdutils::MDPVersion::getInstance().is8x52()) &&
             ctx->mVideoTransFlag &&
             isSecondaryConnected(ctx)) {
         //1 Padding round to shift pipes across mixers
@@ -541,7 +543,8 @@
         ret = false;
     } else if((qdutils::MDPVersion::getInstance().is8x26() ||
                qdutils::MDPVersion::getInstance().is8x16() ||
-               qdutils::MDPVersion::getInstance().is8x39()) &&
+               qdutils::MDPVersion::getInstance().is8x39() ||
+               qdutils::MDPVersion::getInstance().is8x52()) &&
               !mDpy && isSecondaryAnimating(ctx) &&
               isYuvPresent(ctx,HWC_DISPLAY_VIRTUAL)) {
         ALOGD_IF(isDebug(),"%s: Display animation in progress",
@@ -924,6 +927,15 @@
         }
     }
 
+    if(!mDpy && isSecondaryConnected(ctx) &&
+           (qdutils::MDPVersion::getInstance().is8x16() ||
+            qdutils::MDPVersion::getInstance().is8x26() ||
+            qdutils::MDPVersion::getInstance().is8x39()) &&
+           isYuvPresent(ctx, HWC_DISPLAY_VIRTUAL)) {
+        ALOGD_IF(isDebug(), "%s: YUV layer present on secondary", __FUNCTION__);
+        return false;
+    }
+
     mCurrentFrame.fbCount = 0;
     memcpy(&mCurrentFrame.isFBComposed, &mCurrentFrame.drop,
            sizeof(mCurrentFrame.isFBComposed));
@@ -982,6 +994,15 @@
         }
     }
 
+    if(!mDpy && isSecondaryConnected(ctx) &&
+           (qdutils::MDPVersion::getInstance().is8x16() ||
+            qdutils::MDPVersion::getInstance().is8x26() ||
+            qdutils::MDPVersion::getInstance().is8x39()) &&
+           isYuvPresent(ctx, HWC_DISPLAY_VIRTUAL)) {
+        ALOGD_IF(isDebug(), "%s: YUV layer present on secondary", __FUNCTION__);
+        return false;
+    }
+
     /* We cannot use this composition mode, if:
      1. A below layer needs scaling.
      2. Overlap is not peripheral to display.
diff --git a/libhwcomposer/hwc_utils.cpp b/libhwcomposer/hwc_utils.cpp
index 8efe025..aeda428 100644
--- a/libhwcomposer/hwc_utils.cpp
+++ b/libhwcomposer/hwc_utils.cpp
@@ -554,7 +554,37 @@
     }
 }
 
-//Helper to roundoff the refreshrates
+uint32_t getRefreshRate(hwc_context_t* ctx, uint32_t requestedRefreshRate) {
+
+    qdutils::MDPVersion& mdpHw = qdutils::MDPVersion::getInstance();
+    int dpy = HWC_DISPLAY_PRIMARY;
+    uint32_t defaultRefreshRate = ctx->dpyAttr[dpy].refreshRate;
+    uint32_t rate = defaultRefreshRate;
+
+    if(!requestedRefreshRate)
+        return defaultRefreshRate;
+
+    uint32_t maxNumIterations =
+            (uint32_t)ceil(
+                    (float)mdpHw.getMaxFpsSupported()/
+                    (float)requestedRefreshRate);
+
+    for(uint32_t i = 1; i <= maxNumIterations; i++) {
+        rate = roundOff(i * requestedRefreshRate);
+        if(rate < mdpHw.getMinFpsSupported()) {
+            continue;
+        } else if((rate >= mdpHw.getMinFpsSupported() &&
+                   rate <= mdpHw.getMaxFpsSupported())) {
+            break;
+        } else {
+            rate = defaultRefreshRate;
+            break;
+        }
+    }
+    return rate;
+}
+
+//Helper to roundoff the refreshrates to the std refresh-rates
 uint32_t roundOff(uint32_t refreshRate) {
     int count =  (int) (sizeof(stdRefreshRates)/sizeof(stdRefreshRates[0]));
     uint32_t rate = refreshRate;
@@ -1175,21 +1205,18 @@
 
 #ifdef DYNAMIC_FPS
         if (!dpy && mdpHw.isDynFpsSupported() && ctx->mUseMetaDataRefreshRate){
-            //dyn fps: get refreshrate from metadata
-            //Support multiple refresh rates if they are same
-            //else set to  default
+            /* Dyn fps: get refreshrate from metadata */
             MetaData_t *mdata = hnd ? (MetaData_t *)hnd->base_metadata : NULL;
             if (mdata && (mdata->operation & UPDATE_REFRESH_RATE)) {
                 // Valid refreshRate in metadata and within the range
-                uint32_t rate = roundOff(mdata->refreshrate);
-                if((rate >= mdpHw.getMinFpsSupported() &&
-                                rate <= mdpHw.getMaxFpsSupported())) {
-                    if (!refreshRate) {
-                        refreshRate = rate;
-                    } else if(refreshRate != rate) {
-                        // multiple refreshrate requests, set to default
-                        refreshRate = ctx->dpyAttr[dpy].refreshRate;
-                    }
+                uint32_t rate = getRefreshRate(ctx, mdata->refreshrate);
+                if (!refreshRate) {
+                    refreshRate = rate;
+                } else if(refreshRate != rate) {
+                    /* Support multiple refresh rates if they are same
+                     * else set to default.
+                     */
+                    refreshRate = ctx->dpyAttr[dpy].refreshRate;
                 }
             }
         }
@@ -1594,34 +1621,9 @@
     }
 }
 
-int hwc_sync(hwc_context_t *ctx, hwc_display_contents_1_t* list, int dpy,
-        int fd) {
+void hwc_sync_rotator(hwc_context_t *ctx, hwc_display_contents_1_t* list,
+        int dpy) {
     ATRACE_CALL();
-    int ret = 0;
-    int acquireFd[MAX_NUM_APP_LAYERS];
-    int count = 0;
-    int releaseFd = -1;
-    int retireFd = -1;
-    int fbFd = -1;
-    bool swapzero = false;
-
-    struct mdp_buf_sync data;
-    memset(&data, 0, sizeof(data));
-    data.acq_fen_fd = acquireFd;
-    data.rel_fen_fd = &releaseFd;
-    data.retire_fen_fd = &retireFd;
-    data.flags = MDP_BUF_SYNC_FLAG_RETIRE_FENCE;
-
-    char property[PROPERTY_VALUE_MAX];
-    if(property_get("debug.egl.swapinterval", property, "1") > 0) {
-        if(atoi(property) == 0)
-            swapzero = true;
-    }
-
-    bool isExtAnimating = false;
-    if(dpy)
-       isExtAnimating = ctx->listStats[dpy].isDisplayAnimating;
-
     //Send acquireFenceFds to rotator
     for(uint32_t i = 0; i < ctx->mLayerRotMap[dpy]->getCount(); i++) {
         int rotFd = ctx->mRotMgr->getRotDevFd();
@@ -1641,7 +1643,7 @@
             rotData.acq_fen_fd_cnt = 1; //1 ioctl call per rot session
         }
         int ret = 0;
-        if(LIKELY(!swapzero) and (not ctx->mLayerRotMap[dpy]->isRotCached(i)))
+        if(not ctx->mLayerRotMap[dpy]->isRotCached(i))
             ret = ioctl(rotFd, MSMFB_BUFFER_SYNC, &rotData);
 
         if(ret < 0) {
@@ -1659,58 +1661,61 @@
                     rotReleaseFd;
         }
     }
+}
+
+int hwc_sync_mdss(hwc_context_t *ctx, hwc_display_contents_1_t *list, int dpy,
+        bool isExtAnimating, int fd) {
+    ATRACE_CALL();
+    int ret = 0;
+    int acquireFd[MAX_NUM_APP_LAYERS];
+    int count = 0;
+    int releaseFd = -1;
+    int retireFd = -1;
+    int fbFd = ctx->dpyAttr[dpy].fd;
+
+    struct mdp_buf_sync data;
+    memset(&data, 0, sizeof(data));
+    data.acq_fen_fd = acquireFd;
+    data.rel_fen_fd = &releaseFd;
+    data.retire_fen_fd = &retireFd;
+    data.flags = MDP_BUF_SYNC_FLAG_RETIRE_FENCE;
 
     //Accumulate acquireFenceFds for MDP Overlays
     if(list->outbufAcquireFenceFd >= 0) {
         //Writeback output buffer
-        if(LIKELY(!swapzero) )
-            acquireFd[count++] = list->outbufAcquireFenceFd;
+        acquireFd[count++] = list->outbufAcquireFenceFd;
     }
 
     for(uint32_t i = 0; i < list->numHwLayers; i++) {
         if(((isAbcInUse(ctx)== true ) ||
           (list->hwLayers[i].compositionType == HWC_OVERLAY)) &&
                         list->hwLayers[i].acquireFenceFd >= 0) {
-            if(LIKELY(!swapzero) ) {
-                // if ABC is enabled for more than one layer.
-                // renderBufIndexforABC will work as FB.Hence
-                // set the acquireFD from fd - which is coming from copybit
-                if(fd >= 0 && (isAbcInUse(ctx) == true)) {
-                    if(ctx->listStats[dpy].renderBufIndexforABC ==(int32_t)i)
-                        acquireFd[count++] = fd;
-                    else
-                        continue;
-                } else
-                    acquireFd[count++] = list->hwLayers[i].acquireFenceFd;
-            }
+            // if ABC is enabled for more than one layer.
+            // renderBufIndexforABC will work as FB.Hence
+            // set the acquireFD from fd - which is coming from copybit
+            if(fd >= 0 && (isAbcInUse(ctx) == true)) {
+                if(ctx->listStats[dpy].renderBufIndexforABC ==(int32_t)i)
+                    acquireFd[count++] = fd;
+                else
+                    continue;
+            } else
+                acquireFd[count++] = list->hwLayers[i].acquireFenceFd;
         }
         if(list->hwLayers[i].compositionType == HWC_FRAMEBUFFER_TARGET) {
-            if(LIKELY(!swapzero) ) {
-                if(fd >= 0) {
-                    //set the acquireFD from fd - which is coming from c2d
-                    acquireFd[count++] = fd;
-                    // Buffer sync IOCTL should be async when using c2d fence is
-                    // used
-                    data.flags &= ~MDP_BUF_SYNC_FLAG_WAIT;
-                } else if(list->hwLayers[i].acquireFenceFd >= 0)
-                    acquireFd[count++] = list->hwLayers[i].acquireFenceFd;
-            }
+            if(fd >= 0) {
+                //set the acquireFD from fd - which is coming from c2d
+                acquireFd[count++] = fd;
+                // Buffer sync IOCTL should be async when using c2d fence
+                data.flags &= ~MDP_BUF_SYNC_FLAG_WAIT;
+            } else if(list->hwLayers[i].acquireFenceFd >= 0)
+                acquireFd[count++] = list->hwLayers[i].acquireFenceFd;
         }
     }
 
-    if ((fd >= 0) && !dpy && ctx->mPtorInfo.isActive()) {
-        // Acquire c2d fence of Overlap render buffer
-        if(LIKELY(!swapzero) )
-            acquireFd[count++] = fd;
-    }
-
     data.acq_fen_fd_cnt = count;
-    fbFd = ctx->dpyAttr[dpy].fd;
 
     //Waits for acquire fences, returns a release fence
-    if(LIKELY(!swapzero)) {
-        ret = ioctl(fbFd, MSMFB_BUFFER_SYNC, &data);
-    }
+    ret = ioctl(fbFd, MSMFB_BUFFER_SYNC, &data);
 
     if(ret < 0) {
         ALOGE("%s: ioctl MSMFB_BUFFER_SYNC failed, err=%s",
@@ -1731,9 +1736,7 @@
 #endif
            list->hwLayers[i].compositionType == HWC_FRAMEBUFFER_TARGET) {
             //Populate releaseFenceFds.
-            if(UNLIKELY(swapzero)) {
-                list->hwLayers[i].releaseFenceFd = -1;
-            } else if(isExtAnimating) {
+            if(isExtAnimating) {
                 // Release all the app layer fds immediately,
                 // if animation is in progress.
                 list->hwLayers[i].releaseFenceFd = -1;
@@ -1760,16 +1763,11 @@
         }
     }
 
-    if(fd >= 0) {
-        close(fd);
-        fd = -1;
-    }
-
     if (ctx->mCopyBit[dpy]) {
-        if (!dpy && ctx->mPtorInfo.isActive())
-            ctx->mCopyBit[dpy]->setReleaseFdSync(releaseFd);
-        else
+        if((!dpy && ctx->mPtorInfo.isActive()) or
+           ctx->mMDP.version < qdutils::MDP_V4_0) {
             ctx->mCopyBit[dpy]->setReleaseFd(releaseFd);
+        }
     }
 
     //Signals when MDP finishes reading rotator buffers.
@@ -1777,11 +1775,59 @@
     close(releaseFd);
     releaseFd = -1;
 
-    if(UNLIKELY(swapzero)) {
-        list->retireFenceFd = -1;
-    } else {
-        list->retireFenceFd = retireFd;
+    list->retireFenceFd = retireFd;
+
+    return ret;
+}
+
+void hwc_sync_sz(hwc_context_t* ctx, hwc_display_contents_1_t* list, int dpy) {
+    ATRACE_CALL();
+    for(uint32_t i = 0; i < list->numHwLayers; i++) {
+        list->hwLayers[i].releaseFenceFd = -1;
     }
+
+    if (ctx->mCopyBit[dpy]) {
+        if((!dpy && ctx->mPtorInfo.isActive()) or
+           ctx->mMDP.version < qdutils::MDP_V4_0) {
+            ctx->mCopyBit[dpy]->setReleaseFd(-1);
+        }
+    }
+
+    ctx->mLayerRotMap[dpy]->setReleaseFd(-1);
+
+    list->retireFenceFd = -1;
+}
+
+int hwc_sync(hwc_context_t *ctx, hwc_display_contents_1_t* list, int dpy,
+        int fd) {
+    ATRACE_CALL();
+    int ret = 0;
+
+    bool isExtAnimating = false;
+    if(dpy)
+        isExtAnimating = ctx->listStats[dpy].isDisplayAnimating;
+
+    bool swapzero = false;
+    char property[PROPERTY_VALUE_MAX];
+    if(property_get("debug.egl.swapinterval", property, "1") > 0) {
+        if(atoi(property) == 0)
+            swapzero = true;
+    }
+
+    if(swapzero) {
+        hwc_sync_sz(ctx, list, dpy);
+    } else {
+        hwc_sync_rotator(ctx, list, dpy);
+        ret = hwc_sync_mdss(ctx, list, dpy,
+                            isExtAnimating, fd);
+    }
+
+    if(fd >= 0) {
+        close(fd);
+        fd = -1;
+    }
+
+
     return ret;
 }
 
diff --git a/libhwcomposer/hwc_utils.h b/libhwcomposer/hwc_utils.h
index f0f8e77..da0182b 100644
--- a/libhwcomposer/hwc_utils.h
+++ b/libhwcomposer/hwc_utils.h
@@ -352,6 +352,8 @@
 void getAspectRatioPosition(hwc_context_t* ctx, int dpy, int extOrientation,
                                 hwc_rect_t& inRect, hwc_rect_t& outRect);
 
+uint32_t getRefreshRate(hwc_context_t* ctx, uint32_t requestedRefreshRate);
+
 uint32_t roundOff(uint32_t refreshRate);
 
 void setRefreshRate(hwc_context_t *ctx, int dpy, uint32_t refreshRate);
@@ -395,6 +397,17 @@
 //Close acquireFenceFds of all layers of incoming list
 void closeAcquireFds(hwc_display_contents_1_t* list);
 
+//Sync point impl if swapinterval is set to 0
+void hwc_sync_sz(hwc_context_t* ctx, hwc_display_contents_1_t* list, int dpy);
+
+//Sync point impl for rotator
+void hwc_sync_rotator(hwc_context_t *ctx, hwc_display_contents_1_t* list,
+        int dpy);
+
+//Sync point impl for mdss
+int hwc_sync_mdss(hwc_context_t *ctx, hwc_display_contents_1_t *list, int dpy,
+        bool isExtAnimating, int fd);
+
 //Sync point impl.
 int hwc_sync(hwc_context_t *ctx, hwc_display_contents_1_t* list, int dpy,
         int fd);
diff --git a/liboverlay/overlay.cpp b/liboverlay/overlay.cpp
index b7c7fcc..113bd48 100644
--- a/liboverlay/overlay.cpp
+++ b/liboverlay/overlay.cpp
@@ -149,6 +149,8 @@
         return getPipe_8x16(pipeSpecs);
     } else if(MDPVersion::getInstance().is8x39()) {
         return getPipe_8x39(pipeSpecs);
+    } else if(MDPVersion::getInstance().is8x52()) {
+        return getPipe_8x52(pipeSpecs);
     } else if(MDPVersion::getInstance().is8994()) {
         return getPipe_8994(pipeSpecs);
     } else if(MDPVersion::getInstance().is8992()) {
@@ -247,6 +249,12 @@
     return getPipe_8x16(pipeSpecs);
 }
 
+utils::eDest Overlay::getPipe_8x52(const PipeSpecs& pipeSpecs) {
+    //8x16 & 8x52 has same number of pipes, pipe-types & scaling capabilities.
+    //Rely on 8x16 until we see a need to change.
+    return getPipe_8x16(pipeSpecs);
+}
+
 utils::eDest Overlay::getPipe_8994(const PipeSpecs& pipeSpecs) {
     //If DMA pipes need to be used in block mode for downscale, there could be
     //cases where consecutive rounds need separate modes, which cannot be
diff --git a/liboverlay/overlay.h b/liboverlay/overlay.h
index 49be930..2782fc2 100644
--- a/liboverlay/overlay.h
+++ b/liboverlay/overlay.h
@@ -177,6 +177,7 @@
     utils::eDest getPipe_8x26(const PipeSpecs& pipeSpecs);
     utils::eDest getPipe_8x16(const PipeSpecs& pipeSpecs);
     utils::eDest getPipe_8x39(const PipeSpecs& pipeSpecs);
+    utils::eDest getPipe_8x52(const PipeSpecs& pipeSpecs);
     utils::eDest getPipe_8994(const PipeSpecs& pipeSpecs);
     utils::eDest getPipe_8992(const PipeSpecs& pipeSpecs);
 
@@ -344,7 +345,8 @@
 inline bool Overlay::isUIScalingOnExternalSupported() {
     if(qdutils::MDPVersion::getInstance().is8x26() or
        qdutils::MDPVersion::getInstance().is8x16() or
-       qdutils::MDPVersion::getInstance().is8x39()) {
+       qdutils::MDPVersion::getInstance().is8x39() or
+       qdutils::MDPVersion::getInstance().is8x52()) {
         return false;
     }
     return true;
diff --git a/libqdutils/display_config.cpp b/libqdutils/display_config.cpp
index 350192d..0c62ffe 100644
--- a/libqdutils/display_config.cpp
+++ b/libqdutils/display_config.cpp
@@ -440,3 +440,12 @@
     ret = screenRefresh();
     return ret;
 }
+
+// ----------------------------------------------------------------------------
+// Native daemons needs to send enable partial update ack for PU to enable
+// ----------------------------------------------------------------------------
+extern "C" int setPartialUpdateState() {
+    int ret = 0;
+    ret = setPartialUpdate(IQService::ENABLE_PARTIAL_UPDATE);
+    return ret;
+}
diff --git a/libqdutils/mdp_version.cpp b/libqdutils/mdp_version.cpp
index c02e28d..f62f3d0 100644
--- a/libqdutils/mdp_version.cpp
+++ b/libqdutils/mdp_version.cpp
@@ -77,6 +77,15 @@
 #ifndef MDSS_MDP_HW_REV_110
 #define MDSS_MDP_HW_REV_110 0x100a0000 //8992
 #endif
+#ifndef MDSS_MDP_HW_REV_111
+#define MDSS_MDP_HW_REV_111 0x100b0000 //Unused or Next version
+#endif
+#ifndef MDSS_MDP_HW_REV_112
+#define MDSS_MDP_HW_REV_112 0x100c0000 // 8x52
+#endif
+#ifndef MDSS_MDP_HW_REV_113
+#define MDSS_MDP_HW_REV_113 0x100d0000 //Unused Next version
+#endif
 #ifndef MDSS_MDP_HW_REV_200
 #define MDSS_MDP_HW_REV_200 0x20000000 //8092
 #endif
@@ -516,5 +525,10 @@
             mMdpRev < MDSS_MDP_HW_REV_200));
 }
 
+bool MDPVersion::is8x52() {
+    return (mMdpRev >= MDSS_MDP_HW_REV_112 and
+            mMdpRev < MDSS_MDP_HW_REV_113);
+}
+
 }; //namespace qdutils
 
diff --git a/libqdutils/mdp_version.h b/libqdutils/mdp_version.h
index 6ebe558..25356f8 100644
--- a/libqdutils/mdp_version.h
+++ b/libqdutils/mdp_version.h
@@ -153,6 +153,7 @@
     bool is8994();
     bool is8x16();
     bool is8x39();
+    bool is8x52();
     bool is8992();
     bool updateSplitInfo();
 
diff --git a/libqservice/IQService.h b/libqservice/IQService.h
index 5054578..1f28cee 100644
--- a/libqservice/IQService.h
+++ b/libqservice/IQService.h
@@ -88,8 +88,8 @@
     };
 
     enum {
-        PREF_PARTIAL_UPDATE,
         PREF_POST_PROCESSING,
+        PREF_PARTIAL_UPDATE,
         ENABLE_PARTIAL_UPDATE,
     };