Merge "gralloc1: Use implementation defined format at allocate"
diff --git a/libdrmutils/drm_interface.h b/libdrmutils/drm_interface.h
index ca2f6ff..a0b8ec1 100644
--- a/libdrmutils/drm_interface.h
+++ b/libdrmutils/drm_interface.h
@@ -138,6 +138,12 @@
    */
   PLANE_SET_FB_SECURE_MODE,
   /*
+   * Op: Sets csc config on this plane.
+   * Arg: uint32_t - Plane ID
+   *      uint32_t* - pointer to csc type
+   */
+  PLANE_SET_CSC_CONFIG,
+  /*
    * Op: Activate or deactivate a CRTC
    * Arg: uint32_t - CRTC ID
    *      uint32_t - 1 to enable, 0 to disable
@@ -267,6 +273,12 @@
    *      DRMRect * - Array of Connector ROIs
    */
   CONNECTOR_SET_ROI,
+  /*
+   * Op: Set FB secure mode for Writeback connector.
+   * Arg: uint32_t - Connector ID
+   *      uint32_t - FB Secure mode
+   */
+  CONNECTOR_SET_FB_SECURE_MODE,
 };
 
 enum struct DRMRotation {
@@ -353,6 +365,9 @@
   CompRatioMap comp_ratio_rt_map;
   CompRatioMap comp_ratio_nrt_map;
   uint32_t hw_version;
+  uint64_t min_core_ib;
+  uint64_t min_llcc_ib;
+  uint64_t min_dram_ib;
 };
 
 enum struct DRMPlaneType {
@@ -465,6 +480,15 @@
   void *payload;
 };
 
