sdm: Add support for TUI transition prepare, start and stop

1. Pause all other displays except the display for which TUI
   transition prepare has been requested
2. Vote for full frame bandwidth/clock and pause the primary or
   built in display on which TUI transition start is requested
3. Reset CRTC and plane property cache on TUI transition end request

Change-Id: I248074a13ca6481dcb857377256fba2b6c683a4f
diff --git a/composer/display_null.h b/composer/display_null.h
index c1fd69b..8656114 100644
--- a/composer/display_null.h
+++ b/composer/display_null.h
@@ -108,7 +108,7 @@
   MAKE_NO_OP(SetCompositionState(LayerComposition, bool))
   MAKE_NO_OP(GetClientTargetSupport(uint32_t, uint32_t, LayerBufferFormat,
                                     const ColorMetaData &))
-  MAKE_NO_OP(HandleSecureEvent(SecureEvent, LayerStack *))
+  MAKE_NO_OP(HandleSecureEvent(SecureEvent))
   MAKE_NO_OP(SetQSyncMode(QSyncMode))
   MAKE_NO_OP(ControlIdlePowerCollapse(bool, bool))
   MAKE_NO_OP(SetDisplayDppsAdROI(void *))
diff --git a/composer/hwc_display.cpp b/composer/hwc_display.cpp
index 076596d..713c5f6 100644
--- a/composer/hwc_display.cpp
+++ b/composer/hwc_display.cpp
@@ -1988,6 +1988,9 @@
       display_paused_ = false;
       status = INT32(SetPowerMode(HWC2::PowerMode::On, false /* teardown */));
       break;
+    case kDisplayStatusResumeOnly:
+      display_paused_ = false;
+      break;
     case kDisplayStatusOnline:
       status = INT32(SetPowerMode(HWC2::PowerMode::On, false /* teardown */));
       break;
@@ -1995,6 +1998,9 @@
       display_paused_ = true;
       status = INT32(SetPowerMode(HWC2::PowerMode::Off, false /* teardown */));
       break;
+    case kDisplayStatusPauseOnly:
+      display_paused_ = true;
+      break;
     case kDisplayStatusOffline:
       status = INT32(SetPowerMode(HWC2::PowerMode::Off, false /* teardown */));
       break;
diff --git a/composer/hwc_display.h b/composer/hwc_display.h
index 6a65f6e..fe8c578 100644
--- a/composer/hwc_display.h
+++ b/composer/hwc_display.h
@@ -152,8 +152,10 @@
     kDisplayStatusInvalid = -1,
     kDisplayStatusOffline,
     kDisplayStatusOnline,
