sdm: Add binder support to set QSync mode

Change-Id: I18c46235a4b5f79ea7636cf7ba1d00d37280e6b1
CRs-Fixed: 2197669
diff --git a/libqservice/IQService.h b/libqservice/IQService.h
index 5765b10..bbbaf3a 100644
--- a/libqservice/IQService.h
+++ b/libqservice/IQService.h
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2010 The Android Open Source Project
- * Copyright (C) 2012-2014, 2016-2017 The Linux Foundation. All rights reserved.
+ * Copyright (C) 2012-2014, 2016-2018 The Linux Foundation. All rights reserved.
  *
  * Not a Contribution, Apache license notifications and license are
  * retained for attribution purposes only.
@@ -77,6 +77,7 @@
         GET_HDR_CAPABILITIES = 35, // Get HDR capabilities for legacy HWC interface
         SET_COLOR_MODE_BY_ID = 36, // Overrides the QDCM mode using the given mode ID
         GET_COMPOSER_STATUS = 37, // Get composer init status-true if primary display init is done
+        SET_QSYNC_MODE = 38, // Set qsync mode. 0 - (none)disable qsync, 1 - continuous mode.
         COMMAND_LIST_END = 400,
     };
 
@@ -107,6 +108,12 @@
         ENABLE_PARTIAL_UPDATE,
     };
 
+    enum {
+        QSYNC_MODE_NONE,
+        QSYNC_MODE_CONTINUOUS,
+        QSYNC_MODE_ONESHOT,    // Not supported
+    };
+
     // 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/sdm/include/core/display_interface.h b/sdm/include/core/display_interface.h
index eca709a..a82b562 100644
--- a/sdm/include/core/display_interface.h
+++ b/sdm/include/core/display_interface.h
@@ -151,6 +151,13 @@
   kSecureEventMax,
 };
 
+/*! @brief This enum represents the QSync modes supported by the hardware. */
+enum QSyncMode {
+  kQSyncModeNone,        // This is set by the client to disable qsync
+  kQSyncModeContinuous,  // This is set by the client to enable qsync forever
+  kQsyncModeOneShot,     // This is set by client to enable qsync only for current frame.
+};
+
 /*! @brief This structure defines configuration for fixed properties of a display device.
 
   @sa DisplayInterface::GetConfig
@@ -708,6 +715,14 @@
   */
   virtual DisplayError HandleSecureEvent(SecureEvent secure_event) = 0;
 
