hwc: Add layer mixer count

Count how many layer mixers are being used. When DP is connected,
make sure we have enough mixers to handle DP.

Change-Id: Ie40e24cc252c6f032330ac4827088ff0afa2511a
diff --git a/composer/display_null.h b/composer/display_null.h
index 3a0774e..0bd8e10 100644
--- a/composer/display_null.h
+++ b/composer/display_null.h
@@ -81,6 +81,7 @@
   virtual bool IsWriteBackSupportedFormat(const LayerBufferFormat &format) { return false; }
   virtual bool HandleCwbTeardown() { return false; }
   virtual void Abort() {};
+  virtual uint32_t GetAvailableMixerCount() { return 0; }
 
   MAKE_NO_OP(CommitOrPrepare(LayerStack *))
   MAKE_NO_OP(PrePrepare(LayerStack *))
diff --git a/composer/hwc_display.cpp b/composer/hwc_display.cpp
index 68eb399..fdffa4c 100644
--- a/composer/hwc_display.cpp
+++ b/composer/hwc_display.cpp
@@ -2238,6 +2238,10 @@
   return display_intf_->GetMixerResolution(x_pixels, y_pixels);
 }
 
+uint32_t HWCDisplay::GetAvailableMixerCount() {
+  return display_intf_->GetAvailableMixerCount();
+}
+
 void HWCDisplay::GetPanelResolution(uint32_t *x_pixels, uint32_t *y_pixels) {
   DisplayConfigVariableInfo display_config;
   uint32_t active_index = 0;
diff --git a/composer/hwc_display.h b/composer/hwc_display.h
index ca7de82..468ae5e 100644
--- a/composer/hwc_display.h
+++ b/composer/hwc_display.h
@@ -252,6 +252,7 @@
   virtual int GetActiveSecureSession(std::bitset<kSecureMax> *secure_sessions) { return 0; };
   virtual DisplayError SetMixerResolution(uint32_t width, uint32_t height);
   virtual DisplayError GetMixerResolution(uint32_t *width, uint32_t *height);
+  virtual uint32_t GetAvailableMixerCount();
   virtual void GetPanelResolution(uint32_t *width, uint32_t *height);
   virtual void GetRealPanelResolution(uint32_t *width, uint32_t *height);
   virtual void Dump(std::ostringstream *os);
diff --git a/composer/hwc_session.cpp b/composer/hwc_session.cpp
index e858d86..ae94e25 100644
--- a/composer/hwc_session.cpp
+++ b/composer/hwc_session.cpp
@@ -3074,14 +3074,16 @@
     DLOGW("Skipped pluggable display handling in null-display mode");
     return 0;
   }
-  hwc2_display_t virtual_display_index =
-      (hwc2_display_t)GetDisplayIndex(qdutils::DISPLAY_VIRTUAL);
+
+  hwc2_display_t virtual_display_index = (hwc2_display_t)GetDisplayIndex(qdutils::DISPLAY_VIRTUAL);
   std::bitset<kSecureMax> secure_sessions = 0;
+
   hwc2_display_t active_builtin_disp_id = GetActiveBuiltinDisplay();
   if (active_builtin_disp_id < HWCCallbacks::kNumDisplays) {
     Locker::ScopeLock lock_a(locker_[active_builtin_disp_id]);
     hwc_display_[active_builtin_disp_id]->GetActiveSecureSession(&secure_sessions);
   }
+
   if (secure_sessions.any() || hwc_display_[virtual_display_index]) {
     // Defer hotplug handling.
     DLOGI("Marking hotplug pending...");
@@ -3133,6 +3135,19 @@
   std::vector<hwc2_display_t> pending_hotplugs = {};
   hwc2_display_t client_id = 0;
 
+  static constexpr uint32_t min_mixer_count = 2;
+  uint32_t available_mixer_count = 0;
+  hwc2_display_t active_builtin = GetActiveBuiltinDisplay();
+
+  if (active_builtin < HWCCallbacks::kNumDisplays) {
+    Locker::ScopeLock lock_a(locker_[active_builtin]);
+    available_mixer_count = hwc_display_[active_builtin]->GetAvailableMixerCount();
+  }
+
+  if (available_mixer_count < min_mixer_count) {
+    return -EAGAIN;
+  }
+
   for (auto &iter : *hw_displays_info) {
     auto &info = iter.second;
 
diff --git a/libdrmutils/drm_interface.h b/libdrmutils/drm_interface.h
index ca79d4c..3bfdd32 100644
--- a/libdrmutils/drm_interface.h
+++ b/libdrmutils/drm_interface.h
@@ -1405,6 +1405,13 @@
   * [output]: List of plane ids that were used for Demura
   */
   virtual void GetInitialDemuraInfo(std::vector<uint32_t> *initial_demura_planes) = 0;
+
+  /*
+  * Get the total number of crtc supported
+  * [return]: crtc count
+  */
+  virtual uint32_t GetCrtcCount() = 0;
+
 };
 
 }  // namespace sde_drm
