Merge "sdm: Add support to handle idle power collapse event"
diff --git a/sdm/include/private/resource_interface.h b/sdm/include/private/resource_interface.h
index 48b7a02..e32af41 100644
--- a/sdm/include/private/resource_interface.h
+++ b/sdm/include/private/resource_interface.h
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2015 - 2016, The Linux Foundation. All rights reserved.
+* Copyright (c) 2015 - 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:
@@ -32,6 +32,11 @@
 
 class ResourceInterface {
  public:
+  enum ResourceCmd {
+    kCmdResetScalarLUT,
+    kCmdMax,
+  };
+
   virtual DisplayError RegisterDisplay(DisplayType type,
                                        const HWDisplayAttributes &display_attributes,
                                        const HWPanelInfo &hw_panel_info,
@@ -61,6 +66,7 @@
   virtual DisplayError GetScaleLutConfig(HWScaleLutInfo *lut_info) = 0;
   virtual DisplayError SetDetailEnhancerData(Handle display_ctx,
                                              const DisplayDetailEnhancerData &de_data) = 0;
+  virtual DisplayError Perform(int cmd, ...) = 0;
 
  protected:
   virtual ~ResourceInterface() { }
diff --git a/sdm/libs/core/comp_manager.cpp b/sdm/libs/core/comp_manager.cpp
index b070c41..93fdbea 100644
--- a/sdm/libs/core/comp_manager.cpp
+++ b/sdm/libs/core/comp_manager.cpp
@@ -423,6 +423,18 @@
   }
 }
 
+void CompManager::ProcessIdlePowerCollapse(Handle display_ctx) {
+  SCOPE_LOCK(locker_);
+
+  DisplayCompositionContext *display_comp_ctx =
+          reinterpret_cast<DisplayCompositionContext *>(display_ctx);
+
+  if (display_comp_ctx) {
+    resource_intf_->Perform(ResourceInterface::kCmdResetScalarLUT,
+                            display_comp_ctx->display_resource_ctx);
+  }
+}
+
 DisplayError CompManager::SetMaxMixerStages(Handle display_ctx, uint32_t max_mixer_stages) {
   SCOPE_LOCK(locker_);
 
diff --git a/sdm/libs/core/comp_manager.h b/sdm/libs/core/comp_manager.h
index 3713971..2c1a258 100644
--- a/sdm/libs/core/comp_manager.h
+++ b/sdm/libs/core/comp_manager.h
@@ -61,6 +61,7 @@
   void Purge(Handle display_ctx);
   void ProcessIdleTimeout(Handle display_ctx);
   void ProcessThermalEvent(Handle display_ctx, int64_t thermal_level);
+  void ProcessIdlePowerCollapse(Handle display_ctx);
   DisplayError SetMaxMixerStages(Handle display_ctx, uint32_t max_mixer_stages);
   void ControlPartialUpdate(Handle display_ctx, bool enable);
   DisplayError ValidateScaling(const LayerRect &crop, const LayerRect &dst, bool rotate90);
diff --git a/sdm/libs/core/display_hdmi.h b/sdm/libs/core/display_hdmi.h
index 6db2304..f3e64bc 100644
--- a/sdm/libs/core/display_hdmi.h
+++ b/sdm/libs/core/display_hdmi.h
@@ -53,6 +53,7 @@
   virtual void IdleTimeout() { }
   virtual void ThermalEvent(int64_t thermal_level) { }
   virtual void CECMessage(char *message);
+  virtual void IdlePowerCollapse() { }
 
  private:
   uint32_t GetBestConfig(HWS3DMode s3d_mode);
diff --git a/sdm/libs/core/display_primary.cpp b/sdm/libs/core/display_primary.cpp
index 409d659..09e0c22 100644
--- a/sdm/libs/core/display_primary.cpp
+++ b/sdm/libs/core/display_primary.cpp
@@ -295,6 +295,11 @@
   comp_manager_->ProcessThermalEvent(display_comp_ctx_, thermal_level);
 }
 
