Merge "gralloc: Add support for HEIF usage flag."
diff --git a/Makefile.am b/Makefile.am
index 8ecc86b..991d981 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -2,4 +2,4 @@
 
 ACLOCAL_AMFLAGS = -I m4
 
-SUBDIRS = libqservice libqdutils sdm/libs/utils sdm/libs/core
+SUBDIRS = libqservice libdebug libdrmutils sdm/libs/utils sdm/libs/core libqdutils
diff --git a/configure.ac b/configure.ac
index 24c41fd..c9de521 100644
--- a/configure.ac
+++ b/configure.ac
@@ -31,7 +31,15 @@
 AC_ARG_WITH(sanitized-headers,
    AS_HELP_STRING([--with-sanitized-headers=DIR],
        [Specify the location of the sanitized Linux headers]),
-   [CPPFLAGS="$CPPFLAGS -idirafter $withval"])
+   [CPPFLAGS="$CPPFLAGS -I$withval"])
+
+AC_ARG_ENABLE([sdmhaldrm],
+     AC_HELP_STRING([--enable-sdmhaldrm],
+        [enable sdmhaldrm, build display-hal-linux with sdmhaldrm]),
+        [enable_sdmhaldrm="${enableval}"],
+        enable_sdmhaldrm=no)
+
+AM_CONDITIONAL([ENABLE_SDMHALDRM], [test "x${enable_sdmhaldrm}" = "xyes"])
 
 # Checks for programs.
 AC_PROG_CC
@@ -50,6 +58,8 @@
         Makefile \
         libqservice/Makefile \
         libqdutils/Makefile \
+        libdebug/Makefile \
+        libdrmutils/Makefile \
         sdm/libs/utils/Makefile \
         sdm/libs/core/Makefile
         ])