diff --git a/sde-drm/drm_crtc.cpp b/sde-drm/drm_crtc.cpp
index 5cf7f02..ab66b7f 100644
--- a/sde-drm/drm_crtc.cpp
+++ b/sde-drm/drm_crtc.cpp
@@ -1019,4 +1019,8 @@
   tmp_prop_val_map_.erase(prop_mgr_.GetPropertyId(DRMProperty::DRAM_IB));
 }
 
+uint32_t DRMCrtcManager::GetCrtcCount() {
+  return crtc_pool_.size();
+}
+
 }  // namespace sde_drm
diff --git a/sde-drm/drm_crtc.h b/sde-drm/drm_crtc.h
index 09fb1bd..b59feb4 100644
--- a/sde-drm/drm_crtc.h
+++ b/sde-drm/drm_crtc.h
@@ -123,6 +123,7 @@
   void PostValidate(uint32_t crtc_id, bool success);
   void PostCommit(uint32_t crtc_id, bool success);
   void GetCrtcList(std::vector<uint32_t> *crtc_ids);
+  uint32_t GetCrtcCount();
 
  private:
   int fd_ = -1;
diff --git a/sde-drm/drm_manager.cpp b/sde-drm/drm_manager.cpp
index 04a4b15..5907728 100644
--- a/sde-drm/drm_manager.cpp
+++ b/sde-drm/drm_manager.cpp
@@ -499,4 +499,9 @@
     plane_mgr_->GetPlaneIdsFromDescriptions(frl, initial_demura_planes);
   }
 }
+
+uint32_t DRMManager::GetCrtcCount() {
+  return crtc_mgr_->GetCrtcCount();
+}
+
 }  // namespace sde_drm
diff --git a/sde-drm/drm_manager.h b/sde-drm/drm_manager.h
index 850c594..bc349ba 100644
--- a/sde-drm/drm_manager.h
+++ b/sde-drm/drm_manager.h
@@ -72,6 +72,7 @@
   virtual void GetInitialDemuraInfo(std::vector<uint32_t> *initial_demura_planes);
   virtual void MarkPanelFeatureForNullCommit(const DRMDisplayToken &token,
                                              const DRMPanelFeatureID &id);
+  virtual uint32_t GetCrtcCount();
 
   DRMPlaneManager *GetPlaneMgr();
   DRMConnectorManager *GetConnectorMgr();
diff --git a/sdm/include/core/display_interface.h b/sdm/include/core/display_interface.h
index 35ce5c8..d94038b 100644
--- a/sdm/include/core/display_interface.h
+++ b/sdm/include/core/display_interface.h
@@ -1314,8 +1314,18 @@
   */
   virtual DisplayError GetPanelFeatureInfo(PanelFeatureInfo *info) = 0;
 
+  /*! @brief Method to Abort DP connection
+
+    @return \link void \endlink
+  */
   virtual void Abort() = 0;
 
+  /*! @brief Method to Get the free mixer count
+
+    @return \link free mixer count \endlink
+  */
+  virtual uint32_t GetAvailableMixerCount() = 0;
+
  protected:
   virtual ~DisplayInterface() { }
 };
diff --git a/sdm/include/private/hw_info_interface.h b/sdm/include/private/hw_info_interface.h
index 0a17d6f..905ca04 100644
--- a/sdm/include/private/hw_info_interface.h
+++ b/sdm/include/private/hw_info_interface.h
@@ -50,6 +50,8 @@
                        std::map<uint32_t, uint8_t> *required_demura_fetch_cnt) = 0;
   virtual DisplayError GetDemuraPanelIds(std::vector<uint64_t> *panel_ids) = 0;
   virtual DisplayError GetPanelBootParamString(std::string *panel_boot_param_string) = 0;
+  virtual uint32_t GetMaxMixerCount() = 0;
+
  protected:
   static int32_t ref_count_;
   static HWInfoInterface *intf_;
diff --git a/sdm/include/private/resource_interface.h b/sdm/include/private/resource_interface.h
index 00f69bf..7bc004f 100644
--- a/sdm/include/private/resource_interface.h
+++ b/sdm/include/private/resource_interface.h
@@ -139,6 +139,7 @@
   virtual bool HandleCwbTeardown(Handle display_ctx) = 0;
   virtual void HandleSkipValidate(Handle display_ctx) = 0;
   virtual std::string Dump() = 0;
+  virtual uint32_t GetMixerCount() = 0;
 };
 
 }  // namespace sdm
diff --git a/sdm/libs/core/comp_manager.cpp b/sdm/libs/core/comp_manager.cpp
index b6e3168..8dbda9b 100644
--- a/sdm/libs/core/comp_manager.cpp
+++ b/sdm/libs/core/comp_manager.cpp
@@ -1004,4 +1004,10 @@
   return resource_intf_->HandleCwbTeardown(display_comp_ctx->display_resource_ctx);
 }
 