+enum DRMCscType {
+  kCscYuv2Rgb601L,
+  kCscYuv2Rgb601FR,
+  kCscYuv2Rgb709L,
+  kCscYuv2Rgb2020L,
+  kCscYuv2Rgb2020FR,
+  kCscTypeMax,
+};
+
 struct DRMScalerLUTInfo {
   uint32_t dir_lut_size = 0;
   uint32_t cir_lut_size = 0;
diff --git a/libgralloc1/gr_buf_mgr.cpp b/libgralloc1/gr_buf_mgr.cpp
index b79dffa..3c00ca7 100644
--- a/libgralloc1/gr_buf_mgr.cpp
+++ b/libgralloc1/gr_buf_mgr.cpp
@@ -192,7 +192,13 @@
 
 gralloc1_error_t BufferManager::FreeBuffer(std::shared_ptr<Buffer> buf) {
   auto hnd = buf->handle;
-  ALOGD_IF(DEBUG, "FreeBuffer handle:%p id: %" PRIu64, hnd, hnd->id);
+  ALOGD_IF(DEBUG, "FreeBuffer handle:%p", hnd);
+
+  if (private_handle_t::validate(hnd) != 0) {
+    ALOGE("FreeBuffer: Invalid handle: %p", hnd);
+    return GRALLOC1_ERROR_BAD_HANDLE;
+  }
+
   if (allocator_->FreeBuffer(reinterpret_cast<void *>(hnd->base), hnd->size, hnd->offset,
                              hnd->fd, buf->ion_handle_main) != 0) {
     return GRALLOC1_ERROR_BAD_HANDLE;
@@ -272,19 +278,12 @@
   } else {
     private_handle_t *handle = const_cast<private_handle_t *>(hnd);
     err = ImportHandleLocked(handle);
-    if (err == GRALLOC1_ERROR_NONE) {
-      // TODO(user): See bug 35955598
-      if (hnd->flags & private_handle_t::PRIV_FLAGS_SECURE_BUFFER) {
-        return GRALLOC1_ERROR_NONE;  // Don't map secure buffer
-      }
-      err = MapBuffer(hnd);
-    }
   }
   return err;
 }
 
 gralloc1_error_t BufferManager::ReleaseBuffer(private_handle_t const *hnd) {
-  ALOGD_IF(DEBUG, "Release buffer handle:%p id: %" PRIu64, hnd, hnd->id);
+  ALOGD_IF(DEBUG, "Release buffer handle:%p", hnd);
   std::lock_guard<std::mutex> lock(buffer_lock_);
   auto buf = GetBufferFromHandleLocked(hnd);
   if (buf == nullptr) {
@@ -703,7 +702,7 @@
       *flag = hnd->flags &private_handle_t::PRIV_FLAGS_UBWC_ALIGNED;
       int linear_format = 0;
       if (getMetaData(hnd, GET_LINEAR_FORMAT, &linear_format) == 0) {
-        if (!linear_format) {
+        if (linear_format) {
          *flag = 0;
         }
       }
diff --git a/libgralloc1/gr_device_impl.cpp b/libgralloc1/gr_device_impl.cpp
index ee90090..03e42ab 100644
--- a/libgralloc1/gr_device_impl.cpp
+++ b/libgralloc1/gr_device_impl.cpp
@@ -392,14 +392,13 @@
 }
 
 gralloc1_error_t GrallocImpl::ReleaseBuffer(gralloc1_device_t *device, buffer_handle_t buffer) {
-  gralloc1_error_t status = CheckDeviceAndHandle(device, buffer);
-  if (status == GRALLOC1_ERROR_NONE) {
-    const private_handle_t *hnd = PRIV_HANDLE_CONST(buffer);
-    GrallocImpl const *dev = GRALLOC_IMPL(device);
-    status = dev->buf_mgr_->ReleaseBuffer(hnd);
+  if (!device || !buffer) {
+    return GRALLOC1_ERROR_BAD_DESCRIPTOR;
   }
 
-  return status;
+  const private_handle_t *hnd = PRIV_HANDLE_CONST(buffer);
+  GrallocImpl const *dev = GRALLOC_IMPL(device);
+  return dev->buf_mgr_->ReleaseBuffer(hnd);
 }
 
 gralloc1_error_t GrallocImpl::GetNumFlexPlanes(gralloc1_device_t *device, buffer_handle_t buffer,
diff --git a/libgralloc1/gralloc_priv.h b/libgralloc1/gralloc_priv.h
index 2abdd84..cec4af0 100644
--- a/libgralloc1/gralloc_priv.h
+++ b/libgralloc1/gralloc_priv.h
@@ -57,6 +57,7 @@
 /* TODO(user): move these to use producer private bits once 64-bit support available */
 /* This flag is used to indicate 10-bit tight pack format (e.g. TP10) */
 #define GRALLOC1_PRODUCER_USAGE_PRIVATE_10BIT_TP  0x08000000
+#define GRALLOC1_CONSUMER_USAGE_PRIVATE_10BIT_TP  0x08000000
 
 
 /* Consumer flags */
diff --git a/liblight/lights.c b/liblight/lights.c
index 3b5068c..15db827 100644
--- a/liblight/lights.c
+++ b/liblight/lights.c
@@ -361,8 +361,14 @@
         set_light = set_light_battery;
     else if (0 == strcmp(LIGHT_ID_NOTIFICATIONS, name))
         set_light = set_light_notifications;
-    else if (0 == strcmp(LIGHT_ID_BUTTONS, name))
-        set_light = set_light_buttons;
+    else if (0 == strcmp(LIGHT_ID_BUTTONS, name)) {
+        if (!access(BUTTON_FILE, F_OK)) {
+          // enable light button when the file is present
+          set_light = set_light_buttons;
+        } else {
+          return -EINVAL;
+        }
+    }
     else if (0 == strcmp(LIGHT_ID_ATTENTION, name))
         set_light = set_light_attention;
     else
diff --git a/sdm/include/private/hw_info_types.h b/sdm/include/private/hw_info_types.h
index 421277a..ca7261a 100644
--- a/sdm/include/private/hw_info_types.h
+++ b/sdm/include/private/hw_info_types.h
@@ -213,6 +213,9 @@
   CompRatioMap comp_ratio_nrt_map;
   uint32_t cache_size = 0;  // cache size in bytes
   HWQseedStepVersion pipe_qseed3_version = kQseed3v2;  // only valid when has_qseed3=true
+  uint64_t min_core_ib_kbps = 0;
+  uint64_t min_llcc_ib_kbps = 0;
+  uint64_t min_dram_ib_kbps = 0;
 
   void Reset() { *this = HWResourceInfo(); }
 };
diff --git a/sdm/libs/core/drm/hw_device_drm.cpp b/sdm/libs/core/drm/hw_device_drm.cpp
index 23e5447..f87712a 100644
--- a/sdm/libs/core/drm/hw_device_drm.cpp
+++ b/sdm/libs/core/drm/hw_device_drm.cpp
@@ -97,6 +97,7 @@
 using sde_drm::DRMPowerMode;
 using sde_drm::DRMSecureMode;
 using sde_drm::DRMSecurityLevel;
+using sde_drm::DRMCscType;
 
 namespace sdm {
 
@@ -670,9 +671,9 @@
 
   drm_atomic_intf_->Perform(DRMOps::CRTC_SET_ACTIVE, token_.crtc_id, 1);
   drm_atomic_intf_->Perform(DRMOps::CONNECTOR_SET_POWER_MODE, token_.conn_id, DRMPowerMode::ON);
-  int ret = drm_atomic_intf_->Commit(false /* synchronous */);
+  int ret = drm_atomic_intf_->Commit(true /* synchronous */);
   if (ret) {
-    DLOGE("%s failed with error %d", __FUNCTION__, ret);
+    DLOGE("Failed with error: %d", ret);
     return kErrorHardware;
   }
   return kErrorNone;
@@ -686,16 +687,23 @@
 
   drm_atomic_intf_->Perform(DRMOps::CONNECTOR_SET_POWER_MODE, token_.conn_id, DRMPowerMode::OFF);
   drm_atomic_intf_->Perform(DRMOps::CRTC_SET_ACTIVE, token_.crtc_id, 0);
-  int ret = drm_atomic_intf_->Commit(false /* synchronous */);
+  int ret = drm_atomic_intf_->Commit(true /* synchronous */);
   if (ret) {
-    DLOGE("%s failed with error %d", __FUNCTION__, ret);
+    DLOGE("Failed with error: %d", ret);
     return kErrorHardware;
   }
   return kErrorNone;
 }
 
 DisplayError HWDeviceDRM::Doze() {
+  drm_atomic_intf_->Perform(DRMOps::CRTC_SET_ACTIVE, token_.crtc_id, 1);
   drm_atomic_intf_->Perform(DRMOps::CONNECTOR_SET_POWER_MODE, token_.conn_id, DRMPowerMode::DOZE);
+  int ret = drm_atomic_intf_->Commit(false /* synchronous */);
+  if (ret) {
+    DLOGE("Failed with error: %d", ret);
+    return kErrorHardware;
+  }
+
   return kErrorNone;
 }
 
@@ -824,6 +832,10 @@
                                       reinterpret_cast<uint64_t>(&scaler_output.scaler_v2));
           }
         }
+
+        DRMCscType csc_type = DRMCscType::kCscTypeMax;
+        SelectCscType(layer.input_buffer, &csc_type);
+        drm_atomic_intf_->Perform(DRMOps::PLANE_SET_CSC_CONFIG, pipe_id, &csc_type);
       }
     }
   }