+void DisplayPrimary::IdlePowerCollapse() {
+  lock_guard<recursive_mutex> obj(recursive_mutex_);
+  comp_manager_->ProcessIdlePowerCollapse(display_comp_ctx_);
+}
+
 DisplayError DisplayPrimary::GetPanelBrightness(int *level) {
   lock_guard<recursive_mutex> obj(recursive_mutex_);
   return hw_intf_->GetPanelBrightness(level);
diff --git a/sdm/libs/core/display_primary.h b/sdm/libs/core/display_primary.h
index 70c938e..0bfef04 100644
--- a/sdm/libs/core/display_primary.h
+++ b/sdm/libs/core/display_primary.h
@@ -58,13 +58,14 @@
   virtual void IdleTimeout();
   virtual void ThermalEvent(int64_t thermal_level);
   virtual void CECMessage(char *message) { }
+  virtual void IdlePowerCollapse();
 
  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 };
+      HWEvent::SHOW_BLANK_EVENT, HWEvent::THERMAL_LEVEL, HWEvent::IDLE_POWER_COLLAPSE };
   bool avr_prop_disabled_ = false;
   bool switch_to_cmd_ = false;
 };
diff --git a/sdm/libs/core/drm/hw_events_drm.cpp b/sdm/libs/core/drm/hw_events_drm.cpp
index 81384e4..09293a9 100644
--- a/sdm/libs/core/drm/hw_events_drm.cpp
+++ b/sdm/libs/core/drm/hw_events_drm.cpp
@@ -84,6 +84,7 @@
       case HWEvent::CEC_READ_MESSAGE:
       case HWEvent::SHOW_BLANK_EVENT:
       case HWEvent::THERMAL_LEVEL:
+      case HWEvent::IDLE_POWER_COLLAPSE:
         break;
     }
   }
@@ -114,6 +115,9 @@
       case HWEvent::THERMAL_LEVEL:
         event_data.event_parser = &HWEventsDRM::HandleThermal;
         break;
+      case HWEvent::IDLE_POWER_COLLAPSE:
+        event_data.event_parser = &HWEventsDRM::HandleIdlePowerCollapse;
+        break;
       default:
         error = kErrorParameters;
         break;
@@ -188,6 +192,7 @@
       case HWEvent::CEC_READ_MESSAGE:
       case HWEvent::SHOW_BLANK_EVENT:
       case HWEvent::THERMAL_LEVEL:
+      case HWEvent::IDLE_POWER_COLLAPSE:
         break;
       default:
         return kErrorNotSupported;
@@ -239,6 +244,7 @@
         case HWEvent::CEC_READ_MESSAGE:
         case HWEvent::SHOW_BLANK_EVENT:
         case HWEvent::THERMAL_LEVEL:
+        case HWEvent::IDLE_POWER_COLLAPSE:
           if (poll_fd.fd >= 0 && (poll_fd.revents & POLLPRI) &&
               (Sys::pread_(poll_fd.fd, data, kMaxStringLength, 0) > 0)) {
             (this->*(event_data_list_[i]).event_parser)(data);
@@ -295,4 +301,8 @@
   event_handler_->CECMessage(data);
 }
 
+void HWEventsDRM::HandleIdlePowerCollapse(char *data) {
+  event_handler_->IdlePowerCollapse();
+}
+
 }  // namespace sdm
diff --git a/sdm/libs/core/drm/hw_events_drm.h b/sdm/libs/core/drm/hw_events_drm.h
index 9f8dc38..8703321 100644
--- a/sdm/libs/core/drm/hw_events_drm.h
+++ b/sdm/libs/core/drm/hw_events_drm.h
@@ -70,6 +70,7 @@
   void HandleThreadExit(char *data) {}
   void HandleThermal(char *data) {}
   void HandleBlank(char *data) {}
+  void HandleIdlePowerCollapse(char *data);
   void PopulateHWEventData(const vector<HWEvent> &event_list);
   DisplayError SetEventParser();
   DisplayError InitializePollFd();
