sdm: Change idle fallback time dynamically.

- Query composition manager for an optimal
  idle time for the current draw cycle.
- Avoid setting same idle time again on sysfs.

CRs-Fixed: 2011276
Change-Id: I4afde21ad630953d5f701fb3d123435028bdfef2
diff --git a/sdm/include/core/display_interface.h b/sdm/include/core/display_interface.h
index 1b95b91..438a85b 100644
--- a/sdm/include/core/display_interface.h
+++ b/sdm/include/core/display_interface.h
@@ -405,11 +405,11 @@
 
   /*! @brief Method to set idle timeout value. Idle fallback is disabled with timeout value 0.
 
-    @param[in] timeout value in milliseconds.
+    @param[in] active_ms value in milliseconds.
 
     @return \link void \endlink
   */
-  virtual void SetIdleTimeoutMs(uint32_t timeout_ms) = 0;
+  virtual void SetIdleTimeoutMs(uint32_t active_ms) = 0;
 
   /*! @brief Method to set maximum number of mixer stages for each display.
 
diff --git a/sdm/include/private/hw_info_types.h b/sdm/include/private/hw_info_types.h
index 34c92df..3ccf454 100644
--- a/sdm/include/private/hw_info_types.h
+++ b/sdm/include/private/hw_info_types.h
@@ -469,7 +469,9 @@
                                         // be programmed on hardware.
   uint32_t roi_index[kMaxSDELayers] = {0};  // Stores the ROI index where the layers are visible.
 
-  int sync_handle = -1;
+  int sync_handle = -1;         // Release fence id for current draw cycle.
+  int set_idle_time_ms = -1;    // Set idle time to the new specified value.
+                                //    -1 indicates no change in idle time since last set value.
 
   std::vector<LayerRect> left_frame_roi = {};   // Left ROI.
   std::vector<LayerRect> right_frame_roi = {};  // Right ROI.
diff --git a/sdm/include/private/strategy_interface.h b/sdm/include/private/strategy_interface.h
index 90e1064..6aec9cf 100644
--- a/sdm/include/private/strategy_interface.h
+++ b/sdm/include/private/strategy_interface.h
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2014 - 2016, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014 - 2017, The Linux Foundation. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification, are permitted
 * provided that the following conditions are met:
@@ -54,6 +54,7 @@
                                    const DisplayConfigVariableInfo &fb_config) = 0;
   virtual DisplayError SetCompositionState(LayerComposition composition_type, bool enable) = 0;
   virtual DisplayError Purge() = 0;
+  virtual DisplayError SetIdleTimeoutMs(uint32_t active_ms) = 0;
 
  protected:
   virtual ~StrategyInterface() { }
diff --git a/sdm/include/utils/constants.h b/sdm/include/utils/constants.h
index 72b1bed..5efe357 100644
--- a/sdm/include/utils/constants.h
+++ b/sdm/include/utils/constants.h
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2014 - 2016, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014 - 2017, The Linux Foundation. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification, are permitted
 * provided that the following conditions are met:
@@ -48,6 +48,8 @@
 #define ROUND_UP_ALIGN_UP(value, a) FLOAT(CeilToMultipleOf(UINT32(value + 0.5f), UINT32(a)))
 
 #define IDLE_TIMEOUT_DEFAULT_MS 70
+#define IDLE_TIMEOUT_ACTIVE_MS IDLE_TIMEOUT_DEFAULT_MS
+#define IDLE_TIMEOUT_INACTIVE_MS 520
 
 #define IS_RGB_FORMAT(format) (((format) < kFormatYCbCr420Planar) ? true: false)
 
diff --git a/sdm/include/utils/debug.h b/sdm/include/utils/debug.h
index 540a25e..21805ee 100644
--- a/sdm/include/utils/debug.h
+++ b/sdm/include/utils/debug.h
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2014 - 2016, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014 - 2017, The Linux Foundation. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
@@ -64,7 +64,7 @@
   static inline DebugHandler* Get() { return debug_.debug_handler_; }
   static int GetSimulationFlag();
   static int GetHDMIResolution();
-  static uint32_t GetIdleTimeoutMs();
+  static void GetIdleTimeoutMs(uint32_t *active_ms, uint32_t *inactive_ms);
   static int GetBootAnimLayerCount();
   static bool IsRotatorDownScaleDisabled();
   static bool IsDecimationDisabled();
diff --git a/sdm/libs/core/comp_manager.cpp b/sdm/libs/core/comp_manager.cpp
index b070c41..7a9c293 100644
--- a/sdm/libs/core/comp_manager.cpp
+++ b/sdm/libs/core/comp_manager.cpp
@@ -397,6 +397,15 @@
   display_comp_ctx->strategy->Purge();
 }
 
+DisplayError CompManager::SetIdleTimeoutMs(Handle display_ctx, uint32_t active_ms) {
+  SCOPE_LOCK(locker_);
+
+  DisplayCompositionContext *display_comp_ctx =
+                             reinterpret_cast<DisplayCompositionContext *>(display_ctx);
+
+  return display_comp_ctx->strategy->SetIdleTimeoutMs(active_ms);
+}
+
 void CompManager::ProcessIdleTimeout(Handle display_ctx) {
   SCOPE_LOCK(locker_);
 
@@ -506,21 +515,6 @@
   return resource_intf_->SetMaxBandwidthMode(mode);
 }
 
-bool CompManager::CanSetIdleTimeout(Handle display_ctx) {
-  DisplayCompositionContext *display_comp_ctx =
-                             reinterpret_cast<DisplayCompositionContext *>(display_ctx);
-
-  if (!display_comp_ctx) {
-    return false;
-  }
-
-  if (!display_comp_ctx->idle_fallback) {
-    return true;
-  }
-
-  return false;
-}
-
 DisplayError CompManager::GetScaleLutConfig(HWScaleLutInfo *lut_info) {
   return resource_intf_->GetScaleLutConfig(lut_info);
 }
diff --git a/sdm/libs/core/comp_manager.h b/sdm/libs/core/comp_manager.h
index 3713971..11a4654 100644
--- a/sdm/libs/core/comp_manager.h
+++ b/sdm/libs/core/comp_manager.h
@@ -59,6 +59,7 @@
   DisplayError ReConfigure(Handle display_ctx, HWLayers *hw_layers);
   DisplayError PostCommit(Handle display_ctx, HWLayers *hw_layers);
   void Purge(Handle display_ctx);
+  DisplayError SetIdleTimeoutMs(Handle display_ctx, uint32_t active_ms);
   void ProcessIdleTimeout(Handle display_ctx);
   void ProcessThermalEvent(Handle display_ctx, int64_t thermal_level);
   DisplayError SetMaxMixerStages(Handle display_ctx, uint32_t max_mixer_stages);
@@ -66,7 +67,6 @@
   DisplayError ValidateScaling(const LayerRect &crop, const LayerRect &dst, bool rotate90);
   DisplayError ValidateCursorPosition(Handle display_ctx, HWLayers *hw_layers, int x, int y);
   bool SupportLayerAsCursor(Handle display_ctx, HWLayers *hw_layers);
-  bool CanSetIdleTimeout(Handle display_ctx);
   bool SetDisplayState(Handle display_ctx, DisplayState state, DisplayType display_type);
   DisplayError SetMaxBandwidthMode(HWBwModes mode);
   DisplayError GetScaleLutConfig(HWScaleLutInfo *lut_info);
diff --git a/sdm/libs/core/display_base.h b/sdm/libs/core/display_base.h
index 64f8ab7..3b8a1f3 100644
--- a/sdm/libs/core/display_base.h
+++ b/sdm/libs/core/display_base.h
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2014-2016, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014-2017, The Linux Foundation. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification, are permitted
 * provided that the following conditions are met:
@@ -99,7 +99,7 @@
     return kErrorNotSupported;
   }
   virtual DisplayError SetVSyncState(bool enable);
-  virtual void SetIdleTimeoutMs(uint32_t timeout_ms) {}
+  virtual void SetIdleTimeoutMs(uint32_t active_ms) {}
   virtual DisplayError SetMixerResolution(uint32_t width, uint32_t height);
   virtual DisplayError GetMixerResolution(uint32_t *width, uint32_t *height);
   virtual DisplayError SetFrameBufferConfig(const DisplayConfigVariableInfo &variable_info);
diff --git a/sdm/libs/core/display_primary.cpp b/sdm/libs/core/display_primary.cpp
index 409d659..0c07266 100644
--- a/sdm/libs/core/display_primary.cpp
+++ b/sdm/libs/core/display_primary.cpp
@@ -59,8 +59,6 @@
     return error;
   }
 
-  idle_timeout_ms_ = Debug::GetIdleTimeoutMs();
-
   if (hw_panel_info_.mode == kModeCommand && Debug::IsVideoModeEnabled()) {
     error = hw_intf_->SetDisplayMode(kModeVideo);
     if (error != kErrorNone) {
@@ -145,8 +143,6 @@
     }
   }
 
-  bool set_idle_timeout = comp_manager_->CanSetIdleTimeout(display_comp_ctx_);
-
   error = DisplayBase::Commit(layer_stack);
   if (error != kErrorNone) {
     return error;
@@ -154,13 +150,12 @@
 
   DisplayBase::ReconfigureDisplay();
 
-  if (hw_panel_info_.mode == kModeVideo) {
-    if (set_idle_timeout && !layer_stack->flags.single_buffered_layer_present) {
-      hw_intf_->SetIdleTimeoutMs(idle_timeout_ms_);
-    } else {
-      hw_intf_->SetIdleTimeoutMs(0);
-    }
-  } else if (switch_to_cmd_) {
+  int idle_time_ms = hw_layers_.info.set_idle_time_ms;
+  if (idle_time_ms >= 0) {
+    hw_intf_->SetIdleTimeoutMs(UINT32(idle_time_ms));
+  }
+
+  if (switch_to_cmd_) {
     uint32_t pending;
     switch_to_cmd_ = false;
     ControlPartialUpdate(true /* enable */, &pending);