+uint32_t CompManager::GetMixerCount() {
+  std::lock_guard<std::recursive_mutex> obj(comp_mgr_mutex_);
+
+  return resource_intf_->GetMixerCount();
+}
+
 }  // namespace sdm
diff --git a/sdm/libs/core/comp_manager.h b/sdm/libs/core/comp_manager.h
index b040ce0..bcc14aa 100644
--- a/sdm/libs/core/comp_manager.h
+++ b/sdm/libs/core/comp_manager.h
@@ -161,6 +161,7 @@
   virtual void NotifyCwbDone(int32_t display_id, int32_t status, const LayerBuffer& buffer);
   virtual void TriggerRefresh(int32_t display_id);
   std::string Dump();
+  uint32_t GetMixerCount();
 
  private:
   static const int kMaxThermalLevel = 3;
diff --git a/sdm/libs/core/display_base.cpp b/sdm/libs/core/display_base.cpp
index 7d84bf9..ea1cccf 100644
--- a/sdm/libs/core/display_base.cpp
+++ b/sdm/libs/core/display_base.cpp
@@ -4295,4 +4295,17 @@
   return comp_manager_->HandleCwbTeardown(display_comp_ctx_);
 }
 
+uint32_t DisplayBase::GetAvailableMixerCount() {
+  uint32_t max_count = hw_info_intf_->GetMaxMixerCount();
+  uint32_t cur_count = comp_manager_->GetMixerCount();
+
+  DLOGV("max mixer count: %d, currently used: %d", max_count, cur_count);
+  if (!max_count || max_count < cur_count) {
+    DLOGW("invalid mixer count, returing max");
+    return 0xff;
+  }
+
+  return max_count - cur_count;
+}
+
 }  // namespace sdm
diff --git a/sdm/libs/core/display_base.h b/sdm/libs/core/display_base.h
index b1df265..1161076 100644
--- a/sdm/libs/core/display_base.h
+++ b/sdm/libs/core/display_base.h
@@ -245,6 +245,7 @@
   virtual void NotifyCwbDone(int32_t status, const LayerBuffer& buffer);
   virtual void Refresh();
   virtual bool HandleCwbTeardown();
+  virtual uint32_t GetAvailableMixerCount();
 
  protected:
   struct DisplayMutex {
diff --git a/sdm/libs/core/resource_default.cpp b/sdm/libs/core/resource_default.cpp
index 669de13..686820a 100644
--- a/sdm/libs/core/resource_default.cpp
+++ b/sdm/libs/core/resource_default.cpp
@@ -388,6 +388,10 @@
   return "";
 }
 
+uint32_t ResourceDefault::GetMixerCount() {
+  return 0;
+}
+
 DisplayError ResourceDefault::PostCommit(Handle display_ctx, DispLayerStack *disp_layer_stack) {
   DisplayResourceContext *display_resource_ctx =
                           reinterpret_cast<DisplayResourceContext *>(display_ctx);
diff --git a/sdm/libs/core/resource_default.h b/sdm/libs/core/resource_default.h
index adf7a21..7972f66 100644
--- a/sdm/libs/core/resource_default.h
+++ b/sdm/libs/core/resource_default.h
@@ -137,6 +137,7 @@
   }
   virtual void HandleSkipValidate(Handle display_ctx);
   virtual std::string Dump();
+  virtual uint32_t GetMixerCount();
 
  private:
   enum PipeOwner {
diff --git a/sdm/libs/dal/hw_info_drm.cpp b/sdm/libs/dal/hw_info_drm.cpp
index ea1228f..cd982ae 100644
--- a/sdm/libs/dal/hw_info_drm.cpp
+++ b/sdm/libs/dal/hw_info_drm.cpp
@@ -1124,4 +1124,8 @@
   return kErrorNone;
 }
 
+uint32_t HWInfoDRM::GetMaxMixerCount() {
+  return drm_mgr_intf_->GetCrtcCount();
+}
+
 }  // namespace sdm
diff --git a/sdm/libs/dal/hw_info_drm.h b/sdm/libs/dal/hw_info_drm.h
index f1d7c89..aec622e 100644
--- a/sdm/libs/dal/hw_info_drm.h
+++ b/sdm/libs/dal/hw_info_drm.h
@@ -56,6 +56,7 @@
                        std::map<uint32_t, uint8_t> *required_demura_fetch_cnt);
   virtual DisplayError GetDemuraPanelIds(std::vector<uint64_t> *panel_ids);
   virtual DisplayError GetPanelBootParamString(std::string *panel_boot_param_string);
+  virtual uint32_t GetMaxMixerCount();
 
  private:
   void Deinit();