@@ -985,6 +997,12 @@
 }
 
 DisplayError HWDeviceDRM::Flush() {
+  int ret = drm_atomic_intf_->Commit(false /* synchronous */);
+  if (ret) {
+    DLOGE("failed with error %d", ret);
+    return kErrorHardware;
+  }
+
   return kErrorNone;
 }
 
@@ -1011,6 +1029,34 @@
   }
 }
 
+void HWDeviceDRM::SelectCscType(const LayerBuffer &input_buffer, DRMCscType *type) {
+  if (type == NULL) {
+    return;
+  }
+
+  *type = DRMCscType::kCscTypeMax;
+  if (input_buffer.format < kFormatYCbCr420Planar) {
+    return;
+  }
+
+  switch (input_buffer.color_metadata.colorPrimaries) {
+    case ColorPrimaries_BT601_6_525:
+    case ColorPrimaries_BT601_6_625:
+      *type = ((input_buffer.color_metadata.range == Range_Full) ?
+               DRMCscType::kCscYuv2Rgb601FR : DRMCscType::kCscYuv2Rgb601L);
+      break;
+    case ColorPrimaries_BT709_5:
+      *type = DRMCscType::kCscYuv2Rgb709L;
+      break;
+    case ColorPrimaries_BT2020:
+      *type = ((input_buffer.color_metadata.range == Range_Full) ?
+                DRMCscType::kCscYuv2Rgb2020FR : DRMCscType::kCscYuv2Rgb2020L);
+      break;
+    default:
+      break;
+  }
+}
+
 void HWDeviceDRM::SetRect(const LayerRect &source, DRMRect *target) {
   target->left = UINT32(source.left);
   target->top = UINT32(source.top);
@@ -1028,7 +1074,7 @@
 
   // In no rotation case or inline rotation case, plane will handle flips
   // In DRM framework rotation is applied in counter-clockwise direction.
-  if (transform.rotation == 90) {
+  if (mode == kRotatorInline && transform.rotation == 90) {
     // a) rotate 90 clockwise = rotate 270 counter-clockwise in DRM
     // rotate 270 is translated as hflip + vflip + rotate90
     // b) rotate 270 clockwise = rotate 90 counter-clockwise in DRM
diff --git a/sdm/libs/core/drm/hw_device_drm.h b/sdm/libs/core/drm/hw_device_drm.h
index ee5b6c7..883d605 100644
--- a/sdm/libs/core/drm/hw_device_drm.h
+++ b/sdm/libs/core/drm/hw_device_drm.h
@@ -123,6 +123,7 @@
   void AddSolidfillStage(const HWSolidfillStage &sf, uint32_t plane_alpha);
   void SetBlending(const LayerBlending &source, sde_drm::DRMBlendType *target);
   void SetSrcConfig(const LayerBuffer &input_buffer, uint32_t *config);
+  void SelectCscType(const LayerBuffer &input_buffer, sde_drm::DRMCscType *type);
   void SetRect(const LayerRect &source, sde_drm::DRMRect *target);
   void SetRotation(LayerTransform transform, const HWRotatorMode &mode, uint32_t* rot_bit_mask);
   DisplayError DefaultCommit(HWLayers *hw_layers);
diff --git a/sdm/libs/core/drm/hw_info_drm.cpp b/sdm/libs/core/drm/hw_info_drm.cpp
index b8eb564..445974f 100644
--- a/sdm/libs/core/drm/hw_info_drm.cpp
+++ b/sdm/libs/core/drm/hw_info_drm.cpp
@@ -287,6 +287,9 @@
   hw_resource->max_bandwidth_high = info.max_bandwidth_high / kKiloUnit;
   hw_resource->max_sde_clk = info.max_sde_clk;
   hw_resource->hw_revision = info.hw_version;
+  hw_resource->min_core_ib_kbps = info.min_core_ib / kKiloUnit;
+  hw_resource->min_llcc_ib_kbps = info.min_llcc_ib / kKiloUnit;
+  hw_resource->min_dram_ib_kbps = info.min_dram_ib / kKiloUnit;
 
   std::vector<LayerBufferFormat> sdm_format;
   for (auto &it : info.comp_ratio_rt_map) {
diff --git a/sdm/libs/core/drm/hw_tv_drm.cpp b/sdm/libs/core/drm/hw_tv_drm.cpp
index 2659a32..90a204f 100644
--- a/sdm/libs/core/drm/hw_tv_drm.cpp
+++ b/sdm/libs/core/drm/hw_tv_drm.cpp
@@ -56,6 +56,7 @@
 using sde_drm::DRMPPFeatureInfo;
 using sde_drm::DRMOps;
 using sde_drm::DRMTopology;
+using sde_drm::DRMPowerMode;
 
 namespace sdm {
 
@@ -98,6 +99,7 @@
 
   return error;
 }
+
 DisplayError HWTVDRM::SetDisplayAttributes(uint32_t index) {
   if (index >= connector_info_.modes.size()) {
     return kErrorNotSupported;
@@ -146,10 +148,12 @@
         (fps == connector_info_.modes[idex].vrefresh)) {
       if ((format >> 1) & (connector_info_.modes[idex].flags >> kBitYUV)) {
         *index = UINT32(idex);
+        break;
       }
 
       if (format & (connector_info_.modes[idex].flags >> kBitRGB)) {
         *index = UINT32(idex);
+        break;
       }
     }
   }
@@ -157,5 +161,36 @@
   return kErrorNone;
 }
 
+/* overriding display state funcs to have special or NO OP implementation for TVs */
+DisplayError HWTVDRM::Deinit() {
+  drm_atomic_intf_->Perform(DRMOps::CRTC_SET_ACTIVE, token_.crtc_id, 0);
+
+  return HWDeviceDRM::Deinit();
+}
+
+DisplayError HWTVDRM::PowerOff() {
+  DTRACE_SCOPED();
+
+  int ret = drm_atomic_intf_->Commit(true /* synchronous */);
+  if (ret) {
+    DLOGE("%s failed with error %d", __FUNCTION__, ret);
+    return kErrorHardware;
+  }
+
+  return kErrorNone;
+}
+
+DisplayError HWTVDRM::Doze() {
+  return kErrorNone;
+}
+
+DisplayError HWTVDRM::DozeSuspend() {
+  return kErrorNone;
+}
+
+DisplayError HWTVDRM::Standby() {
+  return kErrorNone;
+}
+
 }  // namespace sdm
 
diff --git a/sdm/libs/core/drm/hw_tv_drm.h b/sdm/libs/core/drm/hw_tv_drm.h
index fa8012a..985499e 100644
--- a/sdm/libs/core/drm/hw_tv_drm.h
+++ b/sdm/libs/core/drm/hw_tv_drm.h
@@ -41,8 +41,13 @@
 
  protected:
   virtual DisplayError Init();
+  virtual DisplayError Deinit();
   virtual DisplayError SetDisplayAttributes(uint32_t index);
   virtual DisplayError GetConfigIndex(char *mode, uint32_t *index);
+  virtual DisplayError PowerOff();
+  virtual DisplayError Doze();
+  virtual DisplayError DozeSuspend();
+  virtual DisplayError Standby();
 
  private:
   static const int kBitRGB  = 20;
diff --git a/sdm/libs/core/drm/hw_virtual_drm.cpp b/sdm/libs/core/drm/hw_virtual_drm.cpp
index 55f38ac..7c7e348 100644
--- a/sdm/libs/core/drm/hw_virtual_drm.cpp
+++ b/sdm/libs/core/drm/hw_virtual_drm.cpp
@@ -42,6 +42,7 @@
 using sde_drm::DRMRect;
 using sde_drm::DRMOps;
 using sde_drm::DRMPowerMode;
+using sde_drm::DRMSecureMode;
 namespace sdm {
 
 HWVirtualDRM::HWVirtualDRM(BufferSyncHandler *buffer_sync_handler,
@@ -85,6 +86,11 @@
   return;
 }
 
+void HWVirtualDRM::ConfigureWbConnectorSecureMode(bool secure) {
+  DRMSecureMode secure_mode = secure ? DRMSecureMode::SECURE : DRMSecureMode::NON_SECURE;
+  drm_atomic_intf_->Perform(DRMOps::CONNECTOR_SET_FB_SECURE_MODE, token_.conn_id, secure_mode);
+}
+
 void HWVirtualDRM::InitializeConfigs() {
   drmModeModeInfo mode = {};
   mode.hdisplay = mode.hsync_start = mode.hsync_end = mode.htotal = (uint16_t) width_;
@@ -144,6 +150,7 @@
 
   ConfigureWbConnectorFbId(fb_id);
   ConfigureWbConnectorDestRect();
+  ConfigureWbConnectorSecureMode(output_buffer->flags.secure);
 
   err = HWDeviceDRM::AtomicCommit(hw_layers);
   registry_.UnregisterNext();
diff --git a/sdm/libs/core/drm/hw_virtual_drm.h b/sdm/libs/core/drm/hw_virtual_drm.h
index afa5c71..7fa6c54 100644
--- a/sdm/libs/core/drm/hw_virtual_drm.h
+++ b/sdm/libs/core/drm/hw_virtual_drm.h
@@ -59,6 +59,7 @@
   virtual DisplayError PowerOff();
   void ConfigureWbConnectorFbId(uint32_t fb_id);
   void ConfigureWbConnectorDestRect();
+  void ConfigureWbConnectorSecureMode(bool secure);
   void DumpConfigs();
 
  private:
diff --git a/sdm/libs/hwc2/hwc_buffer_allocator.cpp b/sdm/libs/hwc2/hwc_buffer_allocator.cpp
index eb932e3..c32a236 100644
--- a/sdm/libs/hwc2/hwc_buffer_allocator.cpp
+++ b/sdm/libs/hwc2/hwc_buffer_allocator.cpp
@@ -96,6 +96,10 @@
     alloc_flags |= GRALLOC1_PRODUCER_USAGE_PROTECTED;
   }
 
+  if (buffer_config.secure_camera) {
+    alloc_flags |= GRALLOC1_PRODUCER_USAGE_CAMERA;
+  }
+
   if (!buffer_config.cache) {
     // Allocate uncached buffers
     alloc_flags |= GRALLOC_USAGE_PRIVATE_UNCACHED;
@@ -106,7 +110,7 @@
   }
 
   uint64_t producer_usage = alloc_flags;
-  uint64_t consumer_usage = alloc_flags;
+  uint64_t consumer_usage = (alloc_flags | GRALLOC1_CONSUMER_USAGE_HWCOMPOSER);
   // CreateBuffer
   private_handle_t *hnd = nullptr;
   Perform_(gralloc_device_, GRALLOC1_MODULE_PERFORM_ALLOCATE_BUFFER, width, height, format,
diff --git a/sdm/libs/hwc2/hwc_session.cpp b/sdm/libs/hwc2/hwc_session.cpp
index 272b2f6..41a6b36 100644
--- a/sdm/libs/hwc2/hwc_session.cpp
+++ b/sdm/libs/hwc2/hwc_session.cpp
@@ -163,6 +163,8 @@
     return -EINVAL;
   }
 
+  g_hwc_uevent_.Register(this);
+
   error = CoreInterface::CreateCore(HWCDebugHandler::Get(), &buffer_allocator_,
                                     &buffer_sync_handler_, &socket_handler_, &core_intf_);
   if (error != kErrorNone) {
@@ -171,7 +173,6 @@
     return -EINVAL;
   }
 
-  g_hwc_uevent_.Register(this);
 
   // If HDMI display is primary display, defer display creation until hotplug event is received.
   HWDisplayInterfaceInfo hw_disp_info = {};
@@ -1347,25 +1348,37 @@
   }
 }
 
-void HWCSession::HandleExtHPD(const char *uevent_data, int length) {
+const char *GetTokenValue(const char *uevent_data, int length, const char *token) {
   const char *iterator_str = uevent_data;
-  const char *event_info = "status=";
   const char *pstr = NULL;
   while (((iterator_str - uevent_data) <= length) && (*iterator_str)) {
-    pstr = strstr(iterator_str, event_info);
-    if (pstr != NULL) {
+    pstr = strstr(iterator_str, token);
+    if (pstr) {
       break;
     }
     iterator_str += strlen(iterator_str) + 1;
   }
 
+  if (pstr)
+    pstr = pstr+strlen(token);
+
+  return pstr;
+}
+
+void HWCSession::HandleExtHPD(const char *uevent_data, int length) {
+  const char *pstr = GetTokenValue(uevent_data, length, "name=");
+  if (!pstr || (strcmp(pstr, "DP-1") != 0)) {
+    return;
+  }
+
+  pstr = GetTokenValue(uevent_data, length, "status=");
   if (pstr) {
     bool connected = false;
-    if (strcmp(pstr+strlen(event_info), "connected") == 0) {
+    if (strcmp(pstr, "connected") == 0) {
       connected = true;
     }
 
-    DLOGI("Recived Ext HPD, connected:%d  status=%s", connected, pstr+strlen(event_info));
+    DLOGI("Recived Ext HPD, connected:%d  status=%s", connected, pstr);
     HotPlugHandler(connected);
   }
 }