@@ -185,52 +180,58 @@
   return kErrorNone;
 }
 
-void DisplayPrimary::SetIdleTimeoutMs(uint32_t timeout_ms) {
+void DisplayPrimary::SetIdleTimeoutMs(uint32_t active_ms) {
   lock_guard<recursive_mutex> obj(recursive_mutex_);
 
-  // Idle fallback feature is supported only for video mode panel.
-  if (hw_panel_info_.mode == kModeVideo) {
-    hw_intf_->SetIdleTimeoutMs(timeout_ms);
+  if (comp_manager_->SetIdleTimeoutMs(display_comp_ctx_, active_ms) == kErrorNone) {
+    hw_intf_->SetIdleTimeoutMs(active_ms);
   }
-  idle_timeout_ms_ = timeout_ms;
 }
 
 DisplayError DisplayPrimary::SetDisplayMode(uint32_t mode) {
-  lock_guard<recursive_mutex> obj(recursive_mutex_);
   DisplayError error = kErrorNone;
-  HWDisplayMode hw_display_mode = static_cast<HWDisplayMode>(mode);
-  uint32_t pending = 0;
 
-  if (!active_) {
-    DLOGW("Invalid display state = %d. Panel must be on.", state_);
-    return kErrorNotSupported;
+  // Limit scope of mutex to this block
+  {
+    lock_guard<recursive_mutex> obj(recursive_mutex_);
+    HWDisplayMode hw_display_mode = static_cast<HWDisplayMode>(mode);
+    uint32_t pending = 0;
+
+    if (!active_) {
+      DLOGW("Invalid display state = %d. Panel must be on.", state_);
+      return kErrorNotSupported;
+    }
+
+    if (hw_display_mode != kModeCommand && hw_display_mode != kModeVideo) {
+      DLOGW("Invalid panel mode parameters. Requested = %d", hw_display_mode);
+      return kErrorParameters;
+    }
+
+    if (hw_display_mode == hw_panel_info_.mode) {
+      DLOGW("Same display mode requested. Current = %d, Requested = %d", hw_panel_info_.mode,
+            hw_display_mode);
+      return kErrorNone;
+    }
+
+    error = hw_intf_->SetDisplayMode(hw_display_mode);
+    if (error != kErrorNone) {
+      DLOGW("Retaining current display mode. Current = %d, Requested = %d", hw_panel_info_.mode,
+            hw_display_mode);
+      return error;
+    }
+
+    if (mode == kModeVideo) {
+      ControlPartialUpdate(false /* enable */, &pending);
+    } else if (mode == kModeCommand) {
+      // Flush idle timeout value currently set.
+      hw_intf_->SetIdleTimeoutMs(0);
+      switch_to_cmd_ = true;
+    }
   }
 
-  if (hw_display_mode != kModeCommand && hw_display_mode != kModeVideo) {
-    DLOGW("Invalid panel mode parameters. Requested = %d", hw_display_mode);
-    return kErrorParameters;
-  }
-
-  if (hw_display_mode == hw_panel_info_.mode) {
-    DLOGW("Same display mode requested. Current = %d, Requested = %d", hw_panel_info_.mode,
-          hw_display_mode);
-    return kErrorNone;
-  }
-
-  error = hw_intf_->SetDisplayMode(hw_display_mode);
-  if (error != kErrorNone) {
-    DLOGW("Retaining current display mode. Current = %d, Requested = %d", hw_panel_info_.mode,
-          hw_display_mode);
-    return error;
-  }
-
-  if (mode == kModeVideo) {
-    ControlPartialUpdate(false /* enable */, &pending);
-    hw_intf_->SetIdleTimeoutMs(idle_timeout_ms_);
-  } else if (mode == kModeCommand) {
-    switch_to_cmd_ = true;
-    hw_intf_->SetIdleTimeoutMs(0);
-  }
+  // Request for a new draw cycle. New display mode will get applied on next draw cycle.
+  // New idle time will get configured as part of this.
+  event_handler_->Refresh();
 
   return error;
 }
diff --git a/sdm/libs/core/display_primary.h b/sdm/libs/core/display_primary.h
index 70c938e..3e97670 100644
--- a/sdm/libs/core/display_primary.h
+++ b/sdm/libs/core/display_primary.h
@@ -45,7 +45,7 @@
   virtual DisplayError ControlPartialUpdate(bool enable, uint32_t *pending);
   virtual DisplayError DisablePartialUpdateOneFrame();
   virtual DisplayError SetDisplayState(DisplayState state);
-  virtual void SetIdleTimeoutMs(uint32_t timeout_ms);
+  virtual void SetIdleTimeoutMs(uint32_t active_ms);
   virtual DisplayError SetDisplayMode(uint32_t mode);
   virtual DisplayError GetRefreshRateRange(uint32_t *min_refresh_rate, uint32_t *max_refresh_rate);
   virtual DisplayError SetRefreshRate(uint32_t refresh_rate);
@@ -62,7 +62,6 @@
  private:
   bool NeedsAVREnable();
 
-  uint32_t idle_timeout_ms_ = 0;
   std::vector<HWEvent> event_list_ = { HWEvent::VSYNC, HWEvent::EXIT, HWEvent::IDLE_NOTIFY,
       HWEvent::SHOW_BLANK_EVENT, HWEvent::THERMAL_LEVEL };
   bool avr_prop_disabled_ = false;
diff --git a/sdm/libs/core/strategy.cpp b/sdm/libs/core/strategy.cpp
index a34c40c..8398bbd 100644
--- a/sdm/libs/core/strategy.cpp
+++ b/sdm/libs/core/strategy.cpp
@@ -254,5 +254,12 @@
   return kErrorNone;
 }
 
+DisplayError Strategy::SetIdleTimeoutMs(uint32_t active_ms) {
+  if (strategy_intf_) {
+    return strategy_intf_->SetIdleTimeoutMs(active_ms);
+  }
+
+  return kErrorNotSupported;
+}
 
 }  // namespace sdm
diff --git a/sdm/libs/core/strategy.h b/sdm/libs/core/strategy.h
index d69283f..f05f66b 100644
--- a/sdm/libs/core/strategy.h
+++ b/sdm/libs/core/strategy.h
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2014 - 2016, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014 - 2017, The Linux Foundation. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification, are permitted
 * provided that the following conditions are met:
@@ -52,6 +52,7 @@
                            const DisplayConfigVariableInfo &fb_config);
   DisplayError SetCompositionState(LayerComposition composition_type, bool enable);
   DisplayError Purge();
