Merge "sdm: Do not mandatory enable demura while set power on"
diff --git a/composer/QtiComposerClient.cpp b/composer/QtiComposerClient.cpp
index 2fb19e6..a8e4a9c 100644
--- a/composer/QtiComposerClient.cpp
+++ b/composer/QtiComposerClient.cpp
@@ -1376,7 +1376,7 @@
 
 bool QtiComposerClient::CommandReader::parseSetClientTarget(uint16_t length) {
   // 4 parameters followed by N rectangles
-  if ((length - 4) % 4 != 0) {
+  if (length < 4 || ((length - 4) % 4 != 0)) {
     return false;
   }
 
@@ -1957,7 +1957,7 @@
 bool QtiComposerClient::CommandReader::parseSetLayerPerFrameMetadataBlobs(uint16_t length) {
   // must have at least one metadata blob
   // of at least size 1 in queue (i.e {/*numBlobs=*/1, key, size, blob})
-  if (length < 4) {
+  if (length <= 4) {
     return false;
   }
 
@@ -1971,7 +1971,7 @@
     uint32_t blobSize = read();
     length -= 2;
 
-    if (length * sizeof(uint32_t) < blobSize) {
+    if (length * sizeof(uint32_t) < blobSize && (length % 2 != 0)) {
       return false;
     }
 
diff --git a/composer/hwc_display.cpp b/composer/hwc_display.cpp
old mode 100644
new mode 100755
index 1db3c93..b992a04
--- a/composer/hwc_display.cpp
+++ b/composer/hwc_display.cpp
@@ -914,7 +914,8 @@
 HWC2::Error HWCDisplay::SetLayerType(hwc2_layer_t layer_id, IQtiComposerClient::LayerType type) {
   const auto map_layer = layer_map_.find(layer_id);
   if (map_layer == layer_map_.end()) {
-    DLOGE("[%" PRIu64 "] SetLayerType failed to find layer", id_);
+    DLOGW("display [%" PRIu64"]-[%" PRIu64 "] SetLayerType (%" PRIu64 ") failed to find layer",
+        id_, type_, layer_id);
     return HWC2::Error::BadLayer;
   }
 
@@ -2020,13 +2021,16 @@
         reinterpret_cast<const native_handle_t *>(layer->input_buffer.buffer_id);
     Fence::Wait(layer->input_buffer.acquire_fence);
 
-    DLOGI("Dump layer[%d] of %lu handle %p", i, layer_stack_.layers.size(), handle);
 
     if (!handle) {
-      DLOGE("Buffer handle is null");
+      DLOGW("Buffer handle is detected as null for layer: %s(%d) out of %lu layers with layer "
+            "flag value: %u", layer->layer_name.c_str(), layer->layer_id,
+            layer_stack_.layers.size(), layer->flags);
       continue;
     }
 
+    DLOGI("Dump layer[%d] of %lu handle %p", i, layer_stack_.layers.size(), handle);
+
     void *base_ptr = NULL;
     int error = buffer_allocator_->MapBuffer(handle, nullptr, &base_ptr);
     if (error != kErrorNone) {
@@ -2866,7 +2870,7 @@
                                 vsync_period_change_constraints->desiredTimeNanos);
 
   out_timeline->refreshRequired = true;
-  if (info.x_pixels != fb_width_ || info.y_pixels != fb_height_) {
+  if (is_client_up_ && (info.x_pixels != fb_width_ || info.y_pixels != fb_height_)) {
     out_timeline->refreshRequired = false;
     fb_width_ = info.x_pixels;
     fb_height_ = info.y_pixels;
@@ -3145,7 +3149,11 @@
 }
 
 DisplayError HWCDisplay::PostHandleSecureEvent(SecureEvent secure_event) {
-  return display_intf_->PostHandleSecureEvent(secure_event);
+  DisplayError err = display_intf_->PostHandleSecureEvent(secure_event);
+  if (err == kErrorNone) {
+    secure_event_ = secure_event;
+  }
+  return err;
 }
 
 int HWCDisplay::GetCwbBufferResolution(CwbConfig *cwb_config, uint32_t *x_pixels,
@@ -3167,37 +3175,36 @@
     return kErrorParameters;
   }
 
-  if (!display_intf_->HandleCwbTeardown()) {
-    bool pending_cwb_request = false;
-    {
-      std::unique_lock<std::mutex> lock(cwb_mutex_);
-      pending_cwb_request = !!cwb_buffer_map_.size();
-    }
-
-    if (!pending_cwb_request) {
-      dump_frame_count_ = 0;
-      dump_frame_index_ = 0;
-      dump_output_to_file_ = false;
-      if (output_buffer_base_ != nullptr) {
-        if (munmap(output_buffer_base_, output_buffer_info_.alloc_buffer_info.size) != 0) {
-          DLOGW("unmap failed with err %d", errno);
-        }
-      }
-
-      if (buffer_allocator_ && buffer_allocator_->FreeBuffer(&output_buffer_info_) != 0) {
-        DLOGW("FreeBuffer failed");
-      }
-      output_buffer_info_ = {};
-      output_buffer_base_ = nullptr;
-      frame_capture_buffer_queued_ = false;
-      frame_capture_status_ = 0;
-      *needs_refresh = false;
-      return kErrorNone;
-    }
+  bool pending_cwb_request = false;
+  {
+  std::unique_lock<std::mutex> lock(cwb_mutex_);
+  pending_cwb_request = !!cwb_buffer_map_.size();
   }
 
-  *needs_refresh = true;
-  return kErrorNone;
+  if (!pending_cwb_request) {
+    dump_frame_count_ = 0;
+    dump_frame_index_ = 0;
+    dump_output_to_file_ = false;
+    if (output_buffer_base_ != nullptr) {
+      if (munmap(output_buffer_base_, output_buffer_info_.alloc_buffer_info.size) != 0) {
+        DLOGW("unmap failed with err %d", errno);
+      }
+    }
+
+    if (buffer_allocator_ && buffer_allocator_->FreeBuffer(&output_buffer_info_) != 0) {
+      DLOGW("FreeBuffer failed");
+    }
+    output_buffer_info_ = {};
+    output_buffer_base_ = nullptr;
+    frame_capture_buffer_queued_ = false;
+    frame_capture_status_ = 0;
+    *needs_refresh = false;
+    return kErrorNone;
+  } else {
+    *needs_refresh = true;
+    display_intf_->HandleCwbTeardown();
+    return kErrorNone;
+  }
 }
 
 void HWCDisplay::MMRMEvent(bool restricted) {
@@ -3698,4 +3705,7 @@
   display_intf_->Abort();
 }
 
-} //namespace sdm
+void HWCDisplay::MarkClientActive(bool is_client_up) {
+  is_client_up_ = is_client_up ;
+}
+}  // namespace sdm
diff --git a/composer/hwc_display.h b/composer/hwc_display.h
index c38859e..017c41e 100644
--- a/composer/hwc_display.h
+++ b/composer/hwc_display.h
@@ -523,6 +523,7 @@
   virtual void SetConfigInfo(std::map<uint32_t, DisplayConfigVariableInfo>& variable_config_map,
                              int active_config_index, uint32_t num_configs) {};
   virtual void Abort();
+  virtual void MarkClientActive(bool is_client_up);
 
  protected:
   static uint32_t throttling_refresh_rate_;
@@ -703,6 +704,7 @@
   bool draw_method_set_ = false;
   bool validate_done_ = false;
   bool client_target_3_1_set_ = false;
+  bool is_client_up_ = false;
 };
 
 inline int HWCDisplay::Perform(uint32_t operation, ...) {
diff --git a/composer/hwc_display_builtin.cpp b/composer/hwc_display_builtin.cpp
index 3d63a29..6107364 100644
--- a/composer/hwc_display_builtin.cpp
+++ b/composer/hwc_display_builtin.cpp
@@ -206,6 +206,11 @@
   DebugHandler::Get()->GetProperty(ENABLE_ROUNDED_CORNER, &value);
   enable_round_corner_ = (value == 1);
 
+  value = 0;
+  if (DebugHandler::Get()->GetProperty(LARGE_COMP_HINT_THRESHOLD, &value) == kErrorNone) {
+    large_comp_hint_threshold_ = value;
+  }
+
   uint32_t config_index = 0;
   GetActiveDisplayConfig(&config_index);
   DisplayConfigVariableInfo attr = {};
@@ -1367,6 +1372,12 @@
     return false;
   }
 
+  if (large_comp_hint_threshold_ > 0 && layer_set_.size() >= large_comp_hint_threshold_) {
+    DLOGV_IF(kTagResources, "Number of app layers %d meet requirement %d. Set perf hint for large "
+             "comp cycle", layer_set_.size(), large_comp_hint_threshold_);
+    return true;
+  }
+
   // Send hints when the device is in multi-display or when a skip layer is present.
   if (layer_stack_.flags.skip_present || is_multi_display_) {
     DLOGV_IF(kTagResources, "Found skip_layer:%d or is_multidisplay:%d. Set perf hint for large "
diff --git a/composer/hwc_display_builtin.h b/composer/hwc_display_builtin.h
index 4a05a96..3547f0e 100644
--- a/composer/hwc_display_builtin.h
+++ b/composer/hwc_display_builtin.h
@@ -225,6 +225,7 @@
   // Long term large composition hint
   int hwc_tid_ = 0;
   uint32_t num_basic_frames_ = 0;
+  uint32_t large_comp_hint_threshold_ = 0;
 };
 
 }  // namespace sdm
diff --git a/composer/hwc_session.cpp b/composer/hwc_session.cpp
index 75144f7..870c1b5 100644
--- a/composer/hwc_session.cpp
+++ b/composer/hwc_session.cpp
@@ -1099,10 +1099,11 @@
   }
 
   // On SF stop, disable the idle time.
-  if (!pointer && is_idle_time_up_ && hwc_display_[HWC_DISPLAY_PRIMARY]) { // De-registering…
+  if (!pointer && is_client_up_ && hwc_display_[HWC_DISPLAY_PRIMARY]) { // De-registering…
     DLOGI("disable idle time");
     hwc_display_[HWC_DISPLAY_PRIMARY]->SetIdleTimeoutMs(0,0);
-    is_idle_time_up_ = false;
+    is_client_up_ = false;
+    hwc_display_[HWC_DISPLAY_PRIMARY]->MarkClientActive(false);
   }
 }
 
@@ -3719,23 +3720,69 @@
 
   Fence::Wait(retire_fence);
 
+  SCOPE_LOCK(pluggable_handler_lock_);
+  HWDisplaysInfo hw_displays_info = {};
+  DisplayError error = core_intf_->GetDisplaysStatus(&hw_displays_info);
+  if (error != kErrorNone) {
+    DLOGE("Failed to get connected display list. Error = %d", error);
+    return;
+  }
+
   for (hwc2_display_t display = HWC_DISPLAY_PRIMARY + 1;
     display < HWCCallbacks::kNumDisplays; display++) {
-    if (display != active_builtin_disp_id) {
-      Locker::ScopeLock lock_d(locker_[display]);
-      if (pending_power_mode_[display] && hwc_display_[display]) {
-        HWC2::Error error =
-          hwc_display_[display]->SetPowerMode(hwc_display_[display]->GetPendingPowerMode(), false);
-        if (HWC2::Error::None == error) {
-          pending_power_mode_[display] = false;
-          hwc_display_[display]->ClearPendingPowerMode();
-          pending_refresh_.set(UINT32(HWC_DISPLAY_PRIMARY));
-        } else {
-          DLOGE("SetDisplayStatus error = %d (%s)", error, to_string(error).c_str());
+    if (display == active_builtin_disp_id) {
+      continue;
+    }
+
+    Locker::ScopeLock lock_d(locker_[display]);
+    if (!pending_power_mode_[display] || !hwc_display_[display]) {
+      continue;
+    }
+
+    // check if a pluggable display which is in pending power state is already disconnected.
+    // In such cases, avoid powering up the display. It will be disconnected as part of
+    // HandlePendingHotplug.
+    bool disconnected = false;
+    hwc2_display_t client_id;
+    sdm::DisplayType disp_type;
+    for (auto &map_info : map_info_pluggable_) {
+      if (display != map_info.client_id) {
+        continue;
+      }
+
+      for (auto &iter : hw_displays_info) {
+        auto &info = iter.second;
+        if (info.display_id == map_info.sdm_id && !info.is_connected) {
+          disconnected = true;
+          break;
         }
       }
+      client_id = map_info.client_id;
+      disp_type = map_info.disp_type;
+      break;
+    }
+
+    if (disconnected) {
+      continue;
+    }
+
+    HWC2::PowerMode pending_mode = hwc_display_[display]->GetPendingPowerMode();
+
+    if (pending_mode == HWC2::PowerMode::Off || pending_mode == HWC2::PowerMode::DozeSuspend) {
+      map_active_displays_.erase(display);
+    } else {
+      map_active_displays_.insert(std::make_pair(client_id, disp_type));
+    }
+    HWC2::Error error = hwc_display_[display]->SetPowerMode(pending_mode, false);
+    if (HWC2::Error::None == error) {
+      pending_power_mode_[display] = false;
+      hwc_display_[display]->ClearPendingPowerMode();
+      pending_refresh_.set(UINT32(HWC_DISPLAY_PRIMARY));
+    } else {
+      DLOGE("SetDisplayStatus error = %d (%s)", error, to_string(error).c_str());
     }
   }
+
   secure_session_active_ = false;
 }
 
@@ -4225,6 +4272,7 @@
   int timeout_ms = -1;
   {
     SEQUENCE_WAIT_SCOPE_LOCK(locker_[display]);
+    DLOGI("Acquired lock for client %d display %" PRIu64, client_id, display);
     callbacks_.Refresh(display);
     clients_waiting_for_commit_[display].set(client_id);
     locker_[display].Wait();
@@ -4364,11 +4412,6 @@
     hwc_display_[target_display]->SetQSyncMode(kQSyncModeNone);
   }
 
-  int ret = WaitForCommitDoneAsync(target_display, kClientTrustedUI);
-  if (ret != 0) {
-    DLOGE("WaitForCommitDone failed with error = %d", ret);
-    return -EINVAL;
-  }
 
   int timeout_ms = -1;
   {
@@ -4414,16 +4457,11 @@
     tui_state_transition_[disp_id] = true;
   }
 
-  tui_start_success_ = true;
   return 0;
 }
 android::status_t HWCSession::TUITransitionEnd(int disp_id) {
   // Hold this lock so that any deferred hotplug events will not be handled during the commit
   // and will be handled at the end of TUITransitionPrepare.
-  if (!tui_start_success_) {
-    DLOGI("Bailing out TUI end");
-    return -EINVAL;
-  }
   SCOPE_LOCK(pluggable_handler_lock_);
   hwc2_display_t target_display = GetDisplayIndex(disp_id);
   bool needs_refresh = false;
@@ -4458,10 +4496,9 @@
 
   if (needs_refresh) {
     DLOGI("Waiting for device unassign");
-    int ret = WaitForCommitDoneAsync(target_display, kClientTrustedUI);
+    int ret = WaitForCommitDone(target_display, kClientTrustedUI);
     if (ret != 0) {
       DLOGE("Device unassign failed with error %d", ret);
-      tui_start_success_ = false;
       return -EINVAL;
     }
   }
@@ -4527,7 +4564,6 @@
     std::thread(&HWCSession::HandlePluggableDisplays, this, true).detach();
   }
   // Reset tui session state variable.
-  tui_start_success_ = false;
   DLOGI("End of TUI session on display %d", disp_id);
   return 0;
 }
diff --git a/composer/hwc_session.h b/composer/hwc_session.h
index 96bd91c..bfd72e8 100644
--- a/composer/hwc_session.h
+++ b/composer/hwc_session.h
@@ -723,13 +723,12 @@
   bool tui_state_transition_[HWCCallbacks::kNumDisplays] = {};
   std::bitset<HWCCallbacks::kNumDisplays> display_ready_;
   bool secure_session_active_ = false;
-  bool is_idle_time_up_ = false;
+  bool is_client_up_ = false;
   std::shared_ptr<IPCIntf> ipc_intf_ = nullptr;
   bool primary_pending_ = true;
   Locker primary_display_lock_;
   std::map <hwc2_display_t, sdm::DisplayType> map_active_displays_;
   vector<HWDisplayInfo> virtual_display_list_ = {};
-  bool tui_start_success_ = false;
   std::future<int> commit_done_future_;
 };
 }  // namespace sdm
diff --git a/composer/hwc_session_services.cpp b/composer/hwc_session_services.cpp
index 12ad1ad..9ce8cd9 100644
--- a/composer/hwc_session_services.cpp
+++ b/composer/hwc_session_services.cpp
@@ -1567,7 +1567,8 @@
   if (hwc_session_->hwc_display_[HWC_DISPLAY_PRIMARY]) {
     DLOGI("enable idle time active_ms:%d inactive_ms:%d",active_ms,inactive_ms);
     hwc_session_->hwc_display_[HWC_DISPLAY_PRIMARY]->SetIdleTimeoutMs(active_ms, inactive_ms);
-    hwc_session_->is_idle_time_up_ = true;
+    hwc_session_->is_client_up_ = true;
+    hwc_session_->hwc_display_[HWC_DISPLAY_PRIMARY]->MarkClientActive(true);
     hwc_session_->idle_time_inactive_ms_ = inactive_ms;
     hwc_session_->idle_time_active_ms_ = active_ms;
     return 0;
diff --git a/config/display-product.mk b/config/display-product.mk
index 9acab69..4eb47e9 100644
--- a/config/display-product.mk
+++ b/config/display-product.mk
@@ -84,7 +84,8 @@
     vendor.display.enable_rc_support=1 \
     vendor.display.disable_sdr_histogram=1 \
     vendor.display.enable_hdr10_gpu_target=1 \
-    debug.sf.predict_hwc_composition_strategy=0
+    debug.sf.predict_hwc_composition_strategy=0 \
+    debug.sf.treat_170m_as_sRGB=1
 
 # Enable offline rotator for Bengal.
 ifneq ($(TARGET_BOARD_PLATFORM),bengal)
diff --git a/include/display_properties.h b/include/display_properties.h
index c9e9366..80197b2 100644
--- a/include/display_properties.h
+++ b/include/display_properties.h
@@ -162,6 +162,7 @@
 
 // PERF hint properties
 #define ENABLE_PERF_HINT_LARGE_COMP_CYCLE    DISPLAY_PROP("enable_perf_hint_large_comp_cycle")
+#define LARGE_COMP_HINT_THRESHOLD            DISPLAY_PROP("large_comp_hint_threshold")
 #define DISABLE_DYNAMIC_FPS                  DISPLAY_PROP("disable_dynamic_fps")
 #define ENABLE_QSYNC_IDLE                    DISPLAY_PROP("enable_qsync_idle")
 #define ENHANCE_IDLE_TIME                    DISPLAY_PROP("enhance_idle_time")
diff --git a/libdrmutils/drm_interface.h b/libdrmutils/drm_interface.h
index 81f921d..a987365 100644
--- a/libdrmutils/drm_interface.h
+++ b/libdrmutils/drm_interface.h
@@ -1068,6 +1068,7 @@
   kCscYuv2Rgb2020L,
   kCscYuv2Rgb2020FR,
   kCscYuv2RgbDolbyVisionP5,
+  kCscYuv2RgbDCIP3FR,
   kCscTypeMax,
 };
 
diff --git a/sde-drm/drm_crtc.cpp b/sde-drm/drm_crtc.cpp
old mode 100644
new mode 100755
index ab66b7f..57eeeb9
--- a/sde-drm/drm_crtc.cpp
+++ b/sde-drm/drm_crtc.cpp
@@ -168,6 +168,7 @@
 #define __CLASS__ "DRMCrtcManager"
 
 void DRMCrtcManager::Init(drmModeRes *resource) {
+  lock_guard<mutex> lock(lock_);
   for (int i = 0; i < resource->count_crtcs; i++) {
     unique_ptr<DRMCrtc> crtc(new DRMCrtc(fd_, i));
     drmModeCrtc *libdrm_crtc = drmModeGetCrtc(fd_, resource->crtcs[i]);
@@ -181,10 +182,12 @@
 }
 
 void DRMCrtcManager::DumpByID(uint32_t id) {
+  lock_guard<mutex> lock(lock_);
   crtc_pool_.at(id)->Dump();
 }
 
 void DRMCrtcManager::DumpAll() {
+  lock_guard<mutex> lock(lock_);
   for (auto &crtc : crtc_pool_) {
     crtc.second->Dump();
   }
@@ -210,6 +213,7 @@
 }
 
 void DRMCrtcManager::SetScalerLUT(const DRMScalerLUTInfo &lut_info) {
+  lock_guard<mutex> lock(lock_);
   // qseed3lite lut is hardcoded in HW. No need to program from sw.
   DRMCrtcInfo info;
   crtc_pool_.begin()->second->GetInfo(&info);
@@ -232,6 +236,7 @@
 }
 
 void DRMCrtcManager::UnsetScalerLUT() {
+  lock_guard<mutex> lock(lock_);
   if (dir_lut_blob_id_) {
     drmModeDestroyPropertyBlob(fd_, dir_lut_blob_id_);
     dir_lut_blob_id_ = 0;
@@ -247,6 +252,7 @@
 }
 
 int DRMCrtcManager::GetCrtcInfo(uint32_t crtc_id, DRMCrtcInfo *info) {
+  lock_guard<mutex> lock(lock_);
   if (crtc_id == 0) {
     crtc_pool_.begin()->second->GetInfo(info);
   } else {
@@ -263,6 +269,7 @@
 }
 
 void DRMCrtcManager::GetPPInfo(uint32_t crtc_id, DRMPPFeatureInfo *info) {
+  lock_guard<mutex> lock(lock_);
   auto it = crtc_pool_.find(crtc_id);
   if (it == crtc_pool_.end()) {
     DRM_LOGE("Invalid crtc id %d", crtc_id);
@@ -274,6 +281,7 @@
 
 int DRMCrtcManager::Reserve(const std::set<uint32_t> &possible_crtc_indices,
                              DRMDisplayToken *token) {
+  lock_guard<mutex> lock(lock_);
   for (auto &item : crtc_pool_) {
     if (item.second->GetStatus() == DRMStatus::FREE) {
       if (possible_crtc_indices.find(item.second->GetIndex()) != possible_crtc_indices.end()) {
diff --git a/sde-drm/drm_plane.cpp b/sde-drm/drm_plane.cpp
index 8d5c0a5..a41f096 100644
--- a/sde-drm/drm_plane.cpp
+++ b/sde-drm/drm_plane.cpp
@@ -179,7 +179,18 @@
     { 0x0, 0x0, 0x0,},
     { 0x0, 0x3ff, 0x0, 0x3ff, 0x0, 0x3ff,},
     { 0x0, 0x3ff, 0x0, 0x3ff, 0x0, 0x3ff,},
-  }
+  },
+  [kCscYuv2RgbDCIP3FR] = {
+    {
+      0x100000000, 0x0, 0x194800000,
+      0x100000000, 0x7fd2800000, 0x7f8a800000,
+      0x100000000, 0x1dc800000, 0x0,
+    },
+    { 0x0, 0xfe00, 0xfe00,},
+    { 0x0, 0x0, 0x0, },
+    { 0x0, 0x3ff, 0x0, 0x3ff, 0x0, 0x3ff,},
+    { 0x0, 0x3ff, 0x0, 0x3ff, 0x0, 0x3ff,},
+  },
 };
 
 static struct drm_msm_fp16_csc csc_fp16_convert[kFP16CscTypeMax] = {
diff --git a/sdm/include/core/buffer_allocator.h b/sdm/include/core/buffer_allocator.h
index 63b9f8c..fb05db8 100644
--- a/sdm/include/core/buffer_allocator.h
+++ b/sdm/include/core/buffer_allocator.h
@@ -81,6 +81,17 @@
   bool trusted_ui = false;                    //!< Specifies buffer to be allocated from non-secure
                                               //!< contiguous memory.
   BufferAccessControlMap access_control;      //!< Specifies the access permission for this buffer
+
+  bool operator!=(const BufferConfig& config) const {
+    return width != config.width   ||
+           height != config.height ||
+           format != config.format ||
+           secure != config.secure ||
+           cache != config.cache   ||
+           secure_camera != config.secure_camera ||
+           gfx_client != config.gfx_client ||
+           trusted_ui != config.trusted_ui;
+  }
 };
 
 /*! @brief Holds the information about the allocated buffer.
diff --git a/sdm/include/private/extension_interface.h b/sdm/include/private/extension_interface.h
index be13a7c..e7511cc 100644
--- a/sdm/include/private/extension_interface.h
+++ b/sdm/include/private/extension_interface.h
@@ -69,6 +69,7 @@
                                           const HWResourceInfo &hw_resource_info,
                                           const HWPanelInfo &hw_panel_info,
                                           const HWMixerAttributes &mixer_attributes,
+                                          const HWDisplayAttributes &display_attributes,
                                           const DisplayConfigVariableInfo &fb_config,
                                           StrategyInterface **interface) = 0;
   virtual DisplayError DestroyStrategyExtn(StrategyInterface *interface) = 0;
diff --git a/sdm/include/private/hw_events_interface.h b/sdm/include/private/hw_events_interface.h
index 6901938..98cc145 100644
--- a/sdm/include/private/hw_events_interface.h
+++ b/sdm/include/private/hw_events_interface.h
@@ -22,6 +22,42 @@
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
+/*
+* Changes from Qualcomm Innovation Center are provided under the following license:
+*
+* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted (subject to the limitations in the
+* disclaimer below) provided that the following conditions are met:
+*
+*    * Redistributions of source code must retain the above copyright
+*      notice, this list of conditions and the following disclaimer.
+*
+*    * Redistributions in binary form must reproduce the above
+*      copyright notice, this list of conditions and the following
+*      disclaimer in the documentation and/or other materials provided
+*      with the distribution.
+*
+*    * Neither the name of Qualcomm Innovation Center, Inc. nor the names of its
+*      contributors may be used to endorse or promote products derived
+*      from this software without specific prior written permission.
+*
+* NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE
+* GRANTED BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT
+* HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+* IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
 #ifndef __HW_EVENTS_INTERFACE_H__
 #define __HW_EVENTS_INTERFACE_H__
 
@@ -50,6 +86,7 @@
   MMRM,
   POWER_EVENT,
   VM_RELEASE_EVENT,
+  HW_EVENT_MAX,
 };
 
 class HWEventsInterface {
diff --git a/sdm/include/private/hw_interface.h b/sdm/include/private/hw_interface.h
index 83952e3..c4583c5 100644
--- a/sdm/include/private/hw_interface.h
+++ b/sdm/include/private/hw_interface.h
@@ -184,6 +184,7 @@
   virtual DisplayError GetQsyncFps(uint32_t *qsync_fps) = 0;
   virtual DisplayError UpdateTransferTime(uint32_t transfer_time) = 0;
   virtual DisplayError CancelDeferredPowerMode() = 0;
+  virtual void HandleCwbTeardown() = 0;
 
  protected:
   virtual ~HWInterface() { }
diff --git a/sdm/include/private/resource_interface.h b/sdm/include/private/resource_interface.h
index 95e0969..630b140 100644
--- a/sdm/include/private/resource_interface.h
+++ b/sdm/include/private/resource_interface.h
@@ -141,7 +141,7 @@
   virtual void HandleSkipValidate(Handle display_ctx) = 0;
   virtual std::string Dump() = 0;
   virtual uint32_t GetMixerCount() = 0;
-  virtual void HandleTUITransition(bool tui_active) = 0;
+  virtual void HandleTUITransition(Handle display_ctx, bool tui_active) = 0;
 };
 
 }  // namespace sdm
diff --git a/sdm/include/private/strategy_interface.h b/sdm/include/private/strategy_interface.h
index f2025af..3593f25 100644
--- a/sdm/include/private/strategy_interface.h
+++ b/sdm/include/private/strategy_interface.h
@@ -58,6 +58,7 @@
   virtual DisplayError SetDrawMethod(const DisplayDrawMethod &draw_method) = 0;
   virtual DisplayError Reconfigure(const HWPanelInfo &hw_panel_info,
                                    const HWResourceInfo &hw_res_info,
+                                   const HWDisplayAttributes &display_attributes,
                                    const HWMixerAttributes &mixer_attributes,
                                    const DisplayConfigVariableInfo &fb_config) = 0;
   virtual DisplayError SetCompositionState(LayerComposition composition_type, bool enable) = 0;
diff --git a/sdm/libs/core/comp_manager.cpp b/sdm/libs/core/comp_manager.cpp
index da69d9a..be7639c 100755
--- a/sdm/libs/core/comp_manager.cpp
+++ b/sdm/libs/core/comp_manager.cpp
@@ -777,12 +777,12 @@
                             display_comp_ctx->display_resource_ctx);
   }
   if (secure_event == kTUITransitionStart) {
-    resource_intf_->HandleTUITransition(true);
+    resource_intf_->HandleTUITransition(display_comp_ctx->display_resource_ctx, true);
   }
   if (secure_event == kTUITransitionEnd) {
     resource_intf_->Perform(ResourceInterface::kCmdResetLUT,
                             display_comp_ctx->display_resource_ctx);
-    resource_intf_->HandleTUITransition(false);
+    resource_intf_->HandleTUITransition(display_comp_ctx->display_resource_ctx, false);
     safe_mode_ = false;
   }
   safe_mode_ = (secure_event == kTUITransitionStart) ? true : safe_mode_;
diff --git a/sdm/libs/core/display_base.cpp b/sdm/libs/core/display_base.cpp
index 0d182fe..f14d2cb 100644
--- a/sdm/libs/core/display_base.cpp
+++ b/sdm/libs/core/display_base.cpp
@@ -1796,6 +1796,7 @@
   if (state == state_) {
     if (pending_power_state_ != kPowerStateNone) {
       hw_intf_->CancelDeferredPowerMode();
+      pending_power_state_ = kPowerStateNone;
     }
     DLOGI("Same state transition is requested.");
     return kErrorNone;
@@ -1835,6 +1836,8 @@
       hw_events_intf_->SetEventState(HWEvent::POWER_EVENT, true);
     }
 
+    cached_qos_data_.clock_hz =
+      std::max(cached_qos_data_.clock_hz, disp_layer_stack_.info.qos_data.clock_hz);
     error = hw_intf_->PowerOn(cached_qos_data_, &sync_points);
     if (error != kErrorNone) {
       if (error == kErrorDeferred) {
@@ -1956,12 +1959,6 @@
     return kErrorNone;
   }
 
-  // Reject active config changes if qsync is in use.
-  if (needs_avr_update_ || qsync_mode_ != kQSyncModeNone) {
-    DLOGE("Failed: needs_avr_update_: %d, qsync_mode_: %d", needs_avr_update_, qsync_mode_);
-    return kErrorNotSupported;
-  }
-
   error = hw_intf_->SetDisplayAttributes(index);
   if (error != kErrorNone) {
     return error;
@@ -3804,12 +3801,12 @@
     SetPendingPowerState(state);
   }
 
+  comp_manager_->HandleSecureEvent(display_comp_ctx_, secure_event);
   err = hw_intf_->HandleSecureEvent(secure_event, cached_qos_data_);
   if (err != kErrorNone) {
     return err;
   }
 
-  comp_manager_->HandleSecureEvent(display_comp_ctx_, secure_event);
   secure_event_ = secure_event;
   if (secure_event == kTUITransitionEnd) {
     DisplayState pending_state;
@@ -4351,6 +4348,8 @@
     return false;
   }
 
+  hw_intf_->HandleCwbTeardown();
+
   return comp_manager_->HandleCwbTeardown(display_comp_ctx_);
 }
 
diff --git a/sdm/libs/core/display_builtin.cpp b/sdm/libs/core/display_builtin.cpp
index 57e0c15..2a4bc76 100644
--- a/sdm/libs/core/display_builtin.cpp
+++ b/sdm/libs/core/display_builtin.cpp
@@ -169,18 +169,19 @@
       return error;
     }
 
-    if ((error = SetupDemura()) != kErrorNone) {
+    DisplayError tmp = kErrorNone;
+    if ((tmp = SetupDemura()) != kErrorNone) {
       // Non-fatal but not expected, log error
       DLOGE("Demura failed to initialize on display %d-%d, Error = %d", display_id_,
-            display_type_, error);
+            display_type_, tmp);
       comp_manager_->FreeDemuraFetchResources(display_id_);
       comp_manager_->SetDemuraStatusForDisplay(display_id_, false);
       if (demura_) {
         SetDemuraIntfStatus(false);
       }
     } else if (demuratn_factory_) {
-      if ((error = SetupDemuraTn()) != kErrorNone) {
-        DLOGW("Failed to setup DemuraTn, Error = %d", error);
+      if ((tmp = SetupDemuraTn()) != kErrorNone) {
+        DLOGW("Failed to setup DemuraTn, Error = %d", tmp);
       }
     }
   } else {
@@ -1903,7 +1904,7 @@
   }
 
   // force clear qsync mode if set by idle timeout.
-  if (qsync_mode_ !=  kQSyncModeNone && qsync_mode_ == qsync_mode) {
+  if (qsync_mode_ ==  active_qsync_mode_ && qsync_mode_ == qsync_mode) {
     DLOGW("Qsync mode already set as requested mode: qsync_mode_=%d", qsync_mode_);
     return kErrorNone;
   }
@@ -2556,6 +2557,25 @@
 
 
 // LCOV_EXCL_START
+DisplayError DisplayBuiltIn::HandleSecureEvent(SecureEvent secure_event, bool *needs_refresh) {
+  DisplayError error = kErrorNone;
+
+  error = DisplayBase::HandleSecureEvent(secure_event, needs_refresh);
+  if (error) {
+    DLOGE("Failed to handle secure event %d", secure_event);
+    return error;
+  }
+
+  if (secure_event == kTUITransitionEnd) {
+    // enable demura after TUI transition end
+    if (demura_) {
+      SetDemuraIntfStatus(true);
+    }
+  }
+
+  return error;
+}
+
 DisplayError DisplayBuiltIn::PostHandleSecureEvent(SecureEvent secure_event) {
   ClientLock lock(disp_mutex_);
   if (secure_event == kTUITransitionStart) {
@@ -2572,6 +2592,13 @@
       // Send display config information to secondary VM on TUI session start
       SendDisplayConfigs();
     }
+
+    if (secure_event == kTUITransitionStart) {
+      //  disable demura before TUI transition start
+      if (demura_) {
+        SetDemuraIntfStatus(false);
+      }
+    }
   }
   if (secure_event == kTUITransitionEnd) {
     if (vm_cb_intf_) {
diff --git a/sdm/libs/core/display_builtin.h b/sdm/libs/core/display_builtin.h
index 7e1d5b2..9ca3395 100644
--- a/sdm/libs/core/display_builtin.h
+++ b/sdm/libs/core/display_builtin.h
@@ -180,6 +180,7 @@
   DisplayError GetConfig(DisplayConfigFixedInfo *fixed_info) override;
   DisplayError PrePrepare(LayerStack *layer_stack) override;
   DisplayError SetAlternateDisplayConfig(uint32_t *alt_config) override;
+  DisplayError HandleSecureEvent(SecureEvent secure_event, bool *needs_refresh) override;
   DisplayError PostHandleSecureEvent(SecureEvent secure_event) override;
   void InitCWBBuffer();
   void DeinitCWBBuffer();
diff --git a/sdm/libs/core/display_virtual.cpp b/sdm/libs/core/display_virtual.cpp
index 433537a..4316f8b 100644
--- a/sdm/libs/core/display_virtual.cpp
+++ b/sdm/libs/core/display_virtual.cpp
@@ -120,6 +120,9 @@
     return error;
   }
 
+  uint32_t active_index = 0;
+  hw_intf_->GetActiveConfig(&active_index);
+  hw_intf_->GetDisplayAttributes(active_index, &display_attributes);
   hw_intf_->GetHWPanelInfo(&hw_panel_info);
 
   if (set_max_lum_ != -1.0 || set_min_lum_ != -1.0) {
diff --git a/sdm/libs/core/resource_default.cpp b/sdm/libs/core/resource_default.cpp
index f76ab6f..5aaed31 100644
--- a/sdm/libs/core/resource_default.cpp
+++ b/sdm/libs/core/resource_default.cpp
@@ -392,7 +392,7 @@
   return 0;
 }
 
-void ResourceDefault::HandleTUITransition(bool tui_active) {
+void ResourceDefault::HandleTUITransition(Handle display_ctx, bool tui_active) {
 }
 
 DisplayError ResourceDefault::PostCommit(Handle display_ctx, DispLayerStack *disp_layer_stack) {
diff --git a/sdm/libs/core/resource_default.h b/sdm/libs/core/resource_default.h
index e2dc222..b246ecc 100644
--- a/sdm/libs/core/resource_default.h
+++ b/sdm/libs/core/resource_default.h
@@ -141,7 +141,7 @@
   virtual void HandleSkipValidate(Handle display_ctx);
   virtual std::string Dump();
   virtual uint32_t GetMixerCount();
-  virtual void HandleTUITransition(bool tui_active);
+  virtual void HandleTUITransition(Handle display_ctx, bool tui_active);
 
  private:
   enum PipeOwner {
diff --git a/sdm/libs/core/strategy.cpp b/sdm/libs/core/strategy.cpp
index cb4550c..eac6652 100644
--- a/sdm/libs/core/strategy.cpp
+++ b/sdm/libs/core/strategy.cpp
@@ -20,6 +20,10 @@
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+* Changes from Qualcomm Innovation Center are provided under the following license:
+* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+* SPDX-License-Identifier: BSD-3-Clause-Clear
 */
 
 #include <utils/constants.h>
@@ -55,7 +59,8 @@
   if (extension_intf_) {
     error = extension_intf_->CreateStrategyExtn(display_id_, display_type_, buffer_allocator_,
                                                 hw_resource_info_, hw_panel_info_,
-                                                mixer_attributes_, fb_config_, &strategy_intf_);
+                                                mixer_attributes_, display_attributes_, fb_config_,
+                                                &strategy_intf_);
     if (error != kErrorNone) {
       DLOGE("Failed to create strategy for display %d-%d", display_id_, display_type_);
       return error;
@@ -219,8 +224,8 @@
                                        mixer_attributes, display_attributes, fb_config,
                                        &partial_update_intf_);
 
-  error = strategy_intf_->Reconfigure(hw_panel_info, hw_resource_info_, mixer_attributes,
-                                      fb_config);
+  error = strategy_intf_->Reconfigure(hw_panel_info, hw_resource_info_, display_attributes,
+                                      mixer_attributes, fb_config);
   if (error != kErrorNone) {
     return error;
   }
diff --git a/sdm/libs/dal/hw_device_drm.cpp b/sdm/libs/dal/hw_device_drm.cpp
index 7c704e1..c70ff12 100644
--- a/sdm/libs/dal/hw_device_drm.cpp
+++ b/sdm/libs/dal/hw_device_drm.cpp
@@ -1166,8 +1166,9 @@
 DisplayError HWDeviceDRM::PowerOn(const HWQosData &qos_data, SyncPoints *sync_points) {
   SetQOSData(qos_data);
 
-  if (tui_state_ != kTUIStateNone) {
-    DLOGI("Request deferred TUI state %d", tui_state_);
+  if (tui_state_ != kTUIStateNone || pending_cwb_teardown_) {
+    DLOGI("Request deferred TUI state %d pending cwb teardown %d", tui_state_,
+          pending_cwb_teardown_);
     pending_power_state_ = kPowerStateOn;
     return kErrorDeferred;
   }
@@ -1207,8 +1208,9 @@
     return kErrorNone;
   }
 
-  if (tui_state_ != kTUIStateNone && tui_state_ != kTUIStateEnd) {
-    DLOGI("Request deferred TUI state %d", tui_state_);
+  if ((tui_state_ != kTUIStateNone && tui_state_ != kTUIStateEnd) || pending_cwb_teardown_) {
+    DLOGI("Request deferred TUI state %d pending cwb teardown %d", tui_state_,
+          pending_cwb_teardown_);
     pending_power_state_ = kPowerStateOff;
     return kErrorDeferred;
   }
@@ -1941,6 +1943,7 @@
   update_mode_ = false;
   hw_layers_info->updates_mask = 0;
   pending_power_state_ = kPowerStateNone;
+  pending_cwb_teardown_ = false;
   // Inherently a real commit ensures null commit properties have happened, so update the member
   first_null_cycle_ = false;
   seamless_mode_switch_ = false;
@@ -1967,6 +1970,9 @@
   sync_commit = true;
 #endif
 
+  // dpps commit feature ops doesn't use the obj id, set it as -1
+  drm_atomic_intf_->Perform(DRMOps::DPPS_COMMIT_FEATURE, -1);
+
   int ret = NullCommit(sync_commit /* synchronous */, false /* retain_planes*/);
   if (ret) {
     DLOGE("failed with error %d", ret);
@@ -2037,6 +2043,10 @@
       *type = ((input_buffer.color_metadata.range == Range_Full) ?
                 DRMCscType::kCscYuv2Rgb2020FR : DRMCscType::kCscYuv2Rgb2020L);
       break;
+    case ColorPrimaries_DCIP3:
+      *type = ((input_buffer.color_metadata.range == Range_Full) ?
+                DRMCscType::kCscYuv2RgbDCIP3FR : DRMCscType::kCscTypeMax);
+      break;
     default:
       break;
   }
@@ -3217,4 +3227,9 @@
   return kErrorNone;
 }
 
+void HWDeviceDRM::HandleCwbTeardown() {
+  DLOGI("Pending CWB teardown on CRTC: %u", token_.crtc_id);
+  pending_cwb_teardown_ = true;
+}
+
 }  // namespace sdm
diff --git a/sdm/libs/dal/hw_device_drm.h b/sdm/libs/dal/hw_device_drm.h
index 29a7192..144debf 100644
--- a/sdm/libs/dal/hw_device_drm.h
+++ b/sdm/libs/dal/hw_device_drm.h
@@ -208,6 +208,7 @@
     return kErrorNotSupported;
   }
   virtual DisplayError CancelDeferredPowerMode();
+  virtual void HandleCwbTeardown();
 
   enum {
     kHWEventVSync,
@@ -349,6 +350,7 @@
   bool doze_poms_switch_done_ = false;
   bool pending_poms_switch_ = false;
   bool active_ = false;
+  bool pending_cwb_teardown_ = false;
   PrimariesTransfer blend_space_ = {};
   DRMPowerMode last_power_mode_ = DRMPowerMode::OFF;
   uint32_t dest_scaler_blocks_used_ = 0;  // Dest scaler blocks in use by this HWDeviceDRM instance.
diff --git a/sdm/libs/dal/hw_events_drm.cpp b/sdm/libs/dal/hw_events_drm.cpp
index 1cb091d..765ff13 100644
--- a/sdm/libs/dal/hw_events_drm.cpp
+++ b/sdm/libs/dal/hw_events_drm.cpp
@@ -27,6 +27,42 @@
 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
+/*
+* Changes from Qualcomm Innovation Center are provided under the following license:
+*
+* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted (subject to the limitations in the
+* disclaimer below) provided that the following conditions are met:
+*
+*    * Redistributions of source code must retain the above copyright
+*      notice, this list of conditions and the following disclaimer.
+*
+*    * Redistributions in binary form must reproduce the above
+*      copyright notice, this list of conditions and the following
+*      disclaimer in the documentation and/or other materials provided
+*      with the distribution.
+*
+*    * Neither the name of Qualcomm Innovation Center, Inc. nor the names of its
+*      contributors may be used to endorse or promote products derived
+*      from this software without specific prior written permission.
+*
+* NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE
+* GRANTED BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT
+* HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+* IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
 #include <drm_master.h>
 #include <errno.h>
 #include <fcntl.h>
@@ -184,10 +220,7 @@
         poll_fds_[i].events = POLLIN | POLLPRI | POLLERR;
         vm_release_event_index_ = i;
       } break;
-      case HWEvent::CEC_READ_MESSAGE:
-      case HWEvent::SHOW_BLANK_EVENT:
-      case HWEvent::THERMAL_LEVEL:
-      case HWEvent::PINGPONG_TIMEOUT:
+      default:
         break;
     }
   }
@@ -326,21 +359,30 @@
 }
 
 DisplayError HWEventsDRM::SetEventState(HWEvent event, bool enable, void *arg) {
+  if (event != HWEvent::VSYNC) {
+    if (enable == registered_hw_events_.test(event)) {
+      DLOGW("%s of %sregistered hw event %d occurred!!",
+            enable ? "Registration" : "Deregistration",
+            enable ? "already " : "un-", event);
+      return kErrorNone;
+    }
+  }
   DisplayError error = kErrorNone;
   switch (event) {
     case HWEvent::VSYNC: {
       std::lock_guard<std::mutex> lock(vsync_mutex_);
       vsync_enabled_ = enable;
-      if (vsync_enabled_ && !vsync_registered_) {
+      if (vsync_enabled_ && !registered_hw_events_.test(HWEvent::VSYNC)) {
         error = RegisterVSync();
         if (error != kErrorNone) {
           return error;
         }
-        vsync_registered_ = true;
+        registered_hw_events_.set(event);
       } else if (!vsync_enabled_) {
-        vsync_registered_ = false;
+        registered_hw_events_.reset(event);
       }
-    } break;
+      return kErrorNone;
+    }
     case HWEvent::BACKLIGHT_EVENT: {
       std::lock_guard<std::mutex> lock(backlight_mutex_);
       if (backlight_event_index_ == UINT32_MAX) {
@@ -391,6 +433,7 @@
       DLOGE("Event not supported");
       return kErrorNotSupported;
   }
+  registered_hw_events_.set(event, enable);
 
   return kErrorNone;
 }
@@ -529,6 +572,8 @@
             (this->*(event_data_list_[i]).event_parser)(data);
           }
           break;
+        default:
+          break;
       }
     }
   }
@@ -749,10 +794,11 @@
   vsync_handler_count_ = 0;  //  reset vsync handler count. lock not needed
   {
     std::lock_guard<std::mutex> lock(vsync_mutex_);
-    vsync_registered_ = false;
+    registered_hw_events_.reset(HWEvent::VSYNC);
     if (vsync_enabled_) {
       ret = RegisterVSync();
-      vsync_registered_ = (ret == kErrorNone);
+      if (ret == kErrorNone)
+        registered_hw_events_.set(HWEvent::VSYNC);
     }
   }
 
@@ -767,10 +813,11 @@
   if (vsync_handler_count_ > 1) {
     //  probable thread preemption caused > 1 vsync handling. Re-enable vsync before polling
     std::lock_guard<std::mutex> lock(vsync_mutex_);
-    vsync_registered_ = false;
+    registered_hw_events_.reset(HWEvent::VSYNC);
     if (vsync_enabled_) {
       ret = RegisterVSync();
-      vsync_registered_ = (ret == kErrorNone);
+      if (ret == kErrorNone)
+        registered_hw_events_.set(HWEvent::VSYNC);
     }
   }
 }
diff --git a/sdm/libs/dal/hw_events_drm.h b/sdm/libs/dal/hw_events_drm.h
index 8daf6eb..bf370ac 100644
--- a/sdm/libs/dal/hw_events_drm.h
+++ b/sdm/libs/dal/hw_events_drm.h
@@ -27,6 +27,42 @@
 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
+/*
+* Changes from Qualcomm Innovation Center are provided under the following license:
+*
+* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted (subject to the limitations in the
+* disclaimer below) provided that the following conditions are met:
+*
+*    * Redistributions of source code must retain the above copyright
+*      notice, this list of conditions and the following disclaimer.
+*
+*    * Redistributions in binary form must reproduce the above
+*      copyright notice, this list of conditions and the following
+*      disclaimer in the documentation and/or other materials provided
+*      with the distribution.
+*
+*    * Neither the name of Qualcomm Innovation Center, Inc. nor the names of its
+*      contributors may be used to endorse or promote products derived
+*      from this software without specific prior written permission.
+*
+* NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE
+* GRANTED BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT
+* HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+* IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
 #ifndef __HW_EVENTS_DRM_H__
 #define __HW_EVENTS_DRM_H__
 
@@ -41,6 +77,7 @@
 #include <utility>
 #include <vector>
 #include <climits>
+#include <bitset>
 
 #include "hw_device_drm.h"
 
@@ -108,9 +145,8 @@
   uint32_t vsync_index_ = UINT32_MAX;
   uint32_t histogram_index_ = UINT32_MAX;
   bool vsync_enabled_ = false;
-  bool vsync_registered_ = false;
   uint32_t vsync_handler_count_ = 0;
-  std::mutex vsync_mutex_;  // To protect vsync_enabled_ and vsync_registered_
+  std::mutex vsync_mutex_;  // To protect vsync_enabled_
   sde_drm::DRMDisplayToken token_ = {};
   bool is_primary_ = false;
   uint32_t panel_dead_index_ = UINT32_MAX;
@@ -126,6 +162,7 @@
   uint32_t mmrm_index_ = UINT32_MAX;
   uint32_t power_event_index_ = UINT32_MAX;
   uint32_t vm_release_event_index_ = UINT32_MAX;
+  std::bitset<HW_EVENT_MAX> registered_hw_events_ = {};
 };
 
 }  // namespace sdm
diff --git a/sdm/libs/dal/hw_tv_drm.cpp b/sdm/libs/dal/hw_tv_drm.cpp
index ccafa85..7cc72da 100644
--- a/sdm/libs/dal/hw_tv_drm.cpp
+++ b/sdm/libs/dal/hw_tv_drm.cpp
@@ -257,6 +257,12 @@
     // LP connecter prop N/A for External
     drm_atomic_intf_->Perform(DRMOps::CRTC_SET_ACTIVE, token_.crtc_id, 0);
   }
+
+  if (cwb_config_.cwb_disp_id == display_id_ && cwb_config_.enabled) {
+    drm_atomic_intf_->Perform(DRMOps::CONNECTOR_SET_CRTC, cwb_config_.token.conn_id, 0);
+    DLOGI("Teardown CWB on %d-%d", display_id_, disp_type_);
+  }
+
   ClearSolidfillStages();
   int ret = drm_atomic_intf_->Commit(true /* synchronous */, false /* retain_planes*/);
   if (ret) {
diff --git a/sdm/libs/dal/hw_virtual_drm.cpp b/sdm/libs/dal/hw_virtual_drm.cpp
index f6f3de5..37d323f 100644
--- a/sdm/libs/dal/hw_virtual_drm.cpp
+++ b/sdm/libs/dal/hw_virtual_drm.cpp
@@ -70,6 +70,7 @@
 #include <utils/utils.h>
 #include <algorithm>
 #include <vector>
+#include <cmath>
 #include "hw_device_drm.h"
 #include "hw_virtual_drm.h"
 #include "hw_info_drm.h"
@@ -139,7 +140,8 @@
   mode.vdisplay = mode.vsync_start = mode.vsync_end = mode.vtotal =
                                        UINT16(display_attributes.y_pixels);
   mode.vrefresh = UINT32(display_attributes.fps);
-  mode.clock = (mode.htotal * mode.vtotal * mode.vrefresh) / 1000;
+
+  mode.clock = std::round(FLOAT(mode.htotal * mode.vtotal * mode.vrefresh) / 1000.00f);
   snprintf(mode.name, DRM_DISPLAY_MODE_LEN, "%dx%d", mode.hdisplay, mode.vdisplay);
   modes.push_back(mode);
   for (auto &item : connector_info_.modes) {