diff --git a/gralloc/gr_buf_mgr.cpp b/gralloc/gr_buf_mgr.cpp
index a569184..9a25a8e 100644
--- a/gralloc/gr_buf_mgr.cpp
+++ b/gralloc/gr_buf_mgr.cpp
@@ -101,6 +101,10 @@
 }
 
 Error BufferManager::ImportHandleLocked(private_handle_t *hnd) {
+  if (private_handle_t::validate(hnd) != 0) {
+    ALOGE("ImportHandleLocked: Invalid handle: %p", hnd);
+    return Error::BAD_BUFFER;
+  }
   ALOGD_IF(DEBUG, "Importing handle:%p id: %" PRIu64, hnd, hnd->id);
   int ion_handle = allocator_->ImportBuffer(hnd->fd);
   if (ion_handle < 0) {
diff --git a/gralloc/gr_priv_handle.h b/gralloc/gr_priv_handle.h
index 39e5e20..ace762e 100644
--- a/gralloc/gr_priv_handle.h
+++ b/gralloc/gr_priv_handle.h
@@ -132,12 +132,14 @@
   static int validate(const native_handle *h) {
     auto *hnd = static_cast<const private_handle_t *>(h);
     if (!h || h->version != sizeof(native_handle) || h->numInts != NumInts() ||
-        h->numFds != kNumFds || hnd->magic != kMagic) {
-      ALOGE(
-          "Invalid gralloc handle (at %p): ver(%d/%zu) ints(%d/%d) fds(%d/%d) "
-          "magic(%c%c%c%c/%c%c%c%c)",
+        h->numFds != kNumFds) {
+      ALOGE("Invalid gralloc handle (at %p): ver(%d/%zu) ints(%d/%d) fds(%d/%d) ",
           h, h ? h->version : -1, sizeof(native_handle), h ? h->numInts : -1, NumInts(),
-          h ? h->numFds : -1, kNumFds,
+          h ? h->numFds : -1, kNumFds);
+      return -EINVAL;
+    }
+    if (hnd->magic != kMagic) {
+       ALOGE("magic(%c%c%c%c/%c%c%c%c)",
           hnd ? (((hnd->magic >> 24) & 0xFF) ? ((hnd->magic >> 24) & 0xFF) : '-') : '?',
           hnd ? (((hnd->magic >> 16) & 0xFF) ? ((hnd->magic >> 16) & 0xFF) : '-') : '?',
           hnd ? (((hnd->magic >> 8) & 0xFF) ? ((hnd->magic >> 8) & 0xFF) : '-') : '?',
diff --git a/libdebug/Makefile.am b/libdebug/Makefile.am
new file mode 100644
index 0000000..41a4445
--- /dev/null
+++ b/libdebug/Makefile.am
@@ -0,0 +1,14 @@
+h_sources = debug_handler.h
+
+cpp_sources = debug_handler.cpp
+
+library_includedir = $(includedir)
+library_include_HEADERS = $(h_sources)
+
+lib_LTLIBRARIES = libdisplaydebug.la
+libdisplaydebug_la_CC = @CC@
+libdisplaydebug_la_SOURCES = $(cpp_sources)
+libdisplaydebug_la_CFLAGS = $(COMMON_CFLAGS) -DLOG_TAG=\"SDM\"
+libdisplaydebug_la_CPPFLAGS = $(AM_CPPFLAGS)
+libdisplaydebug_la_LIBADD = -ldl
+libdisplaydebug_la_LDFLAGS = -shared -avoid-version
diff --git a/libdrmutils/Makefile.am b/libdrmutils/Makefile.am
new file mode 100644
index 0000000..a04c874
--- /dev/null
+++ b/libdrmutils/Makefile.am
@@ -0,0 +1,17 @@
+HEADER_PATH := ${WORKSPACE}/display/display-hal/libdrmutils
+
+cpp_sources = drm_lib_loader.cpp \
+              drm_master.cpp \
+              drm_res_mgr.cpp
+
+drmutils_h_sources = $(HEADER_PATH)/*.h
+drmutils_includedir = $(includedir)
+drmutils_include_HEADERS = $(drmutils_h_sources)
+
+lib_LTLIBRARIES = libdrmutils.la
+libdrmutils_la_CC = @CC@
+libdrmutils_la_SOURCES = $(cpp_sources)
+libdrmutils_la_CFLAGS = $(COMMON_CFLAGS) -DLOG_TAG=\"DRMUTILS\"
+libdrmutils_la_CPPFLAGS = $(AM_CPPFLAGS)
+libsdmcore_la_LIBADD = -ldrm
+libdrmutils_la_LDFLAGS = -shared -avoid-version
diff --git a/libdrmutils/drm_interface.h b/libdrmutils/drm_interface.h
index 4598ad5..0fe0d2c 100644
--- a/libdrmutils/drm_interface.h
+++ b/libdrmutils/drm_interface.h
@@ -38,6 +38,7 @@
 #include "xf86drm.h"
 #include "xf86drmMode.h"
 #include <drm/msm_drm.h>
+#include <drm/msm_drm_pp.h>
 
 namespace sde_drm {
 
@@ -667,6 +668,7 @@
   kFeatureAd4Init,
   kFeatureAd4Cfg,
   kFeatureAd4Input,
+  kFeatureAd4Roi,
   kFeatureAd4Backlight,
   kFeatureAd4Assertiveness,
   kFeatureAd4ManualStrength,
diff --git a/libqdutils/Makefile.am b/libqdutils/Makefile.am
index 01fbf19..d0241d0 100644
--- a/libqdutils/Makefile.am
+++ b/libqdutils/Makefile.am
@@ -1,32 +1,16 @@
-h_sources = qdMetaData.h
-
-cpp_sources = qdMetaData.cpp
-
-library_includedir = $(includedir)
-library_include_HEADERS = $(h_sources)
-
-lib_LTLIBRARIES = libqdMetaData.la
-libqdMetaData_la_CC = @CC@
-libqdMetaData_la_SOURCES = $(cpp_sources)
-libqdMetaData_la_CFLAGS = $(AM_CFLAGS) -DLOG_TAG=\"DisplayMetaData\"
-libqdMetaData_la_CPPFLAGS = $(AM_CPPFLAGS)
-libqdMetaData_LDADD = -lcutils -llog
-libqdMetaData_la_LDFLAGS = -shared -avoid-version
-
 header_sources = display_config.h
 
-c_sources = profiler.cpp \
-            qd_utils.cpp \
-            display_config.cpp
+cpp_sources = qd_utils.cpp \
+              display_config.cpp
 
-library_includedir = $(includedir)
-library_include_HEADERS = $(header_sources)
+qdutils_includedir = $(pkgincludedir)/display
+qdutils_include_HEADERS = $(header_sources)
 
-lib_LTLIBRARIES += libqdutils.la
+lib_LTLIBRARIES = libqdutils.la
 libqdutils_la_CC = @CC@
 libqdutils_la_SOURCES = $(c_sources)
 libqdutils_la_CFLAGS = $(COMMON_CFLAGS) -DLOG_TAG=\"qdutils\"
 libqdutils_la_CPPFLAGS = $(AM_CPPFLAGS)
 libqdutils_LDADD = -lhardware -lcutils -llog -lbinder
 libqdutils_la_LIBADD = ../libqservice/libqservice.la
-libqdutils_la_LDFLAGS = -shared -avoid-version
\ No newline at end of file
+libqdutils_la_LDFLAGS = -shared -avoid-version
diff --git a/libqservice/IQService.h b/libqservice/IQService.h
index 929f7b6..11cbf22 100644
--- a/libqservice/IQService.h
+++ b/libqservice/IQService.h
@@ -80,6 +80,7 @@
         SET_QSYNC_MODE = 38, // Set qsync mode. 0 - (none)disable qsync, 1 - continuous mode.
         SET_COLOR_MODE_WITH_RENDER_INTENT = 39,
         SET_IDLE_PC = 40, // Enable/disable Idle power collapse
+        SET_DPPS_AD4_ROI_CONFIG = 41, // Set ad4 roi config for debug
         COMMAND_LIST_END = 400,
     };
 
diff --git a/libqservice/Makefile.am b/libqservice/Makefile.am
index 79935b8..a8c9f6a 100644
--- a/libqservice/Makefile.am
+++ b/libqservice/Makefile.am
@@ -1,18 +1,21 @@
 h_sources = IQService.h \
-            IQClient.h
+            IQClient.h \
+            QService.h \
+            QServiceUtils.h \
+            IQHDMIClient.h
 
 cpp_sources = QService.cpp \
               IQService.cpp \
               IQClient.cpp \
               IQHDMIClient.cpp
 
-library_includedir = $(includedir)
-library_include_HEADERS = $(h_sources)
+qservice_includedir = $(pkgincludedir)/display
+qservice_include_HEADERS = $(h_sources)
 
 lib_LTLIBRARIES = libqservice.la
 libqservice_la_CC = @CC@
 libqservice_la_SOURCES = $(cpp_sources)
 libqservice_la_CFLAGS = $(COMMON_CFLAGS) -DLOG_TAG=\"qdqservice\"
 libqservice_la_CPPFLAGS = $(AM_CPPFLAGS)
-libqservice_LDADD = -lhardware -lcutils -llog -lbinder
+libqservice_la_LIBADD = -lhardware -lcutils -llog -lbinder
 libqservice_la_LDFLAGS = -shared -avoid-version
\ No newline at end of file
diff --git a/sdm/include/core/display_interface.h b/sdm/include/core/display_interface.h
index 758a010..7cac5e1 100644
--- a/sdm/include/core/display_interface.h
+++ b/sdm/include/core/display_interface.h
@@ -163,6 +163,16 @@
   kQsyncModeOneShot,     // This is set by client to enable qsync only for current frame.
 };
 
+/*! @brief This structure defines configuration for display dpps ad4 region of interest. */
+struct DisplayDppsAd4RoiCfg {
+  uint32_t h_start;     //!< start in hotizontal direction
+  uint32_t h_end;       //!< end in hotizontal direction
+  uint32_t v_start;     //!< start in vertical direction
+  uint32_t v_end;       //!< end in vertical direction
+  uint32_t factor_in;   //!< the strength factor of inside ROI region
+  uint32_t factor_out;  //!< the strength factor of outside ROI region
+};
+
 /*! @brief This structure defines configuration for fixed properties of a display device.
 
   @sa DisplayInterface::GetConfig
@@ -409,13 +419,16 @@
   /*! @brief Method to set current state of the display device.
 
     @param[in] state \link DisplayState \endlink
+    @param[in] flag to force full bridge teardown for pluggable displays, no-op for other displays,
+               if requested state is kStateOff
     @param[in] pointer to release fence
 
     @return \link DisplayError \endlink
 
     @sa SetDisplayState
   */
-  virtual DisplayError SetDisplayState(DisplayState state, int *release_fence) = 0;
+  virtual DisplayError SetDisplayState(DisplayState state, bool teardown,
+                                       int *release_fence) = 0;
 
   /*! @brief Method to set active configuration for variable properties of the display device.
 
@@ -730,6 +743,15 @@
   */
   virtual DisplayError HandleSecureEvent(SecureEvent secure_event) = 0;
 
+  /*! @brief Method to set dpps ad roi.
+
+    @param[in] roi config parmas
+
+    @return \link DisplayError \endlink
+  */
+
+  virtual DisplayError SetDisplayDppsAdROI(void *payload) = 0;
+
   /*! @brief Method to set the Qsync mode.
 
   @param[in] qsync_mode: \link QSyncMode \endlink
diff --git a/sdm/include/private/color_interface.h b/sdm/include/private/color_interface.h
index 884df5e..feaea30 100644
--- a/sdm/include/private/color_interface.h
+++ b/sdm/include/private/color_interface.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2017, The Linux Foundataion. All rights reserved.
+/* Copyright (c) 2015-2018, The Linux Foundataion. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
@@ -45,11 +45,12 @@
 
 class ColorInterface;
 
-typedef DisplayError (*CreateColorInterface)(uint16_t version, DisplayType type,
+typedef DisplayError (*CreateColorInterface)(uint16_t version, int32_t display_id,
+                                             DisplayType type,
                                              const PPHWAttributes &attributes,
                                              ColorInterface **interface);
 
-typedef DisplayError (*DestroyColorInterface)(DisplayType type);
+typedef DisplayError (*DestroyColorInterface)(int32_t display_id);
 
 class ColorModeInterface {
  public:
@@ -63,8 +64,8 @@
   virtual ~ColorModeInterface() {}
 };
 
-extern "C" ColorModeInterface* GetColorModeInterface(DisplayType type);
-extern "C" void ReleaseColorModeInterface(DisplayType type);
+extern "C" ColorModeInterface* GetColorModeInterface(int32_t display_id, DisplayType type);
+extern "C" void ReleaseColorModeInterface(int32_t display_id);
 
 class ColorInterface {
  public:
diff --git a/sdm/include/private/color_params.h b/sdm/include/private/color_params.h
index 32f0505..7c2846f 100644
--- a/sdm/include/private/color_params.h
+++ b/sdm/include/private/color_params.h
@@ -55,6 +55,8 @@
   kDisableFrameCapture = BITMAP(7),
   kConfigureDetailedEnhancer = BITMAP(8),
   kModeSet = BITMAP(10),
+  kMultiDispProc = BITMAP(11),
+  kMultiDispGetId = BITMAP(12),
   kGetDetailedEnhancerData = BITMAP(21),
   kNoAction = BITMAP(31),
 };
diff --git a/sdm/libs/core/Makefile.am b/sdm/libs/core/Makefile.am
index 2b45d8e..fc9d237 100644
--- a/sdm/libs/core/Makefile.am
+++ b/sdm/libs/core/Makefile.am
@@ -3,17 +3,24 @@
 c_sources = core_interface.cpp \
             core_impl.cpp \
             display_base.cpp \
-            display_primary.cpp \
-            display_hdmi.cpp \
+            display_builtin.cpp \
+            display_pluggable.cpp \
             display_virtual.cpp \
             comp_manager.cpp \
             strategy.cpp \
             resource_default.cpp \
-            dump_impl.cpp \
             color_manager.cpp \
             hw_interface.cpp \
             hw_info_interface.cpp \
             hw_events_interface.cpp \
+            drm/hw_color_manager_drm.cpp \
+            drm/hw_device_drm.cpp \
+            drm/hw_events_drm.cpp \
+            drm/hw_info_drm.cpp \
+            drm/hw_peripheral_drm.cpp \
+            drm/hw_scale_drm.cpp \
+            drm/hw_tv_drm.cpp \
+            drm/hw_virtual_drm.cpp \
             fb/hw_info.cpp \
             fb/hw_device.cpp \
             fb/hw_primary.cpp \
diff --git a/sdm/libs/core/color_manager.cpp b/sdm/libs/core/color_manager.cpp
index 694aada..d895bf7 100644
--- a/sdm/libs/core/color_manager.cpp
+++ b/sdm/libs/core/color_manager.cpp
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015 - 2017, The Linux Foundataion. All rights reserved.
+/* Copyright (c) 2015 - 2018, The Linux Foundataion. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
@@ -99,10 +99,11 @@
   color_lib_.~DynLib();
 }
 
-ColorManagerProxy::ColorManagerProxy(DisplayType type, HWInterface *intf,
+ColorManagerProxy::ColorManagerProxy(int32_t id, DisplayType type, HWInterface *intf,
                                      const HWDisplayAttributes &attr,
                                      const HWPanelInfo &info)
-    : device_type_(type), pp_hw_attributes_(), hw_intf_(intf), color_intf_(NULL), pp_features_() {}
+    : display_id_(id), device_type_(type), pp_hw_attributes_(), hw_intf_(intf),
+      color_intf_(NULL), pp_features_() {}
 
 ColorManagerProxy *ColorManagerProxy::CreateColorManagerProxy(DisplayType type,
                                                               HWInterface *hw_intf,
@@ -110,6 +111,8 @@
                                                               const HWPanelInfo &panel_info) {
   DisplayError error = kErrorNone;
   PPFeatureVersion versions;
+  int32_t display_id = -1;
+  ColorManagerProxy *color_manager_proxy = NULL;
 
   // check if all resources are available before invoking factory method from libsdm-color.so.
   if (!color_lib_ || !create_intf_ || !destroy_intf_) {
@@ -117,8 +120,9 @@
     return NULL;
   }
 
-  ColorManagerProxy *color_manager_proxy =
-      new ColorManagerProxy(type, hw_intf, attribute, panel_info);
+  hw_intf->GetDisplayId(&display_id);
+  color_manager_proxy = new ColorManagerProxy(display_id, type, hw_intf, attribute, panel_info);
+
   if (color_manager_proxy) {
     // 1. need query post-processing feature version from HWInterface.
     error = color_manager_proxy->hw_intf_->GetPPFeaturesVersion(&versions);
@@ -133,7 +137,8 @@
     }
 
     // 2. instantiate concrete ColorInterface from libsdm-color.so, pass all hardware info in.
-    error = create_intf_(COLOR_VERSION_TAG, color_manager_proxy->device_type_, hw_attr,
+    error = create_intf_(COLOR_VERSION_TAG, color_manager_proxy->display_id_,
+                         color_manager_proxy->device_type_, hw_attr,
                          &color_manager_proxy->color_intf_);
     if (error != kErrorNone) {
       DLOGW("Unable to instantiate concrete ColorInterface from %s", COLORMGR_LIBRARY_NAME);
@@ -147,7 +152,7 @@
 
 ColorManagerProxy::~ColorManagerProxy() {
   if (destroy_intf_)
-    destroy_intf_(device_type_);
+    destroy_intf_(display_id_);
   color_intf_ = NULL;
 }
 
diff --git a/sdm/libs/core/color_manager.h b/sdm/libs/core/color_manager.h
index db050af..74270e0 100644
--- a/sdm/libs/core/color_manager.h
+++ b/sdm/libs/core/color_manager.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2017, The Linux Foundataion. All rights reserved.
+/* Copyright (c) 2015-2018, The Linux Foundataion. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
@@ -77,8 +77,8 @@
 
  protected:
   ColorManagerProxy() {}
-  ColorManagerProxy(DisplayType type, HWInterface *intf, const HWDisplayAttributes &attr,
-                    const HWPanelInfo &info);
+  ColorManagerProxy(int32_t id, DisplayType type, HWInterface *intf,
+                    const HWDisplayAttributes &attr, const HWPanelInfo &info);
 
  private:
   static DynLib color_lib_;
@@ -86,6 +86,7 @@
   static DestroyColorInterface destroy_intf_;
   static HWResourceInfo hw_res_info_;
 
+  int32_t display_id_;
   DisplayType device_type_;
   PPHWAttributes pp_hw_attributes_;
   HWInterface *hw_intf_;
diff --git a/sdm/libs/core/comp_manager.cpp b/sdm/libs/core/comp_manager.cpp
index 305a8fd..e07aae1 100644
--- a/sdm/libs/core/comp_manager.cpp
+++ b/sdm/libs/core/comp_manager.cpp
@@ -250,7 +250,8 @@
   if (!display_comp_ctx->is_primary_panel) {
     bool low_end_hw = ((hw_res_info_.num_vig_pipe + hw_res_info_.num_rgb_pipe +
                         hw_res_info_.num_dma_pipe) <= kSafeModeThreshold);
-    constraints->max_layers = max_sde_ext_layers_;
+    constraints->max_layers = display_comp_ctx->display_type == kBuiltIn ?
+                              max_sde_builtin_layers_ : max_sde_ext_layers_;
     constraints->safe_mode = (low_end_hw && !hw_res_info_.separate_rotator) ? true : safe_mode_;
   }
 
@@ -380,8 +381,8 @@
                              reinterpret_cast<DisplayCompositionContext *>(display_ctx);
   configured_displays_.insert(display_comp_ctx->display_id);
 
-  // Check if all registered displays are in the configured display list.
-  if ((registered_displays_.size() == configured_displays_.size())) {
+  // Check if all poweredon displays are in the configured display list.
+  if ((powered_on_displays_.size() == configured_displays_.size())) {
     safe_mode_ = false;
   }
 
@@ -544,30 +545,37 @@
   DisplayCompositionContext *display_comp_ctx =
       reinterpret_cast<DisplayCompositionContext *>(display_ctx);
 
-  powered_on_displays_.erase(display_comp_ctx->display_id);
-
   switch (state) {
   case kStateOff:
     Purge(display_ctx);
     configured_displays_.erase(display_comp_ctx->display_id);
     DLOGV_IF(kTagCompManager, "Configured displays = [%s]",
              StringDisplayList(configured_displays_));
+    powered_on_displays_.erase(display_comp_ctx->display_id);
     break;
 
   case kStateOn:
+  case kStateDoze:
     // Get active display count.
     if (powered_on_displays_.size()) {
       safe_mode_ = true;
       DLOGV_IF(kTagCompManager, "safe_mode = %d", safe_mode_);
-      break;
     }
     powered_on_displays_.insert(display_comp_ctx->display_id);
     break;
 
+  case kStateDozeSuspend:
+    configured_displays_.erase(display_comp_ctx->display_id);
+    powered_on_displays_.erase(display_comp_ctx->display_id);
+    break;
+
   default:
     break;
   }
 
+  bool inactive = (state == kStateOff) || (state == kStateDozeSuspend);
+  UpdateStrategyConstraints(display_comp_ctx->is_primary_panel, inactive);
+
   return true;
 }
 
@@ -615,4 +623,14 @@
   }
 }
 
+void CompManager::UpdateStrategyConstraints(bool is_primary, bool disabled) {
+  if (!is_primary) {
+    return;
+  }
+
+  // Allow builtin display to use all pipes when primary is suspended.
+  // Restore it back to 2 after primary poweron.
+  max_sde_builtin_layers_ = (disabled && (powered_on_displays_.size() <= 1)) ? kMaxSDELayers : 2;
+}
+
 }  // namespace sdm
diff --git a/sdm/libs/core/comp_manager.h b/sdm/libs/core/comp_manager.h
index 876a217..aba0b8b 100644
--- a/sdm/libs/core/comp_manager.h
+++ b/sdm/libs/core/comp_manager.h
@@ -88,6 +88,7 @@
   static const int kSafeModeThreshold = 4;
 
   void PrepareStrategyConstraints(Handle display_ctx, HWLayers *hw_layers);
+  void UpdateStrategyConstraints(bool is_primary, bool disabled);
   const char *StringDisplayList(const std::set<int32_t> &displays);
 
   struct DisplayCompositionContext {
@@ -120,6 +121,7 @@
   ExtensionInterface *extension_intf_ = NULL;
   uint32_t max_layers_ = kMaxSDELayers;
   uint32_t max_sde_ext_layers_ = 0;
+  uint32_t max_sde_builtin_layers_ = 2;
   DppsControlInterface *dpps_ctrl_intf_ = NULL;
 };
 
diff --git a/sdm/libs/core/display_base.cpp b/sdm/libs/core/display_base.cpp
index bd238a9..c646668 100644
--- a/sdm/libs/core/display_base.cpp
+++ b/sdm/libs/core/display_base.cpp
@@ -128,17 +128,15 @@
     }
   }
 
-  if (!color_mgr_exists_) {
+  // ColorManager supported for built-in display.
+  if (kBuiltIn == display_type_) {
     color_mgr_ = ColorManagerProxy::CreateColorManagerProxy(display_type_, hw_intf_,
                                                             display_attributes_, hw_panel_info_);
 
     if (!color_mgr_) {
-      DLOGW("Unable to create ColorManagerProxy for display = %d", display_type_);
-    } else {
-      color_mgr_exists_ = true;
-      if (InitializeColorModes() != kErrorNone) {
-        DLOGW("InitColorModes failed for display = %d", display_type_);
-      }
+      DLOGW("Unable to create ColorManagerProxy for display %d-%d", display_id_, display_type_);
+    } else if (InitializeColorModes() != kErrorNone) {
+      DLOGW("InitColorModes failed for display %d-%d", display_id_, display_type_);
     }
   }
 
@@ -491,12 +489,14 @@
   return last_power_mode_;
 }
 
-DisplayError DisplayBase::SetDisplayState(DisplayState state, int *release_fence) {
+DisplayError DisplayBase::SetDisplayState(DisplayState state, bool teardown,
+                                          int *release_fence) {
   lock_guard<recursive_mutex> obj(recursive_mutex_);
   DisplayError error = kErrorNone;
   bool active = false;
 
-  DLOGI("Set state = %d, display %d-%d", state, display_id_, display_type_);
+  DLOGI("Set state = %d, display %d-%d, teardown = %d", state, display_id_,
+        display_type_, teardown);
 
   if (state == state_) {
     DLOGI("Same state transition is requested.");
@@ -508,7 +508,7 @@
     hw_layers_.info.hw_layers.clear();
     error = hw_intf_->Flush();
     if (error == kErrorNone) {
-      error = hw_intf_->PowerOff();
+      error = hw_intf_->PowerOff(teardown);
     }
     break;
 
@@ -1631,8 +1631,6 @@
                                 mixer_height != display_height);
 }
 
-bool DisplayBase::color_mgr_exists_ = false;
-
 void DisplayBase::ClearColorInfo() {
   color_modes_.clear();
   color_mode_map_.clear();
@@ -1642,7 +1640,6 @@
   if (color_mgr_) {
     delete color_mgr_;
     color_mgr_ = NULL;
-    color_mgr_exists_ = false;
   }
 }
 
diff --git a/sdm/libs/core/display_base.h b/sdm/libs/core/display_base.h
index 27452f4..7f8e32d 100644
--- a/sdm/libs/core/display_base.h
+++ b/sdm/libs/core/display_base.h
@@ -66,7 +66,8 @@
   virtual DisplayError GetConfig(DisplayConfigFixedInfo *variable_info);
   virtual DisplayError GetActiveConfig(uint32_t *index);
   virtual DisplayError GetVSyncState(bool *enabled);
-  virtual DisplayError SetDisplayState(DisplayState state, int *release_fence);
+  virtual DisplayError SetDisplayState(DisplayState state, bool teardown,
+                                       int *release_fence);
   virtual DisplayError SetActiveConfig(uint32_t index);
   virtual DisplayError SetActiveConfig(DisplayConfigVariableInfo *variable_info) {
     return kErrorNotSupported;
@@ -124,6 +125,9 @@
   virtual DisplayError HandleSecureEvent(SecureEvent secure_event) {
     return kErrorNotSupported;
   }
+  virtual DisplayError SetDisplayDppsAdROI(void *payload) {
+    return kErrorNotSupported;
+  }
   virtual DisplayError SetQSyncMode(QSyncMode qsync_mode) { return kErrorNotSupported; }
   virtual std::string Dump();
   virtual DisplayError InitializeColorModes();
@@ -185,8 +189,6 @@
   uint32_t max_mixer_stages_ = 0;
   HWInfoInterface *hw_info_intf_ = NULL;
   ColorManagerProxy *color_mgr_ = NULL;  // each display object owns its ColorManagerProxy
-  // TODO(user): ColorManager supported only on a single built-in display.
-  static bool color_mgr_exists_;
   bool partial_update_control_ = true;
   HWEventsInterface *hw_events_intf_ = NULL;
   bool disable_pu_one_frame_ = false;
diff --git a/sdm/libs/core/display_builtin.cpp b/sdm/libs/core/display_builtin.cpp
index 3b5ca4b..b618113 100644
--- a/sdm/libs/core/display_builtin.cpp
+++ b/sdm/libs/core/display_builtin.cpp
@@ -191,10 +191,11 @@
   return error;
 }
 
-DisplayError DisplayBuiltIn::SetDisplayState(DisplayState state, int *release_fence) {
+DisplayError DisplayBuiltIn::SetDisplayState(DisplayState state, bool teardown,
+                                             int *release_fence) {
   lock_guard<recursive_mutex> obj(recursive_mutex_);
   DisplayError error = kErrorNone;
-  error = DisplayBase::SetDisplayState(state, release_fence);
+  error = DisplayBase::SetDisplayState(state, teardown, release_fence);
   if (error != kErrorNone) {
     return error;
   }
@@ -427,24 +428,20 @@
   int release_fence = -1;
 
   DLOGI("Powering off built-in/primary %d", display_id_);
-  status = SetDisplayState(kStateOff, &release_fence);
+  status = SetDisplayState(kStateOff, true /* teardown */, &release_fence);
   if (status != kErrorNone) {
     DLOGE("power-off on built-in/primary %d failed with error = %d", display_id_, status);
   }
-  if (release_fence >= 0) {
-    ::close(release_fence);
-  }
+  CloseFd(&release_fence);
 
   DLOGI("Restoring power mode on built-in/primary %d", display_id_);
   DisplayState mode = GetLastPowerMode();
-  status = SetDisplayState(mode, &release_fence);
+  status = SetDisplayState(mode, false /* teardown */, &release_fence);
   if (status != kErrorNone) {
     DLOGE("Setting power mode = %d on built-in/primary %d failed with error = %d", mode,
           display_id_, status);
   }
-  if (release_fence >= 0) {
-    ::close(release_fence);
-  }
+  CloseFd(&release_fence);
 
   DLOGI("Enabling HWVsync");
   status = SetVSyncState(true);
@@ -509,6 +506,17 @@
   return error;
 }
 
+DisplayError DisplayBuiltIn::SetDisplayDppsAdROI(void *payload) {
+  lock_guard<recursive_mutex> obj(recursive_mutex_);
+  DisplayError err = kErrorNone;
+
+  err = hw_intf_->SetDisplayDppsAdROI(payload);
+  if (err != kErrorNone)
+    DLOGE("Failed to set ad roi config, err %d", err);
+
+  return err;
+}
+
 void DppsInfo::Init(DppsPropIntf *intf, const std::string &panel_name) {
   int error = 0;
 
diff --git a/sdm/libs/core/display_builtin.h b/sdm/libs/core/display_builtin.h
index 599a730..267267a 100644
--- a/sdm/libs/core/display_builtin.h
+++ b/sdm/libs/core/display_builtin.h
@@ -62,7 +62,8 @@
   virtual DisplayError Commit(LayerStack *layer_stack);
   virtual DisplayError ControlPartialUpdate(bool enable, uint32_t *pending);
   virtual DisplayError DisablePartialUpdateOneFrame();
-  virtual DisplayError SetDisplayState(DisplayState state, int *release_fence);
+  virtual DisplayError SetDisplayState(DisplayState state, bool teardown,
+                                       int *release_fence);
   virtual void SetIdleTimeoutMs(uint32_t active_ms);
   virtual DisplayError SetDisplayMode(uint32_t mode);
   virtual DisplayError GetRefreshRateRange(uint32_t *min_refresh_rate, uint32_t *max_refresh_rate);
@@ -70,6 +71,7 @@
   virtual DisplayError SetPanelBrightness(int level);
   virtual DisplayError GetPanelBrightness(int *level);
   virtual DisplayError HandleSecureEvent(SecureEvent secure_event);
+  virtual DisplayError SetDisplayDppsAdROI(void *payload);
   virtual DisplayError SetQSyncMode(QSyncMode qsync_mode);
   virtual DisplayError ControlIdlePowerCollapse(bool enable, bool synchronous);
 
diff --git a/sdm/libs/core/display_pluggable.cpp b/sdm/libs/core/display_pluggable.cpp
index da161df..2aaa03a 100644
--- a/sdm/libs/core/display_pluggable.cpp
+++ b/sdm/libs/core/display_pluggable.cpp
@@ -65,22 +65,24 @@
     hw_intf_->GetDisplayId(&display_id_);
   }
 
-  uint32_t active_mode_index;
-  char value[64] = "0";
-  Debug::GetProperty(HDMI_S3D_MODE_PROP, value);
-  HWS3DMode mode = (HWS3DMode)atoi(value);
-  if (mode > kS3DModeNone && mode < kS3DModeMax) {
-    active_mode_index = GetBestConfig(mode);
-  } else {
-    active_mode_index = GetBestConfig(kS3DModeNone);
-  }
-
-  error = hw_intf_->SetDisplayAttributes(active_mode_index);
+  uint32_t active_mode_index = 0;
+  error = hw_intf_->GetActiveConfig(&active_mode_index);
   if (error != kErrorNone) {
     HWInterface::Destroy(hw_intf_);
     return error;
   }
 
+  uint32_t override_mode_index = active_mode_index;
+  error = GetOverrideConfig(&override_mode_index);
+  if (error == kErrorNone && override_mode_index != active_mode_index) {
+    DLOGI("Overriding display mode %d with mode %d.", active_mode_index, override_mode_index);
+    error = hw_intf_->SetDisplayAttributes(override_mode_index);
+    if (error != kErrorNone) {
+      DLOGI("Failed overriding display mode %d with mode %d. Continuing with display mode %d.",
+            active_mode_index, override_mode_index, active_mode_index);
+    }
+  }
+
   error = DisplayBase::Init();
   if (error != kErrorNone) {
     HWInterface::Destroy(hw_intf_);
@@ -182,56 +184,29 @@
   return hw_intf_->OnMinHdcpEncryptionLevelChange(min_enc_level);
 }
 
-uint32_t DisplayPluggable::GetBestConfig(HWS3DMode s3d_mode) {
-  uint32_t best_index = 0, index;
-  uint32_t num_modes = 0;
+DisplayError DisplayPluggable::GetOverrideConfig(uint32_t *mode_index) {
+  DisplayError error = kErrorNone;
 
-  hw_intf_->GetNumDisplayAttributes(&num_modes);
-
-  // Get display attribute for each mode
-  std::vector<HWDisplayAttributes> attrib(num_modes);
-  for (index = 0; index < num_modes; index++) {
-    hw_intf_->GetDisplayAttributes(index, &attrib[index]);
+  if (!mode_index) {
+    DLOGE("Invalid mode index parameter.");
+    return kErrorParameters;
   }
 
-  // Select best config for s3d_mode. If s3d is not enabled, s3d_mode is kS3DModeNone
-  for (index = 0; index < num_modes; index++) {
-    if (attrib[index].s3d_config[s3d_mode]) {
-      break;
-    }
-  }
+  // TODO(user): Need to add support for S3D modes based on HDMI_S3D_MODE_PROP property.
 
-  index = 0;
-  best_index = UINT32(index);
-  for (size_t index = best_index + 1; index < num_modes; index++) {
-    // TODO(user): Need to add support to S3D modes
-    // From the available configs, select the best
-    // Ex: 1920x1080@60Hz is better than 1920x1080@30 and 1920x1080@30 is better than 1280x720@60
-    if (attrib[index].x_pixels > attrib[best_index].x_pixels) {
-      best_index = UINT32(index);
-    } else if (attrib[index].x_pixels == attrib[best_index].x_pixels) {
-      if (attrib[index].y_pixels > attrib[best_index].y_pixels) {
-        best_index = UINT32(index);
-      } else if (attrib[index].y_pixels == attrib[best_index].y_pixels) {
-        if (attrib[index].vsync_period_ns < attrib[best_index].vsync_period_ns) {
-          best_index = UINT32(index);
-        }
-      }
-    }
-  }
   char val[kPropertyMax] = {};
-  // Used for changing HDMI Resolution - override the best with user set config
-  bool user_config = (Debug::GetExternalResolution(val));
-
+  // Used for changing HDMI Resolution - Override the preferred mode with user set config.
+  bool user_config = Debug::GetExternalResolution(val);
   if (user_config) {
     uint32_t config_index = 0;
     // For the config, get the corresponding index
-    DisplayError error = hw_intf_->GetConfigIndex(val, &config_index);
-    if (error == kErrorNone)
-      return config_index;
+    error = hw_intf_->GetConfigIndex(val, &config_index);
+    if (error == kErrorNone) {
+      *mode_index = config_index;
+    }
   }
 
-  return best_index;
+  return error;
 }
 
 void DisplayPluggable::GetScanSupport() {
@@ -368,17 +343,6 @@
   return kErrorNone;
 }
 
-DisplayError DisplayPluggable::SetDisplayState(DisplayState state, int *release_fence) {
-  lock_guard<recursive_mutex> obj(recursive_mutex_);
-  DisplayError error = kErrorNone;
-  error = DisplayBase::SetDisplayState(state, release_fence);
-  if (error != kErrorNone) {
-    return error;
-  }
-
-  return kErrorNone;
-}
-
 static PrimariesTransfer GetBlendSpaceFromAttributes(const std::string &color_gamut,
                                                      const std::string &transfer) {
   PrimariesTransfer blend_space_ = {};
diff --git a/sdm/libs/core/display_pluggable.h b/sdm/libs/core/display_pluggable.h
index 902ff92..d15129c 100644
--- a/sdm/libs/core/display_pluggable.h
+++ b/sdm/libs/core/display_pluggable.h
@@ -53,7 +53,6 @@
   virtual DisplayError GetColorModeCount(uint32_t *mode_count);
   virtual DisplayError GetColorModes(uint32_t *mode_count, std::vector<std::string> *color_modes);
   virtual DisplayError GetColorModeAttr(const std::string &color_mode, AttrVal *attr);
-  virtual DisplayError SetDisplayState(DisplayState state, int *release_fence);
   virtual DisplayError SetColorTransform(const uint32_t length, const double *color_transform) {
     return kErrorNone;
   }
@@ -72,7 +71,7 @@
   void UpdateColorModes();
 
  private:
-  uint32_t GetBestConfig(HWS3DMode s3d_mode);
+  DisplayError GetOverrideConfig(uint32_t *mode_index);
   void GetScanSupport();
   void SetS3DMode(LayerStack *layer_stack);
 
diff --git a/sdm/libs/core/display_virtual.cpp b/sdm/libs/core/display_virtual.cpp
index cff7519..21a7890 100644
--- a/sdm/libs/core/display_virtual.cpp
+++ b/sdm/libs/core/display_virtual.cpp
@@ -165,5 +165,14 @@
   return DisplayBase::Prepare(layer_stack);
 }
 
+DisplayError DisplayVirtual::GetColorModeCount(uint32_t *mode_count) {
+  lock_guard<recursive_mutex> obj(recursive_mutex_);
+
+  // Color Manager isn't supported for virtual displays.
+  *mode_count = 1;
+
+  return kErrorNone;
+}
+
 }  // namespace sdm
 
diff --git a/sdm/libs/core/display_virtual.h b/sdm/libs/core/display_virtual.h
index a651447..e3daec6 100644
--- a/sdm/libs/core/display_virtual.h
+++ b/sdm/libs/core/display_virtual.h
@@ -69,6 +69,7 @@
   virtual DisplayError SetColorTransform(const uint32_t length, const double *color_transform) {
     return kErrorNone;
   }
+  virtual DisplayError GetColorModeCount(uint32_t *mode_count);
 };
 
 }  // namespace sdm
diff --git a/sdm/libs/core/drm/hw_device_drm.cpp b/sdm/libs/core/drm/hw_device_drm.cpp
index 43d182f..cd08e38 100644
--- a/sdm/libs/core/drm/hw_device_drm.cpp
+++ b/sdm/libs/core/drm/hw_device_drm.cpp
@@ -522,6 +522,8 @@
   // Update current mode with preferred mode
   for (uint32_t mode_index = 0; mode_index < connector_info_.modes.size(); mode_index++) {
       if (connector_info_.modes[mode_index].mode.type & DRM_MODE_TYPE_PREFERRED) {
+        DLOGI("Updating current display mode %d to preferred mode %d.", current_mode_index_,
+              mode_index);
         current_mode_index_ = mode_index;
         break;
       }
@@ -861,7 +863,7 @@
   return kErrorNone;
 }
 
-DisplayError HWDeviceDRM::PowerOff() {
+DisplayError HWDeviceDRM::PowerOff(bool teardown) {
   DTRACE_SCOPED();
   if (!drm_atomic_intf_) {
     DLOGE("DRM Atomic Interface is null!");
diff --git a/sdm/libs/core/drm/hw_device_drm.h b/sdm/libs/core/drm/hw_device_drm.h
index 6cfd51c..9bc02b6 100644
--- a/sdm/libs/core/drm/hw_device_drm.h
+++ b/sdm/libs/core/drm/hw_device_drm.h
@@ -80,7 +80,7 @@
   virtual DisplayError SetDisplayAttributes(const HWDisplayAttributes &display_attributes);
   virtual DisplayError GetConfigIndex(char *mode, uint32_t *index);
   virtual DisplayError PowerOn(const HWQosData &qos_data, int *release_fence);
-  virtual DisplayError PowerOff();
+  virtual DisplayError PowerOff(bool teardown);
   virtual DisplayError Doze(const HWQosData &qos_data, int *release_fence);
   virtual DisplayError DozeSuspend(const HWQosData &qos_data, int *release_fence);
   virtual DisplayError Standby();
@@ -116,6 +116,7 @@
   virtual DisplayError ControlIdlePowerCollapse(bool enable, bool synchronous) {
     return kErrorNotSupported;
   }
+  virtual DisplayError SetDisplayDppsAdROI(void *payload) { return kErrorNotSupported; }
 
   enum {
     kHWEventVSync,
diff --git a/sdm/libs/core/drm/hw_peripheral_drm.cpp b/sdm/libs/core/drm/hw_peripheral_drm.cpp
index f35b11e..46e7b5a 100644
--- a/sdm/libs/core/drm/hw_peripheral_drm.cpp
+++ b/sdm/libs/core/drm/hw_peripheral_drm.cpp
@@ -109,8 +109,7 @@
     return;
   }
 
-  uint32_t count = 0;
-  for (uint32_t i = 0; i < hw_resource_.hw_dest_scalar_info.count; i++) {
+  for (uint32_t i = 0; i < hw_resource_.hw_dest_scalar_info.count && validate; i++) {
     DestScaleInfoMap::iterator it = hw_layer_info.dest_scale_info_map.find(i);
 
     if (it == hw_layer_info.dest_scale_info_map.end()) {
@@ -118,10 +117,10 @@
     }
 
     HWDestScaleInfo *dest_scale_info = it->second;
-    SDEScaler *scale = &scalar_data_[count];
+    SDEScaler *scale = &scalar_data_[i];
     hw_scale_->SetScaler(dest_scale_info->scale_data, scale);
 
-    sde_drm_dest_scaler_cfg *dest_scalar_data = &sde_dest_scalar_data_.ds_cfg[count];
+    sde_drm_dest_scaler_cfg *dest_scalar_data = &sde_dest_scalar_data_.ds_cfg[i];
     dest_scalar_data->flags = 0;
     if (scale->scaler_v2.enable) {
       dest_scalar_data->flags |= SDE_DRM_DESTSCALER_ENABLE;
@@ -135,24 +134,31 @@
     if (hw_panel_info_.partial_update) {
       dest_scalar_data->flags |= SDE_DRM_DESTSCALER_PU_ENABLE;
     }
-
-    if (!std::memcmp(&dest_scalar_cache_[count].scalar_data, scale, sizeof(SDEScaler)) &&
-        dest_scalar_cache_[count].flags == dest_scalar_data->flags) {
-      continue;
-    }
-
     dest_scalar_data->index = i;
     dest_scalar_data->lm_width = dest_scale_info->mixer_width;
     dest_scalar_data->lm_height = dest_scale_info->mixer_height;
     dest_scalar_data->scaler_cfg = reinterpret_cast<uint64_t>(&scale->scaler_v2);
-    if (!validate) {
-      dest_scalar_cache_[count].flags = dest_scalar_data->flags;
-      dest_scalar_cache_[count].scalar_data = *scale;
+
+    if (std::memcmp(&dest_scalar_cache_[i].scalar_data, scale, sizeof(SDEScaler)) ||
+        dest_scalar_cache_[i].flags != dest_scalar_data->flags) {
+      needs_ds_update_ = true;
     }
-    count++;
   }
-  if (count) {
-    sde_dest_scalar_data_.num_dest_scaler = count;
+
+  if (needs_ds_update_) {
+    if (!validate) {
+      // Cache the destination scalar data during commit
+      for (uint32_t i = 0; i < hw_resource_.hw_dest_scalar_info.count; i++) {
+        DestScaleInfoMap::iterator it = hw_layer_info.dest_scale_info_map.find(i);
+        if (it == hw_layer_info.dest_scale_info_map.end()) {
+          continue;
+        }
+        dest_scalar_cache_[i].flags = sde_dest_scalar_data_.ds_cfg[i].flags;
+        dest_scalar_cache_[i].scalar_data = scalar_data_[i];
+      }
+      needs_ds_update_ = false;
+    }
+    sde_dest_scalar_data_.num_dest_scaler = UINT32(hw_layer_info.dest_scale_info_map.size());
     drm_atomic_intf_->Perform(DRMOps::CRTC_SET_DEST_SCALER_CONFIG, token_.crtc_id,
                               reinterpret_cast<uint64_t>(&sde_dest_scalar_data_));
   }
@@ -181,6 +187,27 @@
   object_type = feature_payload->object_type;
   feature_id = feature_payload->feature_id;
   value = feature_payload->value;
+
+  if (feature_id == sde_drm::kFeatureAd4Roi) {
+    if (feature_payload->value) {
+      DisplayDppsAd4RoiCfg *params = reinterpret_cast<DisplayDppsAd4RoiCfg *>
+                                                      (feature_payload->value);
+      if (!params) {
+        DLOGE("invalid playload value %d", feature_payload->value);
+        return kErrorNotSupported;
+      }
+
+      ad4_roi_cfg_.h_x = params->h_start;
+      ad4_roi_cfg_.h_y = params->h_end;
+      ad4_roi_cfg_.v_x = params->v_start;
+      ad4_roi_cfg_.v_y = params->v_end;
+      ad4_roi_cfg_.factor_in = params->factor_in;
+      ad4_roi_cfg_.factor_out = params->factor_out;
+
+      value = (uint64_t)&ad4_roi_cfg_;
+    }
+  }
+
   if (object_type == DRM_MODE_OBJECT_CRTC) {
     obj_id = token_.crtc_id;
   } else if (object_type == DRM_MODE_OBJECT_CONNECTOR) {
@@ -336,6 +363,7 @@
   if (!enabled) {
     drm_mgr_intf_->UnregisterDisplay(cwb_config_.token);
     cwb_config_.enabled = false;
+    registry_.Clear();
   }
 }
 
@@ -373,4 +401,26 @@
   return kErrorNone;
 }
 
+DisplayError HWPeripheralDRM::SetDisplayDppsAdROI(void *payload) {
+  DisplayError err = kErrorNone;
+  struct sde_drm::DppsFeaturePayload feature_payload = {};
+
+  if (!payload) {
+    DLOGE("Invalid payload parameter");
+    return kErrorParameters;
+  }
+
+  feature_payload.object_type = DRM_MODE_OBJECT_CRTC;
+  feature_payload.feature_id = sde_drm::kFeatureAd4Roi;
+  feature_payload.value = (uint64_t)(payload);
+
+  err = SetDppsFeature(&feature_payload, sizeof(feature_payload));
+  if (err != kErrorNone) {
+    DLOGE("Faid to SetDppsFeature feature_id = %d, err = %d",
+           sde_drm::kFeatureAd4Roi, err);
+  }
+
+  return err;
+}
+
 }  // namespace sdm
diff --git a/sdm/libs/core/drm/hw_peripheral_drm.h b/sdm/libs/core/drm/hw_peripheral_drm.h
index e693163..96889de 100644
--- a/sdm/libs/core/drm/hw_peripheral_drm.h
+++ b/sdm/libs/core/drm/hw_peripheral_drm.h
@@ -56,6 +56,7 @@
   virtual DisplayError HandleSecureEvent(SecureEvent secure_event);
   virtual DisplayError ControlIdlePowerCollapse(bool enable, bool synchronous);
   virtual DisplayError PowerOn(const HWQosData &qos_data, int *release_fence);
+  virtual DisplayError SetDisplayDppsAdROI(void *payload);
 
  private:
   void SetDestScalarData(HWLayersInfo hw_layer_info, bool validate);
@@ -79,6 +80,8 @@
   CWBConfig cwb_config_ = {};
   sde_drm::DRMIdlePCState idle_pc_state_ = sde_drm::DRMIdlePCState::NONE;
   std::vector<DestScalarCache> dest_scalar_cache_ = {};
+  drm_msm_ad4_roi_cfg ad4_roi_cfg_ = {};
+  bool needs_ds_update_ = false;
 };
 
 }  // namespace sdm
diff --git a/sdm/libs/core/drm/hw_tv_drm.cpp b/sdm/libs/core/drm/hw_tv_drm.cpp
index b6f1b08..6272fa7 100644
--- a/sdm/libs/core/drm/hw_tv_drm.cpp
+++ b/sdm/libs/core/drm/hw_tv_drm.cpp
@@ -163,9 +163,17 @@
   return kErrorNone;
 }
 
-DisplayError HWTVDRM::PowerOff() {
+DisplayError HWTVDRM::PowerOff(bool teardown) {
   DTRACE_SCOPED();
+  if (!drm_atomic_intf_) {
+    DLOGE("DRM Atomic Interface is null!");
+    return kErrorUndefined;
+  }
 
+  if (teardown) {
+    // LP connecter prop N/A for External
+    drm_atomic_intf_->Perform(DRMOps::CRTC_SET_ACTIVE, token_.crtc_id, 0);
+  }
   int ret = drm_atomic_intf_->Commit(true /* synchronous */, false /* retain_planes*/);
   if (ret) {
     DLOGE("%s failed with error %d", __FUNCTION__, ret);
diff --git a/sdm/libs/core/drm/hw_tv_drm.h b/sdm/libs/core/drm/hw_tv_drm.h
index 9fed9ca..96d0746 100644
--- a/sdm/libs/core/drm/hw_tv_drm.h
+++ b/sdm/libs/core/drm/hw_tv_drm.h
@@ -42,7 +42,7 @@
  protected:
   virtual DisplayError SetDisplayAttributes(uint32_t index);
   virtual DisplayError GetConfigIndex(char *mode, uint32_t *index);
-  virtual DisplayError PowerOff();
+  virtual DisplayError PowerOff(bool teardown);
   virtual DisplayError Doze(const HWQosData &qos_data, int *release_fence);
   virtual DisplayError DozeSuspend(const HWQosData &qos_data, int *release_fence);
   virtual DisplayError Standby();
diff --git a/sdm/libs/core/fb/hw_device.cpp b/sdm/libs/core/fb/hw_device.cpp
index 9795328..9e3f2b9 100644
--- a/sdm/libs/core/fb/hw_device.cpp
+++ b/sdm/libs/core/fb/hw_device.cpp
@@ -182,7 +182,7 @@
   return kErrorNone;
 }
 
-DisplayError HWDevice::PowerOff() {
+DisplayError HWDevice::PowerOff(bool teardown) {
   return kErrorNone;
 }
 
diff --git a/sdm/libs/core/fb/hw_device.h b/sdm/libs/core/fb/hw_device.h
index 7504721..6adb93b 100644
--- a/sdm/libs/core/fb/hw_device.h
+++ b/sdm/libs/core/fb/hw_device.h
@@ -72,7 +72,7 @@
   virtual DisplayError SetDisplayAttributes(const HWDisplayAttributes &display_attributes);
   virtual DisplayError GetConfigIndex(char *mode, uint32_t *index);
   virtual DisplayError PowerOn(const HWQosData &qos_data, int *release_fence);
-  virtual DisplayError PowerOff();
+  virtual DisplayError PowerOff(bool teardown);
   virtual DisplayError Doze(const HWQosData &qos_data, int *release_fence);
   virtual DisplayError DozeSuspend(const HWQosData &qos_data, int *release_fence);
   virtual DisplayError Standby();
@@ -106,6 +106,7 @@
   virtual DisplayError ControlIdlePowerCollapse(bool enable, bool synchronous) {
     return kErrorNotSupported;
   }
+  virtual DisplayError SetDisplayDppsAdROI(void *payload) { return kErrorNotSupported; }
 
   enum {
     kHWEventVSync,
diff --git a/sdm/libs/core/fb/hw_hdmi.cpp b/sdm/libs/core/fb/hw_hdmi.cpp
index efbd4fb..b8b196d 100644
--- a/sdm/libs/core/fb/hw_hdmi.cpp
+++ b/sdm/libs/core/fb/hw_hdmi.cpp
@@ -126,6 +126,7 @@
 
   return mdp_pixel_encoding;
 }
+
 static int32_t GetBitsPerComponent(const LayerBuffer &layer_buffer) {
   bool is_yuv = layer_buffer.flags.video;
   bool is_10_bit = Is10BitFormat(layer_buffer.format);
@@ -227,6 +228,12 @@
 
   GetPanelS3DMode();
 
+  error = SetDisplayAttributes(active_config_index_);
+  if (error != kErrorNone) {
+    Deinit();
+    return error;
+  }
+
   s3d_mode_sdm_to_mdp_.insert(std::pair<HWS3DMode, msm_hdmi_s3d_mode>
                              (kS3DModeNone, HDMI_S3D_NONE));
   s3d_mode_sdm_to_mdp_.insert(std::pair<HWS3DMode, msm_hdmi_s3d_mode>
diff --git a/sdm/libs/core/fb/hw_primary.cpp b/sdm/libs/core/fb/hw_primary.cpp
index b58c5b5..d130d87 100644
--- a/sdm/libs/core/fb/hw_primary.cpp
+++ b/sdm/libs/core/fb/hw_primary.cpp
@@ -333,7 +333,7 @@
   return HWDevice::GetConfigIndex(mode, index);
 }
 
-DisplayError HWPrimary::PowerOff() {
+DisplayError HWPrimary::PowerOff(bool teardown) {
   if (Sys::ioctl_(device_fd_, FBIOBLANK, FB_BLANK_POWERDOWN) < 0) {
     IOCTL_LOGE(FB_BLANK_POWERDOWN, device_type_);
     return kErrorHardware;
diff --git a/sdm/libs/core/fb/hw_primary.h b/sdm/libs/core/fb/hw_primary.h
index e2515d1..6d611a5 100644
--- a/sdm/libs/core/fb/hw_primary.h
+++ b/sdm/libs/core/fb/hw_primary.h
@@ -45,7 +45,7 @@
                                             HWDisplayAttributes *display_attributes);
   virtual DisplayError SetDisplayAttributes(uint32_t index);
   virtual DisplayError GetConfigIndex(char *mode, uint32_t *index);
-  virtual DisplayError PowerOff();
+  virtual DisplayError PowerOff(bool teardown);
   virtual DisplayError Doze(const HWQosData &qos_data, int *release_fence);
   virtual DisplayError DozeSuspend(const HWQosData &qos_data, int *release_fence);
   virtual DisplayError Validate(HWLayers *hw_layers);
diff --git a/sdm/libs/core/hw_interface.h b/sdm/libs/core/hw_interface.h
index 06d166e..7980fdd 100644
--- a/sdm/libs/core/hw_interface.h
+++ b/sdm/libs/core/hw_interface.h
@@ -88,7 +88,7 @@
   virtual DisplayError SetDisplayAttributes(const HWDisplayAttributes &display_attributes) = 0;
   virtual DisplayError GetConfigIndex(char *mode, uint32_t *index) = 0;
   virtual DisplayError PowerOn(const HWQosData &qos_data, int *release_fence) = 0;
-  virtual DisplayError PowerOff() = 0;
+  virtual DisplayError PowerOff(bool teardown) = 0;
   virtual DisplayError Doze(const HWQosData &qos_data, int *release_fence) = 0;
   virtual DisplayError DozeSuspend(const HWQosData &qos_data, int *release_fence) = 0;
   virtual DisplayError Standby() = 0;
@@ -119,6 +119,7 @@
   virtual DisplayError GetDppsFeatureInfo(void *payload, size_t size) = 0;
   virtual DisplayError HandleSecureEvent(SecureEvent secure_event) = 0;
   virtual DisplayError ControlIdlePowerCollapse(bool enable, bool synchronous) = 0;
+  virtual DisplayError SetDisplayDppsAdROI(void *payload) = 0;
 
  protected:
   virtual ~HWInterface() { }
diff --git a/sdm/libs/hwc2/display_null.cpp b/sdm/libs/hwc2/display_null.cpp
index 99cd017..9076779 100644
--- a/sdm/libs/hwc2/display_null.cpp
+++ b/sdm/libs/hwc2/display_null.cpp
@@ -146,7 +146,8 @@
   return kErrorNone;
 }
 
-DisplayError DisplayNullExternal::SetDisplayState(DisplayState state, int *release_fence) {
+DisplayError DisplayNullExternal::SetDisplayState(DisplayState state, bool teardown,
+                                                  int *release_fence) {
   state_ = state;
   return kErrorNone;
 }
diff --git a/sdm/libs/hwc2/display_null.h b/sdm/libs/hwc2/display_null.h
index 82b7ed4..65096e1 100644
--- a/sdm/libs/hwc2/display_null.h
+++ b/sdm/libs/hwc2/display_null.h
@@ -59,7 +59,7 @@
 
   MAKE_NO_OP(Commit(LayerStack *))
   MAKE_NO_OP(GetDisplayState(DisplayState *))
-  MAKE_NO_OP(SetDisplayState(DisplayState, int*))
+  MAKE_NO_OP(SetDisplayState(DisplayState, bool, int*))
   MAKE_NO_OP(SetFrameBufferConfig(const DisplayConfigVariableInfo &))
   MAKE_NO_OP(Flush())
   MAKE_NO_OP(GetVSyncState(bool *))
@@ -97,6 +97,7 @@
   MAKE_NO_OP(HandleSecureEvent(SecureEvent))
   MAKE_NO_OP(SetQSyncMode(QSyncMode))
   MAKE_NO_OP(ControlIdlePowerCollapse(bool, bool))
+  MAKE_NO_OP(SetDisplayDppsAdROI(void *))
 
   DisplayConfigVariableInfo default_variable_config_ = {};
   DisplayConfigFixedInfo default_fixed_config_ = {};
@@ -106,7 +107,8 @@
  public:
   virtual DisplayError Commit(LayerStack *layer_stack);
   virtual DisplayError GetDisplayState(DisplayState *state);
-  virtual DisplayError SetDisplayState(DisplayState state, int *release_fence);
+  virtual DisplayError SetDisplayState(DisplayState state, bool teardown,
+                                       int *release_fence);
   virtual DisplayError SetFrameBufferConfig(const DisplayConfigVariableInfo &variable_info);
   virtual DisplayError GetFrameBufferConfig(DisplayConfigVariableInfo *variable_info);
   void SetActive(bool active) { active_ = active; }
diff --git a/sdm/libs/hwc2/hwc_display.cpp b/sdm/libs/hwc2/hwc_display.cpp
index 92f8a3b..6bc5a51 100644
--- a/sdm/libs/hwc2/hwc_display.cpp
+++ b/sdm/libs/hwc2/hwc_display.cpp
@@ -592,7 +592,7 @@
                      (layer->input_buffer.color_metadata.transfer == Transfer_SMPTE_ST2084 ||
                      layer->input_buffer.color_metadata.transfer == Transfer_HLG);
     if (hdr_layer && !disable_hdr_handling_  &&
-        (color_mode_->GetCurrentColorMode()) != ColorMode::NATIVE) {
+        GetCurrentColorMode() != ColorMode::NATIVE) {
       // Dont honor HDR when its handling is disabled
       // Also, when the color mode is native, it implies that
       // SF has not correctly set the mode to BT2100_PQ in the presence of an HDR layer
@@ -739,7 +739,7 @@
   return HWC2::Error::None;
 }
 
-HWC2::Error HWCDisplay::SetPowerMode(HWC2::PowerMode mode) {
+HWC2::Error HWCDisplay::SetPowerMode(HWC2::PowerMode mode, bool teardown) {
   DLOGV("display = %d, mode = %s", id_, to_string(mode).c_str());
   DisplayState state = kStateOff;
   bool flush_on_error = flush_on_error_;
@@ -782,7 +782,7 @@
   int release_fence = -1;
 
   ATRACE_INT("SetPowerMode ", state);
-  DisplayError error = display_intf_->SetDisplayState(state, &release_fence);
+  DisplayError error = display_intf_->SetDisplayState(state, teardown, &release_fence);
   validated_ = false;
 
   if (error == kErrorNone) {
@@ -943,7 +943,7 @@
   } else {
     *out_size = std::min((UINT32(name.size()) + 1), *out_size);
     if (*out_size > 0) {
-      std::strncpy(out_name, name.c_str(), *out_size);
+      strlcpy(out_name, name.c_str(), *out_size);
       out_name[*out_size - 1] = '\0';
     } else {
       DLOGW("Invalid size requested");
@@ -1699,12 +1699,12 @@
     case kDisplayStatusResume:
       display_paused_ = false;
     case kDisplayStatusOnline:
-      status = INT32(SetPowerMode(HWC2::PowerMode::On));
+      status = INT32(SetPowerMode(HWC2::PowerMode::On, false /* teardown */));
       break;
     case kDisplayStatusPause:
       display_paused_ = true;
     case kDisplayStatusOffline:
-      status = INT32(SetPowerMode(HWC2::PowerMode::Off));
+      status = INT32(SetPowerMode(HWC2::PowerMode::Off, false /* teardown */));
       break;
     default:
       DLOGW("Invalid display status %d", display_status);
@@ -1724,6 +1724,11 @@
     return HWC2::Error::None;
   }
 
+  if (!layer_stack_.flags.cursor_present) {
+    DLOGW("Cursor layer not present");
+    return HWC2::Error::BadLayer;
+  }
+
   HWCLayer *hwc_layer = GetHWCLayer(layer);
   if (hwc_layer == nullptr) {
     return HWC2::Error::BadLayer;
@@ -1915,7 +1920,7 @@
 
   if (active_secure_sessions_[kSecureDisplay] != secure_sessions[kSecureDisplay]) {
     if (secure_sessions[kSecureDisplay]) {
-      HWC2::Error error = SetPowerMode(HWC2::PowerMode::Off);
+      HWC2::Error error = SetPowerMode(HWC2::PowerMode::Off, true /* teardown */);
       if (error != HWC2::Error::None) {
         DLOGE("SetPowerMode failed. Error = %d", error);
       }
diff --git a/sdm/libs/hwc2/hwc_display.h b/sdm/libs/hwc2/hwc_display.h
index 27bed47..f14c79f 100644
--- a/sdm/libs/hwc2/hwc_display.h
+++ b/sdm/libs/hwc2/hwc_display.h
@@ -175,6 +175,12 @@
     return HWC2::Error::Unsupported;
   }
 
+  virtual HWC2::Error SetDisplayDppsAdROI(uint32_t h_start, uint32_t h_end,
+                                          uint32_t v_start, uint32_t v_end,
+                                          uint32_t factor_in, uint32_t factor_out) {
+    return HWC2::Error::Unsupported;
+  }
+
   // Display Configurations
   virtual int SetActiveDisplayConfig(uint32_t config);
   virtual int GetActiveDisplayConfig(uint32_t *config);
@@ -251,7 +257,7 @@
   virtual HWC2::Error GetDisplayType(int32_t *out_type);
   virtual HWC2::Error SetCursorPosition(hwc2_layer_t layer, int x, int y);
   virtual HWC2::Error SetVsyncEnabled(HWC2::Vsync enabled);
-  virtual HWC2::Error SetPowerMode(HWC2::PowerMode mode);
+  virtual HWC2::Error SetPowerMode(HWC2::PowerMode mode, bool teardown);
   virtual HWC2::Error CreateLayer(hwc2_layer_t *out_layer_id);
   virtual HWC2::Error DestroyLayer(hwc2_layer_t layer_id);
   virtual HWC2::Error SetLayerZOrder(hwc2_layer_t layer_id, uint32_t z);
diff --git a/sdm/libs/hwc2/hwc_display_builtin.cpp b/sdm/libs/hwc2/hwc_display_builtin.cpp
index ceda6d1..106b147 100644
--- a/sdm/libs/hwc2/hwc_display_builtin.cpp
+++ b/sdm/libs/hwc2/hwc_display_builtin.cpp
@@ -153,7 +153,7 @@
 
   if ((!isEncrypted || (isEncrypted && main_class_services_started)) &&
       bootanim_exit) {
-    DLOGI("Applying default mode");
+    DLOGI("Applying default mode for display %d", sdm_id_);
     boot_animation_completed_ = true;
     // Applying default mode after bootanimation is finished And
     // If Data is Encrypted, it is ready for access.
@@ -359,6 +359,7 @@
   output_buffer_.planes[0].stride = UINT32(handle->width);
   output_buffer_.acquire_fence_fd = dup(acquire_fence);
   output_buffer_.release_fence_fd = -1;
+  output_buffer_.handle_id = handle->id;
 
   post_processed_output_ = post_processed_output;
   readback_buffer_queued_ = true;
@@ -387,6 +388,46 @@
   return status;
 }
 
+HWC2::Error HWCDisplayBuiltIn::SetDisplayDppsAdROI(uint32_t h_start, uint32_t h_end,
+                                                   uint32_t v_start, uint32_t v_end,
+                                                   uint32_t factor_in, uint32_t factor_out) {
+  DisplayError error = kErrorNone;
+  DisplayDppsAd4RoiCfg dpps_ad4_roi_cfg = {};
+  uint32_t panel_width = 0, panel_height = 0;
+  constexpr uint16_t kMaxFactorVal = 0xffff;
+
+  if (h_start >= h_end || v_start >= v_end || factor_in > kMaxFactorVal ||
+      factor_out > kMaxFactorVal) {
+    DLOGE("Invalid roi region = [%u, %u, %u, %u, %u, %u]",
+           h_start, h_end, v_start, v_end, factor_in, factor_out);
+    return HWC2::Error::BadParameter;
+  }
+
+  GetPanelResolution(&panel_width, &panel_height);
+
+  if (h_start >= panel_width || h_end > panel_width ||
+      v_start >= panel_height || v_end > panel_height) {
+    DLOGE("Invalid roi region = [%u, %u, %u, %u], panel resolution = [%u, %u]",
+           h_start, h_end, v_start, v_end, panel_width, panel_height);
+    return HWC2::Error::BadParameter;
+  }
+
+  dpps_ad4_roi_cfg.h_start = h_start;
+  dpps_ad4_roi_cfg.h_end = h_end;
+  dpps_ad4_roi_cfg.v_start = v_start;
+  dpps_ad4_roi_cfg.v_end = v_end;
+  dpps_ad4_roi_cfg.factor_in = factor_in;
+  dpps_ad4_roi_cfg.factor_out = factor_out;
+
+  error = display_intf_->SetDisplayDppsAdROI(&dpps_ad4_roi_cfg);
+  if (error)
+    return HWC2::Error::BadConfig;
+
+  callbacks_->Refresh(HWC_DISPLAY_PRIMARY);
+
+  return HWC2::Error::None;
+}
+
 int HWCDisplayBuiltIn::Perform(uint32_t operation, ...) {
   va_list args;
   va_start(args, operation);
@@ -582,13 +623,11 @@
   dump_output_to_file_ = bit_mask_layer_type & (1 << OUTPUT_LAYER_DUMP);
   DLOGI("output_layer_dump_enable %d", dump_output_to_file_);
 
-  if (!count || !dump_output_to_file_) {
+  if (!count || !dump_output_to_file_ || (output_buffer_info_.alloc_buffer_info.fd >= 0)) {
     return HWC2::Error::None;
   }
 
   // Allocate and map output buffer
-  output_buffer_info_ = {};
-
   if (post_processed) {
     // To dump post-processed (DSPP) output, use Panel resolution.
     GetPanelResolution(&output_buffer_info_.buffer_config.width,
diff --git a/sdm/libs/hwc2/hwc_display_builtin.h b/sdm/libs/hwc2/hwc_display_builtin.h
index 1f01723..6616255 100644
--- a/sdm/libs/hwc2/hwc_display_builtin.h
+++ b/sdm/libs/hwc2/hwc_display_builtin.h
@@ -80,6 +80,8 @@
   virtual HWC2::Error GetReadbackBufferFence(int32_t *release_fence);
   virtual HWC2::Error SetQSyncMode(QSyncMode qsync_mode);
   virtual HWC2::Error ControlIdlePowerCollapse(bool enable, bool synchronous);
+  virtual HWC2::Error SetDisplayDppsAdROI(uint32_t h_start, uint32_t h_end, uint32_t v_start,
+                                          uint32_t v_end, uint32_t factor_in, uint32_t factor_out);
 
  private:
   HWCDisplayBuiltIn(CoreInterface *core_intf, BufferAllocator *buffer_allocator,
diff --git a/sdm/libs/hwc2/hwc_display_pluggable.cpp b/sdm/libs/hwc2/hwc_display_pluggable.cpp
index d97c423..9ac22be 100644
--- a/sdm/libs/hwc2/hwc_display_pluggable.cpp
+++ b/sdm/libs/hwc2/hwc_display_pluggable.cpp
@@ -236,7 +236,7 @@
       }
       int release_fence = -1;
       display_null_.GetDisplayState(&state);
-      display_intf_->SetDisplayState(state, &release_fence);
+      display_intf_->SetDisplayState(state, false /* teardown */, &release_fence);
       if (release_fence >= 0) {
         ::close(release_fence);
       }
@@ -255,7 +255,7 @@
       // Preserve required attributes of HDMI display that surfaceflinger sees.
       // Restore HDMI attributes when display is reconnected.
       display_intf_->GetDisplayState(&state);
-      display_null_.SetDisplayState(state, &release_fence);
+      display_null_.SetDisplayState(state, false /* teardown */, &release_fence);
       if (release_fence >= 0) {
         ::close(release_fence);
       }
diff --git a/sdm/libs/hwc2/hwc_display_virtual.cpp b/sdm/libs/hwc2/hwc_display_virtual.cpp
index 8454536..a05173f 100644
--- a/sdm/libs/hwc2/hwc_display_virtual.cpp
+++ b/sdm/libs/hwc2/hwc_display_virtual.cpp
@@ -63,7 +63,7 @@
     return status;
   }
 
-  status = INT32(hwc_display_virtual->SetPowerMode(HWC2::PowerMode::On));
+  status = INT32(hwc_display_virtual->SetPowerMode(HWC2::PowerMode::On, false /* teardown */));
   if (status) {
     DLOGW("Failed to set power mode on virtual display");
     Destroy(hwc_display_virtual);
diff --git a/sdm/libs/hwc2/hwc_layers.cpp b/sdm/libs/hwc2/hwc_layers.cpp
index 4dc8f13..9ba14a9 100644
--- a/sdm/libs/hwc2/hwc_layers.cpp
+++ b/sdm/libs/hwc2/hwc_layers.cpp
@@ -777,6 +777,7 @@
   // in layer_buffer or copy directly to Vector
   if (cr_stats->bDataValid) {
     switch (cr_stats->version) {
+      case UBWC_3_0:
       case UBWC_2_0:
         cr_vec->push_back(std::make_pair(32, cr_stats->ubwc_stats.nCRStatsTile32));
         cr_vec->push_back(std::make_pair(64, cr_stats->ubwc_stats.nCRStatsTile64));
diff --git a/sdm/libs/hwc2/hwc_session.cpp b/sdm/libs/hwc2/hwc_session.cpp
index fbe57b0..9b5e8da 100644
--- a/sdm/libs/hwc2/hwc_session.cpp
+++ b/sdm/libs/hwc2/hwc_session.cpp
@@ -48,7 +48,6 @@
 #define __CLASS__ "HWCSession"
 
 #define HWC_UEVENT_SWITCH_HDMI "change@/devices/virtual/switch/hdmi"
-#define HWC_UEVENT_GRAPHICS_FB0 "change@/devices/virtual/graphics/fb0"
 #define HWC_UEVENT_DRM_EXT_HOTPLUG "mdss_mdp/drm/card"
 
 static sdm::HWCSession::HWCModuleMethods g_hwc_module_methods;
@@ -606,23 +605,6 @@
   return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::GetDisplayType, out_type);
 }
 
-static int32_t GetDozeSupport(hwc2_device_t *device, hwc2_display_t display, int32_t *out_support) {
-  if (!device || !out_support) {
-    return HWC2_ERROR_BAD_PARAMETER;
-  }
-
-  if (display >= HWCSession::kNumDisplays) {
-    return HWC2_ERROR_BAD_DISPLAY;
-  }
-
-  if (display == HWC_DISPLAY_PRIMARY) {
-    *out_support = 1;
-  } else {
-    *out_support = 0;
-  }
-
-  return HWC2_ERROR_NONE;
-}
 
 static int32_t GetHdrCapabilities(hwc2_device_t* device, hwc2_display_t display,
                                   uint32_t* out_num_types, int32_t* out_types,
@@ -686,7 +668,7 @@
   if (!hwc_session->primary_ready_ && (display == HWC_DISPLAY_PRIMARY)) {
     hwc_session->primary_ready_ = true;
     hwc_session->CreateBuiltInDisplays();
-    hwc_session->CreatePluggableDisplays(false);
+    hwc_session->HandlePluggableDisplays(false);
   }
 
   return INT32(status);
@@ -891,12 +873,13 @@
 
   //  all displays support on/off. Check for doze modes
   int support = 0;
-  GetDozeSupport(device, display, &support);
+  hwc_session->GetDozeSupport(device, display, &support);
   if (!support && (mode == HWC2::PowerMode::Doze || mode == HWC2::PowerMode::DozeSuspend)) {
     return HWC2_ERROR_UNSUPPORTED;
   }
 
-  auto error = CallDisplayFunction(device, display, &HWCDisplay::SetPowerMode, mode);
+  auto error = CallDisplayFunction(device, display, &HWCDisplay::SetPowerMode, mode,
+                                   false /* teardown */);
   if (error != HWC2_ERROR_NONE) {
     return error;
   }
@@ -925,6 +908,25 @@
   return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::SetVsyncEnabled, enabled);
 }
 
+int32_t HWCSession::GetDozeSupport(hwc2_device_t *device, hwc2_display_t display,
+                                   int32_t *out_support) {
+  if (!device || !out_support) {
+    return HWC2_ERROR_BAD_PARAMETER;
+  }
+
+  if (display >= HWCSession::kNumDisplays) {
+    return HWC2_ERROR_BAD_DISPLAY;
+  }
+
+  HWCSession *hwc_session = static_cast<HWCSession *>(device);
+  *out_support = 0;
+  if (display == HWC_DISPLAY_PRIMARY || display == hwc_session->GetNextBuiltinIndex()) {
+    *out_support = 1;
+  }
+
+  return HWC2_ERROR_NONE;
+}
+
 int32_t HWCSession::ValidateDisplay(hwc2_device_t *device, hwc2_display_t display,
                                     uint32_t *out_num_types, uint32_t *out_num_requests) {
   //  out_num_types and out_num_requests will be non-NULL
@@ -1145,6 +1147,16 @@
   return HWC2::Error::None;
 }
 
+hwc2_display_t HWCSession::GetNextBuiltinIndex() {
+  for (auto &map_info : map_info_builtin_) {
+    if (hwc_display_[map_info.client_id]) {
+        return map_info.client_id;
+    }
+  }
+
+  return 0;
+}
+
 // Qclient methods
 android::status_t HWCSession::notifyCallback(uint32_t command, const android::Parcel *input_parcel,
                                              android::Parcel *output_parcel) {
@@ -1419,6 +1431,14 @@
       status = SetIdlePC(input_parcel);
       break;
 
+    case qService::IQService::SET_DPPS_AD4_ROI_CONFIG:
+      if (!input_parcel) {
+        DLOGE("QService command = %d: input_parcel needed.", command);
+        break;
+      }
+      status = SetAd4RoiConfig(input_parcel);
+      break;
+
     default:
       DLOGW("QService command = %d is not supported.", command);
       break;
@@ -1618,6 +1638,29 @@
   return 0;
 }
 
+android::status_t HWCSession::SetAd4RoiConfig(const android::Parcel *input_parcel) {
+  auto display_id = static_cast<uint32_t>(input_parcel->readInt32());
+  auto h_s = static_cast<uint32_t>(input_parcel->readInt32());
+  auto h_e = static_cast<uint32_t>(input_parcel->readInt32());
+  auto v_s = static_cast<uint32_t>(input_parcel->readInt32());
+  auto v_e = static_cast<uint32_t>(input_parcel->readInt32());
+  auto f_in = static_cast<uint32_t>(input_parcel->readInt32());
+  auto f_out = static_cast<uint32_t>(input_parcel->readInt32());
+
+#ifdef DISPLAY_CONFIG_1_5
+  return static_cast<android::status_t>(SetDisplayDppsAdROI(display_id, h_s, h_e, v_s,
+                                                            v_e, f_in, f_out));
+#else
+  auto err = CallDisplayFunction(static_cast<hwc2_device_t *>(this), display_id,
+                                 &HWCDisplay::SetDisplayDppsAdROI, h_s, h_e, v_s, v_e,
+                                 f_in, f_out);
+  if (err != HWC2_ERROR_NONE)
+    return -EINVAL;
+
+  return 0;
+#endif
+}
+
 android::status_t HWCSession::SetColorModeWithRenderIntentOverride(
     const android::Parcel *input_parcel) {
   auto display = static_cast<hwc2_display_t>(input_parcel->readInt32());
@@ -1716,6 +1759,41 @@
   }
 }
 
+android::status_t HWCSession::QdcmCMDDispatch(uint32_t display_id,
+                                              const PPDisplayAPIPayload &req_payload,
+                                              PPDisplayAPIPayload *resp_payload,
+                                              PPPendingParams *pending_action) {
+  int ret = 0;
+  bool is_physical_display = false;
+
+  if (display_id >= kNumDisplays || !hwc_display_[display_id]) {
+      DLOGW("Invalid display id or display = %d is not connected.", display_id);
+      return -ENODEV;
+  }
+
+  if (display_id == map_info_primary_.client_id) {
+    is_physical_display = true;
+  } else {
+    for (auto &map_info : map_info_builtin_) {
+      if (map_info.client_id == display_id) {
+        is_physical_display = true;
+        break;
+     }
+    }
+  }
+
+  if (!is_physical_display) {
+    DLOGW("Skipping QDCM command dispatch on display = %d", display_id);
+    return ret;
+  }
+
+  ret = hwc_display_[display_id]->ColorSVCRequestRoute(req_payload,
+                                                       resp_payload,
+                                                       pending_action);
+
+  return ret;
+}
+
 android::status_t HWCSession::QdcmCMDHandler(const android::Parcel *input_parcel,
                                              android::Parcel *output_parcel) {
   int ret = 0;
@@ -1723,6 +1801,7 @@
   uint32_t display_id(0);
   PPPendingParams pending_action;
   PPDisplayAPIPayload resp_payload, req_payload;
+  uint8_t *disp_id = NULL;
 
   if (!color_mgr_) {
     DLOGW("color_mgr_ not initialized.");
@@ -1735,21 +1814,7 @@
   // Read display_id, payload_size and payload from in_parcel.
   ret = HWCColorManager::CreatePayloadFromParcel(*input_parcel, &display_id, &req_payload);
   if (!ret) {
-    if (display_id >= kNumDisplays || !hwc_display_[display_id]) {
-      DLOGW("Invalid display id or display = %d is not connected.", display_id);
-      ret = -ENODEV;
-    }
-  }
-
-  if (!ret) {
-    if ((HWC_DISPLAY_PRIMARY == display_id) || (HWC_DISPLAY_EXTERNAL == display_id)) {
-      ret = hwc_display_[display_id]->ColorSVCRequestRoute(req_payload, &resp_payload,
-                                                           &pending_action);
-    } else {
-      // Virtual, Tertiary etc. not supported.
-      DLOGW("Operation not supported on display = %d.", display_id);
-      ret = -EINVAL;
-    }
+    ret = QdcmCMDDispatch(display_id, req_payload, &resp_payload, &pending_action);
   }
 
   if (ret) {
@@ -1760,12 +1825,6 @@
   }
 
   if (kNoAction != pending_action.action) {
-    // Restrict pending actions to primary display.
-    if (HWC_DISPLAY_PRIMARY != display_id) {
-      DLOGW("Skipping pending action %d on display = %d.", pending_action.action, display_id);
-      pending_action.action = kNoAction;
-    }
-
     int32_t action = pending_action.action;
     int count = -1;
     while (action > 0) {
@@ -1776,33 +1835,33 @@
       if (!bit)
         continue;
 
-      DLOGV_IF(kTagQDCM, "pending action = %d", BITMAP(count));
+      DLOGV_IF(kTagQDCM, "pending action = %d, display_id = %d", BITMAP(count), display_id);
       switch (BITMAP(count)) {
         case kInvalidating:
-          Refresh(HWC_DISPLAY_PRIMARY);
+          Refresh(display_id);
           break;
         case kEnterQDCMMode:
-          ret = color_mgr_->EnableQDCMMode(true, hwc_display_[HWC_DISPLAY_PRIMARY]);
+          ret = color_mgr_->EnableQDCMMode(true, hwc_display_[display_id]);
           break;
         case kExitQDCMMode:
-          ret = color_mgr_->EnableQDCMMode(false, hwc_display_[HWC_DISPLAY_PRIMARY]);
+          ret = color_mgr_->EnableQDCMMode(false, hwc_display_[display_id]);
           break;
         case kApplySolidFill:
           {
-            SCOPE_LOCK(locker_[HWC_DISPLAY_PRIMARY]);
+            SCOPE_LOCK(locker_[display_id]);
             ret = color_mgr_->SetSolidFill(pending_action.params,
-                                            true, hwc_display_[HWC_DISPLAY_PRIMARY]);
+                                           true, hwc_display_[display_id]);
           }
-          Refresh(HWC_DISPLAY_PRIMARY);
+          Refresh(display_id);
           usleep(kSolidFillDelay);
           break;
         case kDisableSolidFill:
           {
-            SCOPE_LOCK(locker_[HWC_DISPLAY_PRIMARY]);
+            SCOPE_LOCK(locker_[display_id]);
             ret = color_mgr_->SetSolidFill(pending_action.params,
-                                            false, hwc_display_[HWC_DISPLAY_PRIMARY]);
+                                           false, hwc_display_[display_id]);
           }
-          Refresh(HWC_DISPLAY_PRIMARY);
+          Refresh(display_id);
           usleep(kSolidFillDelay);
           break;
         case kSetPanelBrightness:
@@ -1811,30 +1870,65 @@
             DLOGE("Brightness value is Null");
             ret = -EINVAL;
           } else {
-            ret = hwc_display_[HWC_DISPLAY_PRIMARY]->SetPanelBrightness(*brightness_value);
+            ret = hwc_display_[display_id]->SetPanelBrightness(*brightness_value);
           }
           break;
         case kEnableFrameCapture:
           ret = color_mgr_->SetFrameCapture(pending_action.params, true,
-                                        hwc_display_[HWC_DISPLAY_PRIMARY]);
-          Refresh(HWC_DISPLAY_PRIMARY);
+                                            hwc_display_[display_id]);
+          Refresh(display_id);
           break;
         case kDisableFrameCapture:
           ret = color_mgr_->SetFrameCapture(pending_action.params, false,
-                                        hwc_display_[HWC_DISPLAY_PRIMARY]);
+                                            hwc_display_[display_id]);
           break;
         case kConfigureDetailedEnhancer:
           ret = color_mgr_->SetDetailedEnhancer(pending_action.params,
-                                            hwc_display_[HWC_DISPLAY_PRIMARY]);
-          Refresh(HWC_DISPLAY_PRIMARY);
+                                                hwc_display_[display_id]);
+          Refresh(display_id);
           break;
         case kModeSet:
           ret = static_cast<int>
-                 (hwc_display_[HWC_DISPLAY_PRIMARY]->RestoreColorTransform());
-          Refresh(HWC_DISPLAY_PRIMARY);
+                  (hwc_display_[display_id]->RestoreColorTransform());
+          Refresh(display_id);
           break;
         case kNoAction:
           break;
+        case kMultiDispProc:
+          for (auto &map_info : map_info_builtin_) {
+            uint32_t id = UINT32(map_info.client_id);
+            if (id < kNumDisplays && hwc_display_[id]) {
+              int result = 0;
+              resp_payload.DestroyPayload();
+              result = hwc_display_[id]->ColorSVCRequestRoute(req_payload,
+                                                              &resp_payload,
+                                                              &pending_action);
+              if (result) {
+                DLOGW("Failed to dispatch action to disp %d ret %d", id, result);
+                ret = result;
+              }
+            }
+          }
+          break;
+        case kMultiDispGetId:
+          ret = resp_payload.CreatePayloadBytes(HWC_NUM_DISPLAY_TYPES, &disp_id);
+          if (ret) {
+            DLOGW("Unable to create response payload!");
+          } else {
+            for (int i = 0; i < HWC_NUM_DISPLAY_TYPES; i++) {
+              disp_id[i] = HWC_NUM_DISPLAY_TYPES;
+            }
+            if (hwc_display_[HWC_DISPLAY_PRIMARY]) {
+              disp_id[HWC_DISPLAY_PRIMARY] = HWC_DISPLAY_PRIMARY;
+            }
+            for (auto &map_info : map_info_builtin_) {
+              uint64_t id = map_info.client_id;
+              if (id < kNumDisplays && hwc_display_[id]) {
+                disp_id[id] = (uint8_t)id;
+              }
+            }
+          }
+          break;
         default:
           DLOGW("Invalid pending action = %d!", pending_action.action);
           break;
@@ -1882,16 +1976,6 @@
 }
 
 void HWCSession::UEventHandler(const char *uevent_data, int length) {
-  if (strcasestr(uevent_data, HWC_UEVENT_GRAPHICS_FB0)) {
-    DLOGI("Uevent FB0 = %s", uevent_data);
-    int panel_reset = GetEventValue(uevent_data, length, "PANEL_ALIVE=");
-    if (panel_reset == 0) {
-      Refresh(0);
-      reset_panel_ = true;
-    }
-    return;
-  }
-
   if (strcasestr(uevent_data, HWC_UEVENT_DRM_EXT_HOTPLUG)) {
     // MST hotplug will not carry connection status/test pattern etc.
     // Pluggable display handler will check all connection status' and take action accordingly.
@@ -1903,8 +1987,9 @@
 
     hpd_bpp_ = GetEventValue(uevent_data, length, "bpp=");
     hpd_pattern_ = GetEventValue(uevent_data, length, "pattern=");
-    DLOGI("Uevent = %s, bpp = %d, pattern = %d", uevent_data, hpd_bpp_, hpd_pattern_);
-    if (CreatePluggableDisplays(true)) {
+    DLOGI("Uevent = %s, status = %s, MST_HOTPLUG = %s, bpp = %d, pattern = %d", uevent_data,
+          str_status ? str_status : "NULL", str_mst ? str_mst : "NULL", hpd_bpp_, hpd_pattern_);
+    if (HandlePluggableDisplays(true)) {
       DLOGE("Could not handle hotplug. Event dropped.");
     }
 
@@ -1916,30 +2001,6 @@
   }
 }
 
-void HWCSession::ResetPanel() {
-  HWC2::Error status = HWC2::Error::None;
-
-  DLOGI("Powering off primary");
-  status = hwc_display_[HWC_DISPLAY_PRIMARY]->SetPowerMode(HWC2::PowerMode::Off);
-  if (status != HWC2::Error::None) {
-    DLOGE("power-off on primary failed with error = %d", status);
-  }
-
-  DLOGI("Restoring power mode on primary");
-  HWC2::PowerMode mode = hwc_display_[HWC_DISPLAY_PRIMARY]->GetLastPowerMode();
-  status = hwc_display_[HWC_DISPLAY_PRIMARY]->SetPowerMode(mode);
-  if (status != HWC2::Error::None) {
-    DLOGE("Setting power mode = %d on primary failed with error = %d", mode, status);
-  }
-
-  status = hwc_display_[HWC_DISPLAY_PRIMARY]->SetVsyncEnabled(HWC2::Vsync::Enable);
-  if (status != HWC2::Error::None) {
-    DLOGE("enabling vsync failed for primary with error = %d", status);
-  }
-
-  reset_panel_ = false;
-}
-
 int HWCSession::GetVsyncPeriod(int disp) {
   SCOPE_LOCK(locker_[disp]);
   // default value
@@ -2110,7 +2171,7 @@
   return status;
 }
 
-int HWCSession::CreatePluggableDisplays(bool delay_hotplug) {
+int HWCSession::HandlePluggableDisplays(bool delay_hotplug) {
   if (!primary_ready_) {
     DLOGI("Primary display is not ready. Connect displays later if any.");
     return 0;
@@ -2323,11 +2384,6 @@
 
   if (display == HWC_DISPLAY_PRIMARY) {
     // TODO(user): This can be moved to HWCDisplayPrimary
-    if (reset_panel_) {
-      DLOGW("panel is in bad state, resetting the panel");
-      ResetPanel();
-    }
-
     if (need_invalidate_) {
       Refresh(display);
       need_invalidate_ = false;
@@ -2367,7 +2423,8 @@
   for (hwc2_display_t display = HWC_DISPLAY_PRIMARY; display < HWC_NUM_DISPLAY_TYPES; display++) {
     if (hwc_display_[display] != NULL) {
       DLOGI("Powering off display = %d", display);
-      status = hwc_display_[display]->SetPowerMode(HWC2::PowerMode::Off);
+      status = hwc_display_[display]->SetPowerMode(HWC2::PowerMode::Off,
+                                                   true /* teardown */);
       if (status != HWC2::Error::None) {
         DLOGE("Power off for display = %d failed with error = %d", display, status);
       }
@@ -2376,7 +2433,7 @@
   for (hwc2_display_t display = HWC_DISPLAY_PRIMARY; display < HWC_NUM_DISPLAY_TYPES; display++) {
     if (hwc_display_[display] != NULL) {
       DLOGI("Powering on display = %d", display);
-      status = hwc_display_[display]->SetPowerMode(HWC2::PowerMode::On);
+      status = hwc_display_[display]->SetPowerMode(HWC2::PowerMode::On, false /* teardown */);
       if (status != HWC2::Error::None) {
         DLOGE("Power on for display = %d failed with error = %d", display, status);
       }
@@ -2443,7 +2500,8 @@
 
   if (power_on_pending_[HWC_DISPLAY_EXTERNAL]) {
     if (hwc_display_[HWC_DISPLAY_EXTERNAL]) {
-      HWC2::Error status = hwc_display_[HWC_DISPLAY_EXTERNAL]->SetPowerMode(HWC2::PowerMode::On);
+      HWC2::Error status = hwc_display_[HWC_DISPLAY_EXTERNAL]->SetPowerMode(HWC2::PowerMode::On,
+                                                                            false /* teardown */);
       if (status == HWC2::Error::None) {
         power_on_pending_[HWC_DISPLAY_EXTERNAL] = false;
       }
@@ -2452,7 +2510,8 @@
 
   if (power_on_pending_[HWC_DISPLAY_VIRTUAL]) {
     if (hwc_display_[HWC_DISPLAY_VIRTUAL]) {
-      HWC2::Error status = hwc_display_[HWC_DISPLAY_VIRTUAL]->SetPowerMode(HWC2::PowerMode::On);
+      HWC2::Error status = hwc_display_[HWC_DISPLAY_VIRTUAL]->SetPowerMode(HWC2::PowerMode::On,
+                                                                           false /* teardown */);
       if (status == HWC2::Error::None) {
         power_on_pending_[HWC_DISPLAY_VIRTUAL] = false;
       }
@@ -2582,13 +2641,9 @@
 
   // If primary display is powered off, change vsync source to next builtin display.
   // If primary display is powerd on, change vsync source back to primary display.
-  // First check for active builtins. If not found switch to pluggable displays.
-  std::vector<DisplayMapInfo> map_info = map_info_builtin_;
-  std::copy(map_info_pluggable_.begin(), map_info_pluggable_.end(), std::back_inserter(map_info));
-
   if (power_mode == HWC2::PowerMode::Off) {
     hwc2_display_t next_vsync_source = HWC_DISPLAY_PRIMARY;
-    for (auto &info : map_info) {
+    for (auto &info : map_info_builtin_) {
       auto &hwc_display = hwc_display_[info.client_id];
       if (!hwc_display) {
         continue;
diff --git a/sdm/libs/hwc2/hwc_session.h b/sdm/libs/hwc2/hwc_session.h
index f581f60..b2a4100 100644
--- a/sdm/libs/hwc2/hwc_session.h
+++ b/sdm/libs/hwc2/hwc_session.h
@@ -20,7 +20,9 @@
 #ifndef __HWC_SESSION_H__
 #define __HWC_SESSION_H__
 
-#ifdef DISPLAY_CONFIG_1_4
+#ifdef DISPLAY_CONFIG_1_5
+#include <vendor/display/config/1.5/IDisplayConfig.h>
+#elif DISPLAY_CONFIG_1_4
 #include <vendor/display/config/1.4/IDisplayConfig.h>
 #elif DISPLAY_CONFIG_1_3
 #include <vendor/display/config/1.3/IDisplayConfig.h>
@@ -51,7 +53,9 @@
 
 namespace sdm {
 
-#ifdef DISPLAY_CONFIG_1_4
+#ifdef DISPLAY_CONFIG_1_5
+using vendor::display::config::V1_5::IDisplayConfig;
+#elif DISPLAY_CONFIG_1_4
 using vendor::display::config::V1_4::IDisplayConfig;
 #elif  DISPLAY_CONFIG_1_3
 using vendor::display::config::V1_3::IDisplayConfig;
@@ -206,6 +210,8 @@
 
   static int32_t SetVsyncEnabled(hwc2_device_t *device, hwc2_display_t display,
                                  int32_t int_enabled);
+  static int32_t GetDozeSupport(hwc2_device_t *device, hwc2_display_t display,
+                                int32_t *out_support);
 
   static Locker locker_[kNumDisplays];
 
@@ -240,7 +246,7 @@
   int GetDisplayIndex(int dpy);
   int CreatePrimaryDisplay();
   int CreateBuiltInDisplays();
-  int CreatePluggableDisplays(bool delay_hotplug);
+  int HandlePluggableDisplays(bool delay_hotplug);
   int HandleConnectedDisplays(HWDisplaysInfo *hw_displays_info, bool delay_hotplug);
   int HandleDisconnectedDisplays(HWDisplaysInfo *hw_displays_info);
   void DestroyDisplay(DisplayMapInfo *map_info);
@@ -298,6 +304,11 @@
 #ifdef DISPLAY_CONFIG_1_4
   Return<void> getWriteBackCapabilities(getWriteBackCapabilities_cb _hidl_cb) override;
 #endif
+#ifdef DISPLAY_CONFIG_1_5
+  Return<int32_t> SetDisplayDppsAdROI(uint32_t dispaly_id, uint32_t h_start, uint32_t h_end,
+                                      uint32_t v_start, uint32_t v_end, uint32_t factor_in,
+                                      uint32_t factor_out) override;
+#endif
 
   // QClient methods
   virtual android::status_t notifyCallback(uint32_t command, const android::Parcel *input_parcel,
@@ -309,6 +320,10 @@
   android::status_t ConfigureRefreshRate(const android::Parcel *input_parcel);
   android::status_t QdcmCMDHandler(const android::Parcel *input_parcel,
                                    android::Parcel *output_parcel);
+  android::status_t QdcmCMDDispatch(uint32_t display_id,
+                                    const PPDisplayAPIPayload &req_payload,
+                                    PPDisplayAPIPayload *resp_payload,
+                                    PPPendingParams *pending_action);
   android::status_t GetDisplayAttributesForConfig(const android::Parcel *input_parcel,
                                                   android::Parcel *output_parcel);
   android::status_t GetVisibleDisplayRect(const android::Parcel *input_parcel,
@@ -322,6 +337,7 @@
   android::status_t SetQSyncMode(const android::Parcel *input_parcel);
   android::status_t SetIdlePC(const android::Parcel *input_parcel);
   android::status_t RefreshScreen(const android::Parcel *input_parcel);
+  android::status_t SetAd4RoiConfig(const android::Parcel *input_parcel);
 
   void Refresh(hwc2_display_t display);
   void HotPlug(hwc2_display_t display, HWC2::Connection state);
@@ -332,6 +348,7 @@
   void HandlePowerOnPending(hwc2_display_t display, int retire_fence);
   void HandleHotplugPending(hwc2_display_t disp_id, int retire_fence);
   void UpdateVsyncSource(hwc2_display_t display);
+  hwc2_display_t GetNextBuiltinIndex();
 
   CoreInterface *core_intf_ = nullptr;
   HWCDisplay *hwc_display_[kNumDisplays] = {nullptr};
diff --git a/sdm/libs/hwc2/hwc_session_services.cpp b/sdm/libs/hwc2/hwc_session_services.cpp
index a34d0de..ff71e82 100644
--- a/sdm/libs/hwc2/hwc_session_services.cpp
+++ b/sdm/libs/hwc2/hwc_session_services.cpp
@@ -602,8 +602,8 @@
       if (!idle_pc_ref_cnt_) {
         HWC2::Error err =
             hwc_display_[HWC_DISPLAY_PRIMARY]->ControlIdlePowerCollapse(enable, synchronous);
-        if (err != HWC2::Error::None) {
-          return -EINVAL;
+        if (err == HWC2::Error::Unsupported) {
+          return 0;
         }
         Refresh(HWC_DISPLAY_PRIMARY);
         int32_t error = locker_[HWC_DISPLAY_PRIMARY].WaitFinite(kCommitDoneTimeoutMs);
@@ -618,8 +618,8 @@
       if (!(idle_pc_ref_cnt_ - 1)) {
         HWC2::Error err =
             hwc_display_[HWC_DISPLAY_PRIMARY]->ControlIdlePowerCollapse(enable, synchronous);
-        if (err != HWC2::Error::None) {
-          return -EINVAL;
+        if (err == HWC2::Error::Unsupported) {
+          return 0;
         }
         DLOGI("Idle PC enabled!!");
       }
@@ -663,4 +663,14 @@
 }
 #endif  // DISPLAY_CONFIG_1_4
 
+#ifdef DISPLAY_CONFIG_1_5
+Return<int32_t> HWCSession::SetDisplayDppsAdROI(uint32_t display_id, uint32_t h_start,
+                                                uint32_t h_end, uint32_t v_start, uint32_t v_end,
+                                                uint32_t factor_in, uint32_t factor_out) {
+  return CallDisplayFunction(static_cast<hwc2_device_t *>(this), display_id,
+                             &HWCDisplay::SetDisplayDppsAdROI, h_start, h_end, v_start, v_end,
+                             factor_in, factor_out);
+}
+#endif  // DISPLAY_CONFIG_1_5
+
 }  // namespace sdm
diff --git a/sdm/libs/utils/Makefile.am b/sdm/libs/utils/Makefile.am
index d8d8dc5..098775a 100644
--- a/sdm/libs/utils/Makefile.am
+++ b/sdm/libs/utils/Makefile.am
@@ -9,4 +9,5 @@
 libsdmutils_la_SOURCES = $(cpp_sources)
 libsdmutils_la_CFLAGS = $(COMMON_CFLAGS) -DLOG_TAG=\"SDM\"
 libsdmutils_la_CPPFLAGS = $(AM_CPPFLAGS)
+libsdmutils_la_LIBADD = ../../../libdebug/libdisplaydebug.la
 libsdmutils_la_LDFLAGS = -shared -avoid-version