+  DisplayError SetIdleTimeoutMs(uint32_t active_ms);
 
  private:
   void GenerateROI();
diff --git a/sdm/libs/utils/debug.cpp b/sdm/libs/utils/debug.cpp
index fc8567a..69316b6 100644
--- a/sdm/libs/utils/debug.cpp
+++ b/sdm/libs/utils/debug.cpp
@@ -54,11 +54,15 @@
   return value;
 }
 
-uint32_t Debug::GetIdleTimeoutMs() {
-  int value = IDLE_TIMEOUT_DEFAULT_MS;
-  debug_.debug_handler_->GetProperty("sdm.idle_time", &value);
+void Debug::GetIdleTimeoutMs(uint32_t *active_ms, uint32_t *inactive_ms) {
+  int active_val = IDLE_TIMEOUT_ACTIVE_MS;
+  int inactive_val = IDLE_TIMEOUT_INACTIVE_MS;
 
-  return UINT32(value);
+  debug_.debug_handler_->GetProperty("sdm.idle_time", &active_val);
+  debug_.debug_handler_->GetProperty("sdm.idle_time.inactive", &inactive_val);
+
+  *active_ms = UINT32(active_val);
+  *inactive_ms = UINT32(inactive_val);
 }
 
 int Debug::GetBootAnimLayerCount() {