-    kDisplayStatusPause,
-    kDisplayStatusResume,
+    kDisplayStatusPause,       // Pause + PowerOff
+    kDisplayStatusResume,      // Resume + PowerOn
+    kDisplayStatusPauseOnly,
+    kDisplayStatusResumeOnly,
   };
 
   enum DisplayValidateState {
@@ -191,6 +193,7 @@
   virtual int Perform(uint32_t operation, ...);
   virtual int HandleSecureSession(const std::bitset<kSecureMax> &secure_sessions,
                                   bool *power_on_pending);
+  virtual DisplayError HandleSecureEvent(SecureEvent secure_event) { return kErrorNotSupported; }
   virtual int GetActiveSecureSession(std::bitset<kSecureMax> *secure_sessions);
   virtual DisplayError SetMixerResolution(uint32_t width, uint32_t height);
   virtual DisplayError GetMixerResolution(uint32_t *width, uint32_t *height);
diff --git a/composer/hwc_display_builtin.cpp b/composer/hwc_display_builtin.cpp
index 66f145f..a7d20b2 100644
--- a/composer/hwc_display_builtin.cpp
+++ b/composer/hwc_display_builtin.cpp
@@ -358,14 +358,8 @@
 
   DTRACE_SCOPED();
 
-  if (!is_primary_ && active_secure_sessions_[kSecureDisplay]) {
+  if ((!is_primary_ && active_secure_sessions_[kSecureDisplay]) || display_paused_) {
     return status;
-  } else if (display_paused_) {
-    DisplayError error = display_intf_->Flush(&layer_stack_);
-    validated_ = false;
-    if (error != kErrorNone) {
-      DLOGE("Flush failed. Error = %d", error);
-    }
   } else {
     CacheAvrStatus();
 
@@ -753,7 +747,7 @@
   if (active_secure_sessions_[kSecureDisplay] != secure_sessions[kSecureDisplay]) {
     SecureEvent secure_event =
         secure_sessions.test(kSecureDisplay) ? kSecureDisplayStart : kSecureDisplayEnd;
-    DisplayError err = display_intf_->HandleSecureEvent(secure_event, &layer_stack_);
+    DisplayError err = display_intf_->HandleSecureEvent(secure_event);
     if (err != kErrorNone) {
       DLOGE("Set secure event failed");
       return err;
@@ -768,6 +762,21 @@
   return 0;
 }
 
+DisplayError HWCDisplayBuiltIn::HandleSecureEvent(SecureEvent secure_event) {
+  if (current_power_mode_ != HWC2::PowerMode::On) {
+    DLOGW("Cannot handle secure event when display is not active");
+    return kErrorPermission;
+  }
+
+  DisplayError err = display_intf_->HandleSecureEvent(secure_event);
+  if (err != kErrorNone) {
+    DLOGE("Handle secure event failed");
+     return err;
+  }
+
+  return kErrorNone;
+}
+
 void HWCDisplayBuiltIn::ForceRefreshRate(uint32_t refresh_rate) {
   if ((refresh_rate && (refresh_rate < min_refresh_rate_ || refresh_rate > max_refresh_rate_)) ||
       force_refresh_rate_ == refresh_rate) {
diff --git a/composer/hwc_display_builtin.h b/composer/hwc_display_builtin.h
index 90f9b6b..1ec9fee 100644
--- a/composer/hwc_display_builtin.h
+++ b/composer/hwc_display_builtin.h
@@ -96,6 +96,7 @@
   virtual int Perform(uint32_t operation, ...);
   virtual int HandleSecureSession(const std::bitset<kSecureMax> &secure_session,
                                   bool *power_on_pending);
+  virtual DisplayError HandleSecureEvent(SecureEvent secure_event);
   virtual void SetIdleTimeoutMs(uint32_t timeout_ms);
   virtual HWC2::Error SetFrameDumpConfig(uint32_t count, uint32_t bit_mask_layer_type,
                                          int32_t format, bool post_processed);
diff --git a/composer/hwc_display_pluggable.cpp b/composer/hwc_display_pluggable.cpp
index a3b61ec..9815259 100644
--- a/composer/hwc_display_pluggable.cpp
+++ b/composer/hwc_display_pluggable.cpp
@@ -122,7 +122,7 @@
 HWC2::Error HWCDisplayPluggable::Validate(uint32_t *out_num_types, uint32_t *out_num_requests) {
   auto status = HWC2::Error::None;
 
-  if (active_secure_sessions_[kSecureDisplay]) {
+  if (active_secure_sessions_[kSecureDisplay] || display_paused_) {
     MarkLayersForGPUBypass();
     return status;
   }
@@ -153,7 +153,7 @@
 HWC2::Error HWCDisplayPluggable::Present(shared_ptr<Fence> *out_retire_fence) {
   auto status = HWC2::Error::None;
 
-  if (!active_secure_sessions_[kSecureDisplay]) {
+  if (!active_secure_sessions_[kSecureDisplay] && !display_paused_) {
     status = HWCDisplay::CommitLayerStack();
     if (status == HWC2::Error::None) {
       status = HWCDisplay::PostCommitLayerStack(out_retire_fence);
diff --git a/composer/hwc_display_virtual_dpu.cpp b/composer/hwc_display_virtual_dpu.cpp
index ffa0f84..7b94dc1 100644
--- a/composer/hwc_display_virtual_dpu.cpp
+++ b/composer/hwc_display_virtual_dpu.cpp
@@ -158,15 +158,11 @@
     return HWC2::Error::NoResources;
   }
 
-  if (active_secure_sessions_.any()) {
-    return status;
+  if (NeedsGPUBypass()) {
+    return HWC2::Error::None;
   }
 
   layer_stack_.output_buffer = &output_buffer_;
-  if (display_paused_) {
-    validated_ = false;
-    flush_ = true;
-  }
 
   status = HWCDisplay::CommitLayerStack();
   if (status != HWC2::Error::None) {
diff --git a/composer/hwc_display_virtual_gpu.cpp b/composer/hwc_display_virtual_gpu.cpp
index 8a249cf..951b196 100644
--- a/composer/hwc_display_virtual_gpu.cpp
+++ b/composer/hwc_display_virtual_gpu.cpp
@@ -146,14 +146,11 @@
     return HWC2::Error::NoResources;
   }
 
-  if (active_secure_sessions_.any() || layer_set_.empty()) {
+  if (NeedsGPUBypass()) {
     return status;
   }
 
   layer_stack_.output_buffer = &output_buffer_;
-  if (display_paused_) {
-    validated_ = false;
-  }
 
   // Ensure that blit is initialized.
   // GPU context gets in secure or non-secure mode depending on output buffer provided.
diff --git a/composer/hwc_session.cpp b/composer/hwc_session.cpp
index c372c10..d54aef8 100644
--- a/composer/hwc_session.cpp
+++ b/composer/hwc_session.cpp
@@ -806,6 +806,7 @@
         status = hwc_display_[target_display]->Present(out_retire_fence);
         if (status == HWC2::Error::None) {
           PerformQsyncCallback(target_display);
+          locker_[target_display].Broadcast();
         }
       }
     }
@@ -1688,6 +1689,18 @@
     }
     break;
 
+    case qService::IQService::NOTIFY_TUI_TRANSITION: {
+      if (!input_parcel || !output_parcel) {
+        DLOGE("QService command = %d: input_parcel and output_parcel needed.", command);
+        break;
+      }
+      int event = input_parcel->readInt32();
+      int disp_id = input_parcel->readInt32();
+      status = HandleTUITransition(disp_id, event);
+      output_parcel->writeInt32(status);
+    }
+    break;
+
     default:
       DLOGW("QService command = %d is not supported.", command);
       break;
@@ -3484,4 +3497,151 @@
                              vsync_period_change_constraints, out_timeline);
 }
 
+android::status_t HWCSession::HandleTUITransition(int disp_id, int event) {
+  switch(event) {
+    case qService::IQService::TUI_TRANSITION_PREPARE:
+      return TUITransitionPrepare(disp_id);
+    case qService::IQService::TUI_TRANSITION_START:
+      return TUITransitionStart(disp_id);
+    case qService::IQService::TUI_TRANSITION_END:
+      return TUITransitionEnd(disp_id);
+    default:
+      DLOGE("Invalid event %d", event);
+      return -EINVAL;
+  }
+}
+
+android::status_t HWCSession::TUITransitionPrepare(int disp_id) {
+  hwc2_display_t target_display = GetDisplayIndex(disp_id);
+  if (target_display == -1) {
+    target_display = GetActiveBuiltinDisplay();
+  }
+
+  if (target_display != qdutils::DISPLAY_PRIMARY && target_display != qdutils::DISPLAY_BUILTIN_2) {
+    DLOGE("Display %d not supported", target_display);
+    return -ENOTSUP;
+  }
+
+  std::vector<DisplayMapInfo> map_info = {map_info_primary_};
+  std::copy(map_info_builtin_.begin(), map_info_builtin_.end(), std::back_inserter(map_info));
+  std::copy(map_info_pluggable_.begin(), map_info_pluggable_.end(), std::back_inserter(map_info));
+  std::copy(map_info_virtual_.begin(), map_info_virtual_.end(), std::back_inserter(map_info));
+
+  for (auto &info : map_info) {
+    Locker::ScopeLock lock_d(locker_[info.client_id]);
+    if (hwc_display_[info.client_id]) {
+      if (info.client_id == target_display) {
+        continue;
+      }
+      int err = hwc_display_[info.client_id]->SetDisplayStatus(HWCDisplay::kDisplayStatusPause);
+      if (err != 0) {
+        return err;
+      }
+    }
+  }
+
+  return 0;
+}
+
+android::status_t HWCSession::TUITransitionStart(int disp_id) {
+  hwc2_display_t target_display = GetDisplayIndex(disp_id);
+  if (target_display == -1) {
+    target_display = GetActiveBuiltinDisplay();
+  }
+
+  if (target_display != qdutils::DISPLAY_PRIMARY && target_display != qdutils::DISPLAY_BUILTIN_2) {
+    DLOGE("Display %d not supported", target_display);
+    return -ENOTSUP;
+  }
+
+  {
+    Locker::ScopeLock lock_d(locker_[target_display]);
+    if (hwc_display_[target_display]) {
+      if (hwc_display_[target_display]->HandleSecureEvent(kTUITransitionStart) != kErrorNone) {
+        return -EINVAL;
+      }
+
+      if (hwc_display_[target_display]->IsDisplayCommandMode()) {
+        // Todo(user): Unlock it before sending events to client. It may cause deadlocks in future.
+        callbacks_.Refresh(target_display);
+
+        DLOGI("Waiting for device assign");
+
+        locker_[target_display].Wait();
+      }
+      DLOGI("Pause display %d", target_display);
+
+      int err = hwc_display_[target_display]->SetDisplayStatus(HWCDisplay::kDisplayStatusPauseOnly);
+      if (err != 0) {
+        return err;
+      }
+    } else {
+      DLOGW("Target display %d is not ready", disp_id);
+      return -ENODEV;
+    }
+  }
+  return 0;
+}
+android::status_t HWCSession::TUITransitionEnd(int disp_id) {
+  hwc2_display_t target_display = GetDisplayIndex(disp_id);
+  if (target_display == -1) {
+    target_display = GetActiveBuiltinDisplay();
+  }
+
+  if (target_display != qdutils::DISPLAY_PRIMARY && target_display != qdutils::DISPLAY_BUILTIN_2) {
+    DLOGE("Display %d not supported", target_display);
+    return -ENOTSUP;
+  }
+
+  {
+    Locker::ScopeLock lock_d(locker_[target_display]);
+    if (hwc_display_[target_display]) {
+      DLOGI("Resume display %d", target_display);
+
+      int err =
+          hwc_display_[target_display]->SetDisplayStatus(HWCDisplay::kDisplayStatusResumeOnly);
+      if (err != 0) {
+        return err;
+      }
+
+      if (hwc_display_[target_display]->HandleSecureEvent(kTUITransitionEnd) != kErrorNone) {
+        return -EINVAL;
+      }
+
+      if (hwc_display_[target_display]->IsDisplayCommandMode()) {
+        hwc_display_[target_display]->ResetValidation();
+        // Todo(user): Unlock it before sending events to client. It may cause deadlocks in future.
+        callbacks_.Refresh(target_display);
+
+        DLOGI("Waiting for device unassign");
+        locker_[target_display].Wait();
+      }
+
+    } else {
+      DLOGW("Target display %d is not ready", disp_id);
+      return -ENODEV;
+    }
+  }
+
+  std::vector<DisplayMapInfo> map_info = {map_info_primary_};
+  std::copy(map_info_builtin_.begin(), map_info_builtin_.end(), std::back_inserter(map_info));
+  std::copy(map_info_pluggable_.begin(), map_info_pluggable_.end(), std::back_inserter(map_info));
+  std::copy(map_info_virtual_.begin(), map_info_virtual_.end(), std::back_inserter(map_info));
+
+  for (auto &info : map_info) {
+    Locker::ScopeLock lock_d(locker_[info.client_id]);
+    if (hwc_display_[info.client_id]) {
+      if (info.client_id == target_display) {
+        continue;
+      }
+      int err = hwc_display_[info.client_id]->SetDisplayStatus(HWCDisplay::kDisplayStatusResume);
+      if (err != 0) {
+        return err;
+      }
+    }
+  }
+
+  return 0;
+}
+
 }  // namespace sdm
diff --git a/composer/hwc_session.h b/composer/hwc_session.h
index 62c884d..136df8c 100644
--- a/composer/hwc_session.h
+++ b/composer/hwc_session.h
@@ -383,6 +383,7 @@
     virtual int IsRotatorSupportedFormat(int hal_format, bool ubwc, bool *supported);
     virtual int ControlQsyncCallback(bool enable);
     virtual int GetDisplayHwId(uint32_t disp_id, uint32_t *display_hw_id);
+    virtual int SendTUIEvent(DispType dpy, DisplayConfig::TUIEventType event_type);
 
     std::weak_ptr<DisplayConfig::ConfigCallback> callback_;
     HWCSession *hwc_session_ = nullptr;
@@ -486,6 +487,7 @@
   android::status_t SetFrameTriggerMode(const android::Parcel *input_parcel);
   android::status_t SetPanelLuminanceAttributes(const android::Parcel *input_parcel);
   android::status_t setColorSamplingEnabled(const android::Parcel *input_parcel);
+  android::status_t HandleTUITransition(int disp_id, int event);
 
   // Internal methods
   HWC2::Error ValidateDisplayInternal(hwc2_display_t display, uint32_t *out_num_types,
@@ -501,6 +503,9 @@
   int32_t GetVirtualDisplayId();
   void PerformQsyncCallback(hwc2_display_t display);
   bool isSmartPanelConfig(uint32_t disp_id, uint32_t config_id);
+  android::status_t TUITransitionPrepare(int disp_id);
+  android::status_t TUITransitionStart(int disp_id);
+  android::status_t TUITransitionEnd(int disp_id);
 
   CoreInterface *core_intf_ = nullptr;
   HWCDisplay *hwc_display_[HWCCallbacks::kNumDisplays] = {nullptr};
diff --git a/composer/hwc_session_services.cpp b/composer/hwc_session_services.cpp
index 1f8324f..f9f5822 100644
--- a/composer/hwc_session_services.cpp
+++ b/composer/hwc_session_services.cpp
@@ -61,6 +61,9 @@
     case DispType::kVirtual:
       return qdutils::DISPLAY_VIRTUAL;
 
+    case DispType::kBuiltIn2:
+      return qdutils::DISPLAY_BUILTIN_2;
+
     default:
       break;
   }
@@ -1230,4 +1233,20 @@
   return error;
 }
 
+int HWCSession::DisplayConfigImpl::SendTUIEvent(DispType dpy,
+                                                DisplayConfig::TUIEventType event_type) {
+  int disp_id = MapDisplayType(dpy);
+  switch(event_type) {
+    case DisplayConfig::TUIEventType::kPrepareTUITransition:
+      return hwc_session_->TUITransitionPrepare(disp_id);
+    case DisplayConfig::TUIEventType::kStartTUITransition:
+      return hwc_session_->TUITransitionStart(disp_id);
+    case DisplayConfig::TUIEventType::kEndTUITransition:
+      return hwc_session_->TUITransitionEnd(disp_id);
+    default:
+      DLOGE("Invalid event %d", event_type);
+      return -EINVAL;
+  }
+}
+
 }  // namespace sdm
diff --git a/libdrmutils/drm_interface.h b/libdrmutils/drm_interface.h
index be2ecca..815b022 100644
--- a/libdrmutils/drm_interface.h
+++ b/libdrmutils/drm_interface.h
@@ -177,6 +177,11 @@
    */
   PLANE_SET_POST_PROC,
   /*
+   * Op: Resets property cache of all planes that are assigned to given CRTC
+   * Arg: uint32_t - CRTC ID
+   */
+  PLANES_RESET_CACHE,
+  /*
    * Op: Activate or deactivate a CRTC
    * Arg: uint32_t - CRTC ID
    *      uint32_t - 1 to enable, 0 to disable
@@ -312,6 +317,17 @@
    */
   CRTC_SET_CACHE_STATE,
   /*
+   * Op: Sets VM Request state for CRTC.
+   * Arg: uint32_t - CRTC ID
+   *      uint32_t - vm request state
+   */
+  CRTC_SET_VM_REQ_STATE,
+  /*
+   * Op: reset CRTC property cache.
+   * Arg: uint32_t - CRTC ID
+   */
+  CRTC_RESET_CACHE,
+  /*
    * Op: Returns retire fence for this commit. Should be called after Commit() on
    * DRMAtomicReqInterface.
    * Arg: uint32_t - Connector ID
@@ -450,6 +466,12 @@
   VIRTUAL,
 };
 
+enum struct DRMVMRequestState {
+  NONE,
+  ACQUIRE,
+  RELEASE,
+};
+
 struct DRMRect {
   uint32_t left;    // Left-most pixel coordinate.
   uint32_t top;     // Top-most pixel coordinate.
diff --git a/libqservice/IQService.h b/libqservice/IQService.h
index 8ce6549..a904a5a 100644
--- a/libqservice/IQService.h
+++ b/libqservice/IQService.h
@@ -79,7 +79,8 @@
       SET_PANEL_LUMINANCE = 47,                // Set Panel Luminance attributes.
       SET_BRIGHTNESS_SCALE = 48,               // Set brightness scale ratio
       SET_COLOR_SAMPLING_ENABLED = 49,         // Toggle the collection of display color stats
-      SET_VSYNC_STATE = 50,                  // Enable/disable Vsync
+      SET_VSYNC_STATE = 50,                    // Enable/disable Vsync
+      NOTIFY_TUI_TRANSITION = 51,              // Notify TUI transition prepare/start/stop
       COMMAND_LIST_END = 400,
     };
 
@@ -116,6 +117,12 @@
         QSYNC_MODE_ONESHOT,    // Not supported
     };
 
+    enum {
+        TUI_TRANSITION_PREPARE,
+        TUI_TRANSITION_START,
+        TUI_TRANSITION_END,
+    };
+
     // Register a HWC client that can be notified
     // This client is generic and is intended to get
     // dispatches of all events calling into QService
diff --git a/sde-drm/drm_atomic_req.cpp b/sde-drm/drm_atomic_req.cpp
index 0245bea..6935ed0 100644
--- a/sde-drm/drm_atomic_req.cpp
+++ b/sde-drm/drm_atomic_req.cpp
@@ -107,7 +107,9 @@
     case DRMOps::CRTC_SET_DEST_SCALER_CONFIG:
     case DRMOps::CRTC_SET_CAPTURE_MODE:
     case DRMOps::CRTC_SET_IDLE_PC_STATE:
-    case DRMOps::CRTC_SET_CACHE_STATE: {
+    case DRMOps::CRTC_SET_CACHE_STATE:
+    case DRMOps::CRTC_SET_VM_REQ_STATE:
+    case DRMOps::CRTC_RESET_CACHE: {
       drm_mgr_->GetCrtcMgr()->Perform(opcode, obj_id, drm_atomic_req_, args);
     } break;
     case DRMOps::CONNECTOR_SET_CRTC:
@@ -132,6 +134,9 @@
     case DRMOps::DPPS_COMMIT_FEATURE: {
       drm_mgr_->GetDppsMgrIntf()->CommitDppsFeatures(drm_atomic_req_, token_);
     } break;
+    case DRMOps::PLANES_RESET_CACHE: {
+      drm_mgr_->GetPlaneMgr()->ResetCache(obj_id);
+    } break;
     default:
       DRM_LOGE("Invalid opcode %d", opcode);
   }
@@ -144,7 +149,6 @@
   // because we just want to validate, not actually mark planes as removed
   drm_mgr_->GetPlaneMgr()->UnsetUnusedResources(token_.crtc_id, false/*is_commit*/,
                                                 drm_atomic_req_);
-
   int ret = drmModeAtomicCommit(fd_, drm_atomic_req_,
                                 DRM_MODE_ATOMIC_ALLOW_MODESET | DRM_MODE_ATOMIC_TEST_ONLY, nullptr);
   if (ret) {
diff --git a/sde-drm/drm_crtc.cpp b/sde-drm/drm_crtc.cpp
index 0646f80..22e25e1 100644
--- a/sde-drm/drm_crtc.cpp
+++ b/sde-drm/drm_crtc.cpp
@@ -74,6 +74,11 @@
 static uint8_t CACHE_STATE_DISABLED = 0;
 static uint8_t CACHE_STATE_ENABLED = 1;
 
+// VM Request states
+static uint8_t VM_REQ_STATE_NONE = 0;
+static uint8_t VM_REQ_STATE_RELEASE = 1;
+static uint8_t VM_REQ_STATE_ACQUIRE = 2;
+
 static void PopulateSecurityLevels(drmModePropertyRes *prop) {
   static bool security_levels_populated = false;
   if (!security_levels_populated) {
@@ -136,6 +141,23 @@
   }
 }
 
+static void PopulateVMRequestStates(drmModePropertyRes *prop) {
+  static bool idle_pc_state_populated = false;
+  if (!idle_pc_state_populated) {
+    for (auto i = 0; i < prop->count_enums; i++) {
+      string enum_name(prop->enums[i].name);
+      if (enum_name == "vm_req_none") {
+        VM_REQ_STATE_NONE = prop->enums[i].value;
+      } else if (enum_name == "vm_req_release") {
+        VM_REQ_STATE_RELEASE = prop->enums[i].value;
+      } else if (enum_name == "vm_req_acquire") {
+        VM_REQ_STATE_ACQUIRE = prop->enums[i].value;
+      }
+    }
+    idle_pc_state_populated = true;
+  }
+}
+
 #define __CLASS__ "DRMCrtcManager"
 
 void DRMCrtcManager::Init(drmModeRes *resource) {
@@ -326,6 +348,10 @@
       PopulateCacheStates(info);
     }
 
+    if (prop_enum == DRMProperty::VM_REQ_STATE) {
+      PopulateVMRequestStates(info);
+    }
+
     prop_mgr_.SetPropertyId(prop_enum, info->prop_id);
     if (prop_enum == DRMProperty::CAPABILITIES) {
       ParseCapabilities(props->prop_values[j]);
@@ -780,6 +806,33 @@
                   crtc_cache_state, false /* cache */, tmp_prop_val_map_);
     } break;
 
+    case DRMOps::CRTC_SET_VM_REQ_STATE: {
+      if (!prop_mgr_.IsPropertyAvailable(DRMProperty::VM_REQ_STATE)) {
+        return;
+      }
+      int drm_vm_req_state = va_arg(args, int);
+      uint32_t vm_req_state = VM_REQ_STATE_NONE;
+      switch (drm_vm_req_state) {
+        case static_cast<int>(DRMVMRequestState::RELEASE):
+          vm_req_state = VM_REQ_STATE_RELEASE;
+          break;
+        case static_cast<int>(DRMVMRequestState::ACQUIRE):
+          vm_req_state = VM_REQ_STATE_ACQUIRE;
+          break;
+        default:
+          vm_req_state = VM_REQ_STATE_NONE;
+          break;
+      }
+      AddProperty(req, obj_id, prop_mgr_.GetPropertyId(DRMProperty::VM_REQ_STATE), vm_req_state,
+                  true /* cache */, tmp_prop_val_map_);
+      DRM_LOGD("CRTC %d: Set vm_req_state %d", obj_id, vm_req_state);
+    }; break;
+
+    case DRMOps::CRTC_RESET_CACHE: {
+      tmp_prop_val_map_.clear();
+      committed_prop_val_map_.clear();
+    } break;
+
     default:
       DRM_LOGE("Invalid opcode %d to set the property on crtc %d", code, obj_id);
       break;
diff --git a/sde-drm/drm_plane.cpp b/sde-drm/drm_plane.cpp
index f1bd93b..bee1922 100644
--- a/sde-drm/drm_plane.cpp
+++ b/sde-drm/drm_plane.cpp
@@ -403,6 +403,17 @@
   }
 }
 
+void DRMPlaneManager::ResetCache(uint32_t crtc_id) {
+  lock_guard<mutex> lock(lock_);
+  for (auto &plane : plane_pool_) {
+    uint32_t assigned_crtc = 0;
+    plane.second->GetAssignedCrtc(&assigned_crtc);
+    if (assigned_crtc == crtc_id) {
+      plane.second->ResetCache();
+    }
+  }
+}
+
 // ==============================================================================================//
 
 #undef __CLASS__
diff --git a/sde-drm/drm_plane.h b/sde-drm/drm_plane.h
index b3bd9df..fc464be 100644
--- a/sde-drm/drm_plane.h
+++ b/sde-drm/drm_plane.h
@@ -84,6 +84,10 @@
   void ResetColorLUTs(bool is_commit, drmModeAtomicReq *req);
   void ResetColorLUTState(DRMTonemapLutType lut_type, bool is_commit, drmModeAtomicReq *req);
   void ResetColorLUT(DRMPPFeatureID id, drmModeAtomicReq *req);
+  void ResetCache() {
+    tmp_prop_val_map_.clear();
+    committed_prop_val_map_.clear();
+  }
 
  private:
   typedef std::map<DRMProperty, std::tuple<uint64_t, drmModePropertyRes *>> PropertyMap;
@@ -133,6 +137,7 @@
   void UnsetScalerLUT();
   void PostValidate(uint32_t crtc_id, bool success);
   void PostCommit(uint32_t crtc_id, bool success);
+  void ResetCache(uint32_t crtc_id);
 
  private:
   void Perform(DRMOps code, drmModeAtomicReq *req, uint32_t obj_id, ...);
diff --git a/sde-drm/drm_property.cpp b/sde-drm/drm_property.cpp
index 1cf4d4e..b79372a 100644
--- a/sde-drm/drm_property.cpp
+++ b/sde-drm/drm_property.cpp
@@ -164,6 +164,7 @@
   if (name == "supported_colorspaces") { return DRMProperty::SUPPORTED_COLORSPACES; }
   if (name == "SDE_DSPP_SPR_DITHER_V1") { return DRMProperty::SDE_DSPP_SPR_DITHER_V1; }
   if (name == "cache_state") { return DRMProperty::CACHE_STATE; }
+  if (name == "vm_request_state") { return DRMProperty::VM_REQ_STATE; }
 
   return DRMProperty::INVALID;
 }
diff --git a/sde-drm/drm_property.h b/sde-drm/drm_property.h
index 9788790..a7986e9 100644
--- a/sde-drm/drm_property.h
+++ b/sde-drm/drm_property.h
@@ -169,6 +169,7 @@
   COLORSPACE,
   SUPPORTED_COLORSPACES,
   CACHE_STATE,
+  VM_REQ_STATE,
 
   // Insert above
   MAX
diff --git a/sdm/include/core/display_interface.h b/sdm/include/core/display_interface.h
index a78ed22..1e4b461 100644
--- a/sdm/include/core/display_interface.h
+++ b/sdm/include/core/display_interface.h
@@ -156,6 +156,10 @@
 enum SecureEvent {
   kSecureDisplayStart,  // Client sets it to notify secure display session start
   kSecureDisplayEnd,    // Client sets it to notify secure display session end
+  kTUITransitionStart,  // Client sets it to notify start of TUI Transition to release
+                        // the display hardware to trusted VM.
+  kTUITransitionEnd,    // Client sets it to notify end of TUI Transition to acquire
+                        // the display hardware from trusted VM.
   kSecureEventMax,
 };
 
@@ -814,7 +818,7 @@
 
     @return \link DisplayError \endlink
   */
-  virtual DisplayError HandleSecureEvent(SecureEvent secure_event, LayerStack *layer_stack) = 0;
+  virtual DisplayError HandleSecureEvent(SecureEvent secure_event) = 0;
 
   /*! @brief Method to set dpps ad roi.
 
diff --git a/sdm/include/private/resource_interface.h b/sdm/include/private/resource_interface.h
index 9e6ee7e..bcbf26c 100644
--- a/sdm/include/private/resource_interface.h
+++ b/sdm/include/private/resource_interface.h
@@ -34,7 +34,7 @@
  public:
   enum ResourceCmd {
     kCmdResetLUT,
-    kCmdGetDefaultClk,
+    kCmdGetDefaultQosData,
     kCmdDisableRotatorOneFrame,
     kCmdSetDisplayState,
     kCmdUpdateSyncHandle,
diff --git a/sdm/include/utils/locker.h b/sdm/include/utils/locker.h
index 4b3f3c6..37eab46 100755
--- a/sdm/include/utils/locker.h
+++ b/sdm/include/utils/locker.h
@@ -77,7 +77,6 @@
     }
 
     ~SequenceExitScopeLock() {
-      locker_.Broadcast();
       locker_.Unlock();
     }
 
@@ -117,7 +116,6 @@
     }
 
     ~SequenceCancelScopeLock() {
-      locker_.Broadcast();
       locker_.Unlock();
     }
 
diff --git a/sdm/libs/core/comp_manager.cpp b/sdm/libs/core/comp_manager.cpp
index 8f35daa..9b5a631 100644
--- a/sdm/libs/core/comp_manager.cpp
+++ b/sdm/libs/core/comp_manager.cpp
@@ -83,7 +83,7 @@
                                           const HWPanelInfo &hw_panel_info,
                                           const HWMixerAttributes &mixer_attributes,
                                           const DisplayConfigVariableInfo &fb_config,
-                                          Handle *display_ctx, uint32_t *default_clk_hz) {
+                                          Handle *display_ctx, HWQosData*default_qos_data) {
   SCOPE_LOCK(locker_);
 
   DisplayError error = kErrorNone;
@@ -121,8 +121,8 @@
     return error;
   }
 
-  error = resource_intf_->Perform(ResourceInterface::kCmdGetDefaultClk,
-                                  display_comp_ctx->display_resource_ctx, default_clk_hz);
+  error = resource_intf_->Perform(ResourceInterface::kCmdGetDefaultQosData,
+                                  display_comp_ctx->display_resource_ctx, default_qos_data);
   if (error != kErrorNone) {
     strategy->Deinit();
     delete strategy;
@@ -212,7 +212,7 @@
                                              const HWPanelInfo &hw_panel_info,
                                              const HWMixerAttributes &mixer_attributes,
                                              const DisplayConfigVariableInfo &fb_config,
-                                             uint32_t *default_clk_hz) {
+                                             HWQosData*default_qos_data) {
   SCOPE_LOCK(locker_);
   DTRACE_SCOPED();
 
@@ -226,8 +226,8 @@
     return error;
   }
 
-  error = resource_intf_->Perform(ResourceInterface::kCmdGetDefaultClk,
-                                  display_comp_ctx->display_resource_ctx, default_clk_hz);
+  error = resource_intf_->Perform(ResourceInterface::kCmdGetDefaultQosData,
+                                  display_comp_ctx->display_resource_ctx, default_qos_data);
   if (error != kErrorNone) {
     return error;
   }
@@ -660,6 +660,7 @@
     resource_intf_->Perform(ResourceInterface::kCmdDisableRotatorOneFrame,
                             display_comp_ctx->display_resource_ctx);
   }
+  safe_mode_ = (secure_event == kSecureDisplayStart) ? true : false;
 }
 
 void CompManager::UpdateStrategyConstraints(bool is_primary, bool disabled) {
diff --git a/sdm/libs/core/comp_manager.h b/sdm/libs/core/comp_manager.h
index 43aee7f..f2db8de 100644
--- a/sdm/libs/core/comp_manager.h
+++ b/sdm/libs/core/comp_manager.h
@@ -49,13 +49,13 @@
                                const HWPanelInfo &hw_panel_info,
                                const HWMixerAttributes &mixer_attributes,
                                const DisplayConfigVariableInfo &fb_config, Handle *display_ctx,
-                               uint32_t *default_clk_hz);
+                               HWQosData *qos_data);
   DisplayError UnregisterDisplay(Handle display_ctx);
   DisplayError ReconfigureDisplay(Handle display_ctx, const HWDisplayAttributes &display_attributes,
                                   const HWPanelInfo &hw_panel_info,
                                   const HWMixerAttributes &mixer_attributes,
                                   const DisplayConfigVariableInfo &fb_config,
-                                  uint32_t *default_clk_hz);
+                                  HWQosData *qos_data);
   void PrePrepare(Handle display_ctx, HWLayers *hw_layers);
   DisplayError Prepare(Handle display_ctx, HWLayers *hw_layers);
   DisplayError Commit(Handle display_ctx, HWLayers *hw_layers);
diff --git a/sdm/libs/core/display_base.cpp b/sdm/libs/core/display_base.cpp
index 343c688..108057b 100644
--- a/sdm/libs/core/display_base.cpp
+++ b/sdm/libs/core/display_base.cpp
@@ -136,7 +136,7 @@
 
   error = comp_manager_->RegisterDisplay(display_id_, display_type_, display_attributes_,
                                          hw_panel_info_, mixer_attributes_, fb_config_,
-                                         &display_comp_ctx_, &(default_qos_data_.clock_hz));
+                                         &display_comp_ctx_, &default_qos_data_);
   if (error != kErrorNone) {
     DLOGW("Display %d comp manager registration failed!", display_id_);
     goto CleanupOnError;
@@ -582,7 +582,7 @@
 
     error = comp_manager_->ReconfigureDisplay(display_comp_ctx_, display_attributes_,
                                               hw_panel_info_, mixer_attributes_, fb_config_,
-                                              &(default_qos_data_.clock_hz));
+                                              &default_qos_data_);
     if (error != kErrorNone) {
       return error;
     }
@@ -1241,7 +1241,7 @@
 DisplayError DisplayBase::SetVSyncState(bool enable) {
   lock_guard<recursive_mutex> obj(recursive_mutex_);
 
-  if (state_ == kStateOff && enable) {
+  if ((state_ == kStateOff || secure_event_ == kSecureDisplayStart) && enable) {
     DLOGW("Can't enable vsync when display %d-%d is powered off!! Defer it when display is active",
           display_id_, display_type_);
     vsync_enable_pending_ = true;
@@ -1306,8 +1306,7 @@
   }
 
   error = comp_manager_->ReconfigureDisplay(display_comp_ctx_, display_attributes, hw_panel_info,
-                                            mixer_attributes, fb_config_,
-                                            &(default_qos_data_.clock_hz));
+                                            mixer_attributes, fb_config_, &default_qos_data_);
   if (error != kErrorNone) {
     return error;
   }
@@ -1416,6 +1415,14 @@
   uint32_t mixer_height = mixer_attributes_.height;
   uint32_t fb_width = fb_config_.x_pixels;
   uint32_t fb_height = fb_config_.y_pixels;
+  uint32_t display_width = display_attributes_.x_pixels;
+  uint32_t display_height = display_attributes_.y_pixels;
+
+  if (secure_event_ == kSecureDisplayStart) {
+    *new_mixer_width = display_width;
+    *new_mixer_height = display_height;
+    return ((*new_mixer_width != mixer_width) || (*new_mixer_height != mixer_height));
+  }
 
   if (req_mixer_width_ && req_mixer_height_) {
     DLOGD_IF(kTagDisplay, "Required mixer width : %d, height : %d",
@@ -1432,8 +1439,6 @@
   uint32_t layer_count = UINT32(layer_stack->layers.size());
   uint32_t fb_area = fb_width * fb_height;
   LayerRect fb_rect = (LayerRect) {0.0f, 0.0f, FLOAT(fb_width), FLOAT(fb_height)};
-  uint32_t display_width = display_attributes_.x_pixels;
-  uint32_t display_height = display_attributes_.y_pixels;
 
   RectOrientation fb_orientation = GetOrientation(fb_rect);
   uint32_t max_layer_area = 0;
@@ -1519,8 +1524,7 @@
   }
 
   error =  comp_manager_->ReconfigureDisplay(display_comp_ctx_, display_attributes_, hw_panel_info_,
-                                             mixer_attributes_, variable_info,
-                                             &(default_qos_data_.clock_hz));
+                                             mixer_attributes_, variable_info, &default_qos_data_);
   if (error != kErrorNone) {
     return error;
   }
diff --git a/sdm/libs/core/display_base.h b/sdm/libs/core/display_base.h
index 3138c84..832be0f 100644
--- a/sdm/libs/core/display_base.h
+++ b/sdm/libs/core/display_base.h
@@ -137,7 +137,7 @@
   virtual DisplayError GetClientTargetSupport(uint32_t width, uint32_t height,
                                               LayerBufferFormat format,
                                               const ColorMetaData &color_metadata);
-  virtual DisplayError HandleSecureEvent(SecureEvent secure_event, LayerStack *layer_stack) {
+  virtual DisplayError HandleSecureEvent(SecureEvent secure_event) {
     return kErrorNotSupported;
   }
   virtual DisplayError SetDisplayDppsAdROI(void *payload) {
@@ -261,6 +261,7 @@
 
   static Locker display_power_reset_lock_;
   static bool display_power_reset_pending_;
+  SecureEvent secure_event_ = kSecureEventMax;
 
  private:
   bool StartDisplayPowerReset();
diff --git a/sdm/libs/core/display_builtin.cpp b/sdm/libs/core/display_builtin.cpp
index 73edd4f..a201ccd 100644
--- a/sdm/libs/core/display_builtin.cpp
+++ b/sdm/libs/core/display_builtin.cpp
@@ -85,7 +85,10 @@
             kModeVideo);
     }
   }
-
+#ifdef TRUSTED_VM
+  event_list_ = {HWEvent::VSYNC, HWEvent::EXIT, HWEvent::PINGPONG_TIMEOUT, HWEvent::PANEL_DEAD,
+                 HWEvent::HW_RECOVERY};
+#else
   if (hw_panel_info_.mode == kModeCommand) {
     event_list_ = {HWEvent::VSYNC, HWEvent::EXIT,
                    /*HWEvent::IDLE_NOTIFY, */
@@ -99,7 +102,7 @@
                    HWEvent::PANEL_DEAD,    HWEvent::HW_RECOVERY,
                    HWEvent::HISTOGRAM};
   }
