Merge "sdm: Handle idle fall back and idle power collapse with same event"
diff --git a/sdm/include/private/color_params.h b/sdm/include/private/color_params.h
index fdab206..2cfb99e 100644
--- a/sdm/include/private/color_params.h
+++ b/sdm/include/private/color_params.h
@@ -297,6 +297,7 @@
   static const int kGamutTableNum = 4;
   static const int kGamutScaleoffTableNum = 3;
   static const int kGamutTableSize = 1229;
+  static const int kGamutTableCoarse13Size = 550;
   static const int kGamutTableCoarseSize = 32;
   static const int kGamutScaleoffSize = 16;
   uint32_t mode;
diff --git a/sdm/include/private/hw_info_types.h b/sdm/include/private/hw_info_types.h
index 5d19952..b6c4690 100644
--- a/sdm/include/private/hw_info_types.h
+++ b/sdm/include/private/hw_info_types.h
@@ -109,6 +109,19 @@
   kOneShotMode,     // Mode to enable AVR feature for particular frame.
 };
 
+enum HWTopology {
+  kUnknown,
+  kSingleLM,
+  kSingleLMDSC,
+  kDualLM,
+  kDualLMDSC,
+  kDualLMMerge,
+  kDualLMMergeDSC,
+  kDualLMDSCMerge,
+  kPPSplit,
+};
+
+
 typedef std::map<HWSubBlockType, std::vector<LayerBufferFormat>> FormatsMap;
 typedef std::map<LayerBufferFormat, float> CompRatioMap;
 
@@ -557,6 +570,8 @@
   uint32_t h_total = 0;        //!< Total width of panel (hActive + hFP + hBP + hPulseWidth)
   uint32_t v_total = 0;        //!< Total height of panel (vActive + vFP + vBP + vPulseWidth)
   std::bitset<32> s3d_config;  //!< Stores the bit mask of S3D modes
+  uint32_t clock_khz = 0;      //!< Stores the pixel clock of panel in khz
+  HWTopology topology = kUnknown;  //!< Stores the topology information.
 
   void Reset() { *this = HWDisplayAttributes(); }
 
@@ -572,7 +587,10 @@
             (v_back_porch != display_attributes.v_back_porch) ||
             (v_pulse_width != display_attributes.v_pulse_width) ||
             (h_total != display_attributes.h_total) ||
-            (is_yuv != display_attributes.is_yuv));
+            (is_yuv != display_attributes.is_yuv) ||
+            (s3d_config != display_attributes.s3d_config) ||
+            (clock_khz != display_attributes.clock_khz) ||
+            (topology != display_attributes.topology));
   }
 
   bool operator ==(const HWDisplayAttributes &display_attributes) {
diff --git a/sdm/libs/core/drm/hw_device_drm.cpp b/sdm/libs/core/drm/hw_device_drm.cpp
index 8ee52ba..bd09a38 100644
--- a/sdm/libs/core/drm/hw_device_drm.cpp
+++ b/sdm/libs/core/drm/hw_device_drm.cpp
@@ -411,7 +411,6 @@
   uint32_t mm_width = 0;
   uint32_t mm_height = 0;
   DRMTopology topology = DRMTopology::SINGLE_LM;
-  bool dual_display = false;
 
   if (default_mode_) {
     DRMResMgr *res_mgr = nullptr;
@@ -451,14 +450,11 @@
   display_attributes_[index].v_back_porch = mode.vtotal - mode.vsync_end;
   display_attributes_[index].v_total = mode.vtotal;
   display_attributes_[index].h_total = mode.htotal;
-  uint32_t h_blanking = mode.htotal - mode.hdisplay;
   display_attributes_[index].is_device_split =
       (topology == DRMTopology::DUAL_LM || topology == DRMTopology::DUAL_LM_MERGE ||
        topology == DRMTopology::DUAL_LM_MERGE_DSC || topology == DRMTopology::DUAL_LM_DSC ||
        topology == DRMTopology::DUAL_LM_DSCMERGE);
-  dual_display = (topology == DRMTopology::DUAL_LM || topology == DRMTopology::DUAL_LM_DSC ||
-       topology == DRMTopology::PPSPLIT);
-  display_attributes_[index].h_total += dual_display ? h_blanking : 0;
+  display_attributes_[index].clock_khz = mode.clock;
 
   // If driver doesn't return panel width/height information, default to 320 dpi
   if (INT(mm_width) <= 0 || INT(mm_height) <= 0) {
@@ -469,15 +465,17 @@
 
   display_attributes_[index].x_dpi = (FLOAT(mode.hdisplay) * 25.4f) / FLOAT(mm_width);
   display_attributes_[index].y_dpi = (FLOAT(mode.vdisplay) * 25.4f) / FLOAT(mm_height);
+  SetTopology(topology, &display_attributes_[index].topology);
 
   DLOGI("Display attributes[%d]: WxH: %dx%d, DPI: %fx%f, FPS: %d, LM_SPLIT: %d, V_BACK_PORCH: %d," \
-        " V_FRONT_PORCH: %d, V_PULSE_WIDTH: %d, V_TOTAL: %d, H_TOTAL: %d, TOPOLOGY: %d", index,
-        display_attributes_[index].x_pixels, display_attributes_[index].y_pixels,
+        " V_FRONT_PORCH: %d, V_PULSE_WIDTH: %d, V_TOTAL: %d, H_TOTAL: %d, CLK: %dKHZ, TOPOLOGY: %d",
+        index, display_attributes_[index].x_pixels, display_attributes_[index].y_pixels,
         display_attributes_[index].x_dpi, display_attributes_[index].y_dpi,
         display_attributes_[index].fps, display_attributes_[index].is_device_split,
         display_attributes_[index].v_back_porch, display_attributes_[index].v_front_porch,
         display_attributes_[index].v_pulse_width, display_attributes_[index].v_total,
-        display_attributes_[index].h_total, topology);
+        display_attributes_[index].h_total, display_attributes_[index].clock_khz,
+        display_attributes_[index].topology);
 
   return kErrorNone;
 }
@@ -1395,4 +1393,18 @@
   }
 }
 