+  /*! @brief Method to set the Qsync mode.
+
+  @param[in] qsync_mode: \link QSyncMode \endlink
+
+  @return \link DisplayError \endlink
+  */
+  virtual DisplayError SetQSyncMode(QSyncMode qsync_mode) = 0;
+
   /*
    * Returns a string consisting of a dump of SDM's display and layer related state
    * as programmed to driver
diff --git a/sdm/libs/core/display_base.h b/sdm/libs/core/display_base.h
index ca873b0..74d203e 100644
--- a/sdm/libs/core/display_base.h
+++ b/sdm/libs/core/display_base.h
@@ -121,6 +121,7 @@
   virtual DisplayError HandleSecureEvent(SecureEvent secure_event) {
     return kErrorNotSupported;
   }
+  virtual DisplayError SetQSyncMode(QSyncMode qsync_mode) { return kErrorNotSupported; }
   virtual std::string Dump();
   virtual DisplayError InitializeColorModes();
 
diff --git a/sdm/libs/core/display_primary.cpp b/sdm/libs/core/display_primary.cpp
index 49d4146..916bce2 100644
--- a/sdm/libs/core/display_primary.cpp
+++ b/sdm/libs/core/display_primary.cpp
@@ -400,7 +400,7 @@
 }
 
 bool DisplayPrimary::NeedsAVREnable() {
-  if (avr_prop_disabled_) {
+  if (avr_prop_disabled_ || qsync_mode_ == kQSyncModeNone) {
     return false;
   }
 
@@ -536,5 +536,15 @@
   return hw_intf_->HandleSecureEvent(secure_event);
 }
 
+DisplayError DisplayPrimary::SetQSyncMode(QSyncMode qsync_mode) {
+  lock_guard<recursive_mutex> obj(recursive_mutex_);
+  if (GetDriverType() == DriverType::DRM && qsync_mode == kQsyncModeOneShot) {
+    return kErrorNotSupported;
+  }
+  qsync_mode_ = qsync_mode;
+
+  return kErrorNone;
+}
+
 }  // namespace sdm
 
diff --git a/sdm/libs/core/display_primary.h b/sdm/libs/core/display_primary.h
index 2da6712..3f24bb1 100644
--- a/sdm/libs/core/display_primary.h
+++ b/sdm/libs/core/display_primary.h
@@ -69,6 +69,7 @@
   virtual DisplayError GetPanelBrightness(int *level);
   virtual DisplayError CachePanelBrightness(int level);
   virtual DisplayError HandleSecureEvent(SecureEvent secure_event);
+  virtual DisplayError SetQSyncMode(QSyncMode qsync_mode);
 
   // Implement the HWEventHandlers
   virtual DisplayError VSync(int64_t timestamp);
@@ -95,6 +96,7 @@
   uint32_t current_refresh_rate_ = 0;
   bool reset_panel_ = false;
   DppsInfo dpps_info_ = {};
+  QSyncMode qsync_mode_ = kQSyncModeNone;
 };
 
 }  // namespace sdm
diff --git a/sdm/libs/hwc2/display_null.h b/sdm/libs/hwc2/display_null.h
index 9241acc..ddd9b27 100644
--- a/sdm/libs/hwc2/display_null.h
+++ b/sdm/libs/hwc2/display_null.h
@@ -93,6 +93,7 @@
   MAKE_NO_OP(GetClientTargetSupport(uint32_t, uint32_t, LayerBufferFormat,
                                     const ColorMetaData &))
   MAKE_NO_OP(HandleSecureEvent(SecureEvent))
+  MAKE_NO_OP(SetQSyncMode(QSyncMode))
 
   DisplayConfigVariableInfo default_variable_config_ = {};
   DisplayConfigFixedInfo default_fixed_config_ = {};
diff --git a/sdm/libs/hwc2/hwc_display.h b/sdm/libs/hwc2/hwc_display.h
index f1df3ee..d35ea23 100644
--- a/sdm/libs/hwc2/hwc_display.h
+++ b/sdm/libs/hwc2/hwc_display.h
@@ -253,6 +253,9 @@
   }
   virtual HWC2::Error GetValidateDisplayOutput(uint32_t *out_num_types, uint32_t *out_num_requests);
   virtual bool IsDisplayCommandMode();
+  virtual HWC2::Error SetQSyncMode(QSyncMode qsync_mode) {
+    return HWC2::Error::Unsupported;
+  }
 
  protected:
   // Maximum number of layers supported by display manager.
diff --git a/sdm/libs/hwc2/hwc_display_primary.cpp b/sdm/libs/hwc2/hwc_display_primary.cpp
index 4723409..36050d2 100644
--- a/sdm/libs/hwc2/hwc_display_primary.cpp
+++ b/sdm/libs/hwc2/hwc_display_primary.cpp
@@ -673,4 +673,13 @@
   return display_intf_->GetMixerResolution(width, height);
 }
 
+HWC2::Error HWCDisplayPrimary::SetQSyncMode(QSyncMode qsync_mode) {
+  auto err = display_intf_->SetQSyncMode(qsync_mode);
+  if (err != kErrorNone) {
+    return HWC2::Error::Unsupported;
+  }
+
+  return HWC2::Error::None;
+}
+
 }  // namespace sdm
diff --git a/sdm/libs/hwc2/hwc_display_primary.h b/sdm/libs/hwc2/hwc_display_primary.h
index cedf859..c561f4c 100644
--- a/sdm/libs/hwc2/hwc_display_primary.h
+++ b/sdm/libs/hwc2/hwc_display_primary.h
@@ -73,6 +73,7 @@
   virtual HWC2::Error SetReadbackBuffer(const native_handle_t *buffer, int32_t acquire_fence,
                                         bool post_processed_output);
   virtual HWC2::Error GetReadbackBufferFence(int32_t *release_fence);
+  virtual HWC2::Error SetQSyncMode(QSyncMode qsync_mode);
 
  private:
   HWCDisplayPrimary(CoreInterface *core_intf, BufferAllocator *buffer_allocator,
diff --git a/sdm/libs/hwc2/hwc_session.cpp b/sdm/libs/hwc2/hwc_session.cpp
index 874b8d9..237343f 100644
--- a/sdm/libs/hwc2/hwc_session.cpp
+++ b/sdm/libs/hwc2/hwc_session.cpp
@@ -1219,6 +1219,14 @@
       output_parcel->writeInt32(getComposerStatus());
       break;
 
+    case qService::IQService::SET_QSYNC_MODE:
+      if (!input_parcel) {
+        DLOGE("QService command = %d: input_parcel needed.", command);
+        break;
+      }
+      status = SetQSyncMode(input_parcel);
+      break;
+
     default:
       DLOGW("QService command = %d is not supported.", command);
       break;
@@ -2145,4 +2153,26 @@
   return CallDisplayFunction(device, display, &HWCDisplay::GetReadbackBufferFence, release_fence);
 }
 
+android::status_t HWCSession::SetQSyncMode(const android::Parcel *input_parcel) {
+  auto mode = input_parcel->readInt32();
+  auto device = static_cast<hwc2_device_t *>(this);
+
+  QSyncMode qsync_mode = kQSyncModeNone;
+  switch (mode) {
+    case qService::IQService::QSYNC_MODE_NONE:
+      qsync_mode = kQSyncModeNone;
+      break;
+    case qService::IQService::QSYNC_MODE_CONTINUOUS:
+      qsync_mode = kQSyncModeContinuous;
+      break;
+    case qService::IQService::QSYNC_MODE_ONESHOT:
+      qsync_mode = kQsyncModeOneShot;
+      break;
+    default:
+      DLOGE("Qsync mode not supported %d", mode);
+      return -EINVAL;
+  }
+  return CallDisplayFunction(device, HWC_DISPLAY_PRIMARY, &HWCDisplay::SetQSyncMode, qsync_mode);
+}
+
 }  // namespace sdm
diff --git a/sdm/libs/hwc2/hwc_session.h b/sdm/libs/hwc2/hwc_session.h
index cd962f4..f74179b 100644
--- a/sdm/libs/hwc2/hwc_session.h
+++ b/sdm/libs/hwc2/hwc_session.h
@@ -261,6 +261,7 @@
 
   android::status_t SetColorModeById(const android::Parcel *input_parcel);
   android::status_t getComposerStatus();
+  android::status_t SetQSyncMode(const android::Parcel *input_parcel);
 
   void Refresh(hwc2_display_t display);
   void HotPlug(hwc2_display_t display, HWC2::Connection state);