-
+#endif
   avr_prop_disabled_ = Debug::IsAVRDisabled();
 
   error = HWEventsInterface::Create(display_id_, kBuiltIn, this, event_list_, hw_intf_,
@@ -1108,13 +1111,14 @@
     DLOGE("DppsNotifyOps op %d error %d", op, ret);
 }
 
-DisplayError DisplayBuiltIn::HandleSecureEvent(SecureEvent secure_event, LayerStack *layer_stack) {
-  hw_layers_.info.stack = layer_stack;
-  DisplayError err = hw_intf_->HandleSecureEvent(secure_event, &hw_layers_);
+DisplayError DisplayBuiltIn::HandleSecureEvent(SecureEvent secure_event) {
+  lock_guard<recursive_mutex> obj(recursive_mutex_);
+  DisplayError err = hw_intf_->HandleSecureEvent(secure_event, default_qos_data_);
   if (err != kErrorNone) {
     return err;
   }
   comp_manager_->HandleSecureEvent(display_comp_ctx_, secure_event);
+  secure_event_ = secure_event;
 
   return kErrorNone;
 }
@@ -1401,7 +1405,7 @@
 
   error = comp_manager_->ReconfigureDisplay(display_comp_ctx_, display_attributes, hw_panel_info,
                                             mixer_attributes, fb_config_,
-                                            &(default_qos_data_.clock_hz));
+                                            &default_qos_data_);
   if (error != kErrorNone) {
     return error;
   }