+void HWDeviceDRM::SetTopology(sde_drm::DRMTopology drm_topology, HWTopology *hw_topology) {
+  switch (drm_topology) {
+    case DRMTopology::SINGLE_LM:          *hw_topology = kSingleLM;        break;
+    case DRMTopology::SINGLE_LM_DSC:      *hw_topology = kSingleLMDSC;     break;
+    case DRMTopology::DUAL_LM:            *hw_topology = kDualLM;          break;
+    case DRMTopology::DUAL_LM_DSC:        *hw_topology = kDualLMDSC;       break;
+    case DRMTopology::DUAL_LM_MERGE:      *hw_topology = kDualLMMerge;     break;
+    case DRMTopology::DUAL_LM_MERGE_DSC:  *hw_topology = kDualLMMergeDSC;  break;
+    case DRMTopology::DUAL_LM_DSCMERGE:   *hw_topology = kDualLMDSCMerge;  break;
+    case DRMTopology::PPSPLIT:            *hw_topology = kPPSplit;         break;
+    default:                              *hw_topology = kUnknown;         break;
+  }
+}
+
 }  // namespace sdm
diff --git a/sdm/libs/core/drm/hw_device_drm.h b/sdm/libs/core/drm/hw_device_drm.h
index 883d605..cc17668 100644
--- a/sdm/libs/core/drm/hw_device_drm.h
+++ b/sdm/libs/core/drm/hw_device_drm.h
@@ -133,6 +133,7 @@
                        sde_drm::DRMSecurityLevel *security_level);
   bool IsResolutionSwitchEnabled() const { return resolution_switch_enabled_; }
   void UpdatePanelSplitInfo();
+  void SetTopology(sde_drm::DRMTopology drm_topology, HWTopology *hw_topology);
 
   class Registry {
    public:
diff --git a/sdm/libs/core/drm/hw_info_drm.cpp b/sdm/libs/core/drm/hw_info_drm.cpp
index 445974f..1ce77b6 100644
--- a/sdm/libs/core/drm/hw_info_drm.cpp
+++ b/sdm/libs/core/drm/hw_info_drm.cpp
@@ -400,7 +400,7 @@
 void HWInfoDRM::PopulateSupportedFmts(HWSubBlockType sub_blk_type,
                                       const sde_drm::DRMPlaneTypeInfo  &info,
                                       HWResourceInfo *hw_resource) {
-  vector<LayerBufferFormat> sdm_formats = {};
+  vector<LayerBufferFormat> sdm_formats;
   FormatsMap &fmts_map = hw_resource->supported_formats_map;
 
   if (fmts_map.find(sub_blk_type) == fmts_map.end()) {
@@ -414,7 +414,7 @@
 
 void HWInfoDRM::GetWBInfo(HWResourceInfo *hw_resource) {
   HWSubBlockType sub_blk_type = kHWWBIntfOutput;
-  vector<LayerBufferFormat> supported_sdm_formats = {};
+  vector<LayerBufferFormat> supported_sdm_formats;
   sde_drm::DRMDisplayToken token;
 
   // Fake register