diff --git a/sdm/libs/core/fb/hw_events.cpp b/sdm/libs/core/fb/hw_events.cpp
index ea8034f..c0467f9 100644
--- a/sdm/libs/core/fb/hw_events.cpp
+++ b/sdm/libs/core/fb/hw_events.cpp
@@ -101,6 +101,9 @@
     case HWEvent::THERMAL_LEVEL:
       event_data->event_parser = &HWEvents::HandleThermal;
       break;
+    case HWEvent::IDLE_POWER_COLLAPSE:
+      event_data->event_parser = &HWEvents::HandleIdlePowerCollapse;
+      break;
     default:
       error = kErrorParameters;
       break;
@@ -131,7 +134,8 @@
   event_thread_name_ += " - " + std::to_string(fb_num_);
   map_event_to_node_ = {{HWEvent::VSYNC, "vsync_event"}, {HWEvent::EXIT, "thread_exit"},
     {HWEvent::IDLE_NOTIFY, "idle_notify"}, {HWEvent::SHOW_BLANK_EVENT, "show_blank_event"},
-    {HWEvent::CEC_READ_MESSAGE, "cec/rd_msg"}, {HWEvent::THERMAL_LEVEL, "msm_fb_thermal_level"}};
+    {HWEvent::CEC_READ_MESSAGE, "cec/rd_msg"}, {HWEvent::THERMAL_LEVEL, "msm_fb_thermal_level"},
+    {HWEvent::IDLE_POWER_COLLAPSE, "idle_power_collapse"}};
 
   PopulateHWEventData();
 
@@ -234,4 +238,8 @@
   event_handler_->CECMessage(data);
 }
 
+void HWEvents::HandleIdlePowerCollapse(char *data) {
+  event_handler_->IdlePowerCollapse();
+}
+
 }  // namespace sdm
diff --git a/sdm/libs/core/fb/hw_events.h b/sdm/libs/core/fb/hw_events.h
index e024924..347495f 100644
--- a/sdm/libs/core/fb/hw_events.h
+++ b/sdm/libs/core/fb/hw_events.h
@@ -63,6 +63,7 @@
   void HandleThermal(char *data);
   void HandleCECMessage(char *data);
   void HandleThreadExit(char *data) { }
+  void HandleIdlePowerCollapse(char *data);
   void PopulateHWEventData();
   DisplayError SetEventParser(HWEvent event_type, HWEventData *event_data);
   pollfd InitializePollFd(HWEventData *event_data);
diff --git a/sdm/libs/core/hw_events_interface.h b/sdm/libs/core/hw_events_interface.h
index bcb7d43..e6a714c 100644
--- a/sdm/libs/core/hw_events_interface.h
+++ b/sdm/libs/core/hw_events_interface.h
@@ -41,6 +41,7 @@
   CEC_READ_MESSAGE,
   SHOW_BLANK_EVENT,
   THERMAL_LEVEL,
+  IDLE_POWER_COLLAPSE,
 };
 
 class HWEventsInterface {
diff --git a/sdm/libs/core/hw_interface.h b/sdm/libs/core/hw_interface.h
index 2e082ae..fbebb13 100644
--- a/sdm/libs/core/hw_interface.h
+++ b/sdm/libs/core/hw_interface.h
@@ -59,6 +59,7 @@
   virtual void IdleTimeout() = 0;
   virtual void ThermalEvent(int64_t thermal_level) = 0;
   virtual void CECMessage(char *message) = 0;
+  virtual void IdlePowerCollapse() = 0;
 
  protected:
   virtual ~HWEventHandler() { }
diff --git a/sdm/libs/core/resource_default.h b/sdm/libs/core/resource_default.h
index 9fab0d0..f835410 100644
--- a/sdm/libs/core/resource_default.h
+++ b/sdm/libs/core/resource_default.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:
@@ -64,6 +64,7 @@
   DisplayError SetMaxBandwidthMode(HWBwModes mode);
   virtual DisplayError SetDetailEnhancerData(Handle display_ctx,
                                              const DisplayDetailEnhancerData &de_data);
+  virtual DisplayError Perform(int cmd, ...) { return kErrorNone; }
 
  private:
   enum PipeOwner {