diff --git a/sdm/libs/core/display_builtin.h b/sdm/libs/core/display_builtin.h
index 556bdb9..27ce7c2 100644
--- a/sdm/libs/core/display_builtin.h
+++ b/sdm/libs/core/display_builtin.h
@@ -117,8 +117,7 @@
   DisplayError GetPanelBrightness(float *brightness) override;
   DisplayError GetPanelMaxBrightness(uint32_t *max_brightness_level) override;
   DisplayError GetRefreshRate(uint32_t *refresh_rate) override;
-  DisplayError HandleSecureEvent(SecureEvent secure_event,
-                                 LayerStack *layer_stack) override;
+  DisplayError HandleSecureEvent(SecureEvent secure_event) override;
   DisplayError SetDisplayDppsAdROI(void *payload) override;
   DisplayError SetQSyncMode(QSyncMode qsync_mode) override;
   DisplayError ControlIdlePowerCollapse(bool enable, bool synchronous) override;
diff --git a/sdm/libs/core/display_virtual.cpp b/sdm/libs/core/display_virtual.cpp
index 1da0ece..f7611ab 100644
--- a/sdm/libs/core/display_virtual.cpp
+++ b/sdm/libs/core/display_virtual.cpp
@@ -141,11 +141,11 @@
   if (!display_comp_ctx_) {
     error = comp_manager_->RegisterDisplay(display_id_, display_type_, display_attributes,
                                            hw_panel_info, mixer_attributes, fb_config,
-                                           &display_comp_ctx_, &(default_qos_data_.clock_hz));
+                                           &display_comp_ctx_, &default_qos_data_);
   } else {
     error = comp_manager_->ReconfigureDisplay(display_comp_ctx_, display_attributes, hw_panel_info,
                                               mixer_attributes, fb_config,
-                                              &(default_qos_data_.clock_hz));
+                                              &default_qos_data_);
   }
   if (error != kErrorNone) {
     return error;
diff --git a/sdm/libs/core/drm/hw_device_drm.cpp b/sdm/libs/core/drm/hw_device_drm.cpp
index 251bec5..a125d24 100644
--- a/sdm/libs/core/drm/hw_device_drm.cpp
+++ b/sdm/libs/core/drm/hw_device_drm.cpp
@@ -537,6 +537,10 @@
     drm_atomic_intf_->Perform(DRMOps::CONNECTOR_SET_POWER_MODE, token_.conn_id, DRMPowerMode::OFF);
     drm_atomic_intf_->Perform(DRMOps::CRTC_SET_MODE, token_.crtc_id, nullptr);
     drm_atomic_intf_->Perform(DRMOps::CRTC_SET_ACTIVE, token_.crtc_id, 0);
+#ifdef TRUSTED_VM
+    drm_atomic_intf_->Perform(sde_drm::DRMOps::CRTC_SET_VM_REQ_STATE, token_.crtc_id,
+                              sde_drm::DRMVMRequestState::RELEASE);
+#endif
     int ret = NullCommit(true /* synchronous */, false /* retain_planes */);
     if (ret) {
       DLOGE("Commit failed with error: %d", ret);
@@ -1106,7 +1110,7 @@
   solid_fills_.clear();
   bool resource_update = hw_layers->updates_mask.test(kUpdateResources);
   bool buffer_update = hw_layers->updates_mask.test(kSwapBuffers);
-  bool update_config = resource_update || buffer_update ||
+  bool update_config = resource_update || buffer_update || tui_state_ == kTUIStateEnd ||
                        hw_layer_info.stack->flags.geometry_changed;
 
   if (hw_panel_info_.partial_update && update_config) {
@@ -1310,12 +1314,16 @@
     }
   }
 
-  if (first_cycle_) {
+  if (first_cycle_ || tui_state_ == kTUIStateEnd) {
     drm_atomic_intf_->Perform(DRMOps::CONNECTOR_SET_TOPOLOGY_CONTROL, token_.conn_id,
                               topology_control_);
     drm_atomic_intf_->Perform(DRMOps::CRTC_SET_ACTIVE, token_.crtc_id, 1);
     drm_atomic_intf_->Perform(DRMOps::CONNECTOR_SET_CRTC, token_.conn_id, token_.crtc_id);
     drm_atomic_intf_->Perform(DRMOps::CONNECTOR_SET_POWER_MODE, token_.conn_id, DRMPowerMode::ON);
+#ifdef TRUSTED_VM
+    drm_atomic_intf_->Perform(sde_drm::DRMOps::CRTC_SET_VM_REQ_STATE, token_.crtc_id,
+                              sde_drm::DRMVMRequestState::ACQUIRE);
+#endif
     last_power_mode_ = DRMPowerMode::ON;
   } else if (pending_doze_ && !validate) {
     drm_atomic_intf_->Perform(DRMOps::CRTC_SET_ACTIVE, token_.crtc_id, 1);
@@ -1474,6 +1482,9 @@
   Fence::ScopedRef scoped_ref;
   SetupAtomic(scoped_ref, hw_layers, false /* validate */, &release_fence_fd, &retire_fence_fd);
 
+  bool sync_commit = synchronous_commit_ ||
+                    (tui_state_ == kTUIStateStart || tui_state_ == kTUIStateEnd);
+
   if (hw_layers->elapse_timestamp > 0) {
     struct timespec t = {0, 0};
     clock_gettime(CLOCK_MONOTONIC, &t);
@@ -1483,7 +1494,7 @@
     }
   }
 
-  int ret = drm_atomic_intf_->Commit(synchronous_commit_, false /* retain_planes*/);
+  int ret = drm_atomic_intf_->Commit(sync_commit, false /* retain_planes*/);
   shared_ptr<Fence> release_fence = Fence::Create(INT(release_fence_fd), "release");
   shared_ptr<Fence> retire_fence = Fence::Create(INT(retire_fence_fd), "retire");
   if (ret) {
@@ -1560,13 +1571,25 @@
   // Inherently a real commit ensures null commit properties have happened, so update the member
   first_null_cycle_ = false;
 
+  if (tui_state_ == kTUIStateStart) {
+    tui_state_ = kTUIStateInProgress;
+  } else if (tui_state_ == kTUIStateEnd) {
+    tui_state_ = kTUIStateNone;
+  }
+#ifdef TRUSTED_VM
+  drm_atomic_intf_->Perform(sde_drm::DRMOps::CRTC_SET_VM_REQ_STATE, token_.crtc_id,
+                            sde_drm::DRMVMRequestState::NONE);
+#endif
+
   return kErrorNone;
 }
 
 DisplayError HWDeviceDRM::Flush(HWLayers *hw_layers) {
   ClearSolidfillStages();
   ResetROI();
-  int ret = NullCommit(secure_display_active_ /* synchronous */, false /* retain_planes*/);
+  bool sync_commit = (tui_state_ == kTUIStateStart || tui_state_ == kTUIStateEnd ||
+                      secure_display_active_);
+  int ret = NullCommit(sync_commit /* synchronous */, false /* retain_planes*/);
   if (ret) {
     DLOGE("failed with error %d", ret);
     return kErrorHardware;
diff --git a/sdm/libs/core/drm/hw_device_drm.h b/sdm/libs/core/drm/hw_device_drm.h
index dee925c..b826506 100644
--- a/sdm/libs/core/drm/hw_device_drm.h
+++ b/sdm/libs/core/drm/hw_device_drm.h
@@ -115,7 +115,7 @@
   virtual DisplayError SetDppsFeature(void *payload, size_t size) { return kErrorNotSupported; }
   virtual DisplayError GetDppsFeatureInfo(void *payload, size_t size) { return kErrorNotSupported; }
   virtual DisplayError TeardownConcurrentWriteback(void) { return kErrorNotSupported; }
-  virtual DisplayError HandleSecureEvent(SecureEvent secure_event, HWLayers *hw_layers) {
+  virtual DisplayError HandleSecureEvent(SecureEvent secure_event, const HWQosData &qos_data) {
     return kErrorNotSupported;
   }
   virtual DisplayError ControlIdlePowerCollapse(bool enable, bool synchronous) {
@@ -139,6 +139,13 @@
     kHWEventBlank,
   };
 
+  enum TUIState {
+    kTUIStateNone,
+    kTUIStateStart,
+    kTUIStateInProgress,
+    kTUIStateEnd,
+  };
+
   static const int kMaxStringLength = 1024;
   static const int kNumPhysicalDisplays = 2;
   static const int kMaxSysfsCommandLength = 12;
@@ -233,6 +240,7 @@
   HWMixerAttributes mixer_attributes_ = {};
   std::vector<sde_drm::DRMSolidfillStage> solid_fills_ {};
   bool secure_display_active_ = false;
+  TUIState tui_state_ = kTUIStateNone;
   uint64_t debug_dump_count_ = 0;
   bool synchronous_commit_ = false;
   uint32_t topology_control_ = 0;
diff --git a/sdm/libs/core/drm/hw_peripheral_drm.cpp b/sdm/libs/core/drm/hw_peripheral_drm.cpp
index fbce11a..acc2921 100644
--- a/sdm/libs/core/drm/hw_peripheral_drm.cpp
+++ b/sdm/libs/core/drm/hw_peripheral_drm.cpp
@@ -159,6 +159,7 @@
   SetupConcurrentWriteback(hw_layer_info, true, nullptr);
   SetIdlePCState();
   SetSelfRefreshState();
+  SetVMReqState();
 
   return HWDeviceDRM::Validate(hw_layers);
 }
@@ -172,6 +173,7 @@
 
   SetIdlePCState();
   SetSelfRefreshState();
+  SetVMReqState();
 
   DisplayError error = HWDeviceDRM::Commit(hw_layers);
   if (error != kErrorNone) {
@@ -349,12 +351,34 @@
   return kErrorNone;
 }
 
-DisplayError HWPeripheralDRM::HandleSecureEvent(SecureEvent secure_event, HWLayers *hw_layers) {
+DisplayError HWPeripheralDRM::HandleSecureEvent(SecureEvent secure_event,
+                                                const HWQosData &qos_data) {
   switch (secure_event) {
+    case kTUITransitionStart: {
+      tui_state_ = kTUIStateStart;
+      idle_pc_state_ = sde_drm::DRMIdlePCState::DISABLE;
+      if (hw_panel_info_.mode != kModeCommand) {
+        SetQOSData(qos_data);
+        SetVMReqState();
+        DisplayError err = Flush(NULL);
+        if (err != kErrorNone) {
+          return err;
+        }
+      }
+    }
+    break;
+
+    case kTUITransitionEnd: {
+      tui_state_ = kTUIStateEnd;
+      ResetPropertyCache();
+      idle_pc_state_ = sde_drm::DRMIdlePCState::ENABLE;
+    }
+    break;
+
     case kSecureDisplayStart: {
       secure_display_active_ = true;
       if (hw_panel_info_.mode != kModeCommand) {
-        DisplayError err = Flush(hw_layers);
+        DisplayError err = Flush(NULL);
         if (err != kErrorNone) {
           return err;
         }
@@ -364,7 +388,7 @@
 
     case kSecureDisplayEnd: {
       if (hw_panel_info_.mode != kModeCommand) {
-        DisplayError err = Flush(hw_layers);
+        DisplayError err = Flush(NULL);
         if (err != kErrorNone) {
           return err;
         }
@@ -736,4 +760,9 @@
   return kErrorNone;
 }
 
+void HWPeripheralDRM::ResetPropertyCache() {
+  drm_atomic_intf_->Perform(sde_drm::DRMOps::PLANES_RESET_CACHE, token_.crtc_id);
+  drm_atomic_intf_->Perform(sde_drm::DRMOps::CRTC_RESET_CACHE, token_.crtc_id);
+}
+
 }  // namespace sdm
diff --git a/sdm/libs/core/drm/hw_peripheral_drm.h b/sdm/libs/core/drm/hw_peripheral_drm.h
index 9f9d90d..ce51bf7 100644
--- a/sdm/libs/core/drm/hw_peripheral_drm.h
+++ b/sdm/libs/core/drm/hw_peripheral_drm.h
@@ -60,7 +60,7 @@
   virtual DisplayError Flush(HWLayers *hw_layers);
   virtual DisplayError SetDppsFeature(void *payload, size_t size);
   virtual DisplayError GetDppsFeatureInfo(void *payload, size_t size);
-  virtual DisplayError HandleSecureEvent(SecureEvent secure_event, HWLayers *hw_layers);
+  virtual DisplayError HandleSecureEvent(SecureEvent secure_event, const HWQosData &qos_data);
   virtual DisplayError ControlIdlePowerCollapse(bool enable, bool synchronous);
   virtual DisplayError PowerOn(const HWQosData &qos_data, shared_ptr<Fence> *release_fence);
   virtual DisplayError SetDisplayDppsAdROI(void *payload);
@@ -92,6 +92,19 @@
   }
   void CacheDestScalarData();
   void SetSelfRefreshState();
+  void SetVMReqState() {
+    if (tui_state_ == kTUIStateStart) {
+      drm_atomic_intf_->Perform(sde_drm::DRMOps::CRTC_SET_VM_REQ_STATE, token_.crtc_id,
+                                sde_drm::DRMVMRequestState::RELEASE);
+    } else if (tui_state_ == kTUIStateEnd) {
+      drm_atomic_intf_->Perform(sde_drm::DRMOps::CRTC_SET_VM_REQ_STATE, token_.crtc_id,
+                                sde_drm::DRMVMRequestState::ACQUIRE);
+    } else if (tui_state_ == kTUIStateNone) {
+      drm_atomic_intf_->Perform(sde_drm::DRMOps::CRTC_SET_VM_REQ_STATE, token_.crtc_id,
+                                sde_drm::DRMVMRequestState::NONE);
+    }
+  }
+  void ResetPropertyCache();
 
   struct DestScalarCache {
     SDEScaler scalar_data = {};
diff --git a/sdm/libs/core/hw_interface.h b/sdm/libs/core/hw_interface.h
index 15e3c92..67ea174 100644
--- a/sdm/libs/core/hw_interface.h
+++ b/sdm/libs/core/hw_interface.h
@@ -118,7 +118,7 @@
   virtual DisplayError DumpDebugData() = 0;
   virtual DisplayError SetDppsFeature(void *payload, size_t size) = 0;
   virtual DisplayError GetDppsFeatureInfo(void *payload, size_t size) = 0;
-  virtual DisplayError HandleSecureEvent(SecureEvent secure_event, HWLayers *hw_layers) = 0;
+  virtual DisplayError HandleSecureEvent(SecureEvent secure_event, const HWQosData &qos_data) = 0;
   virtual DisplayError ControlIdlePowerCollapse(bool enable, bool synchronous) = 0;
   virtual DisplayError SetDisplayDppsAdROI(void *payload) = 0;
   virtual DisplayError SetDynamicDSIClock(uint64_t bit_clk_rate) = 0;