Merge "drm : Add secondary/external display support"
diff --git a/libdrmutils/drm_interface.h b/libdrmutils/drm_interface.h
index 866ade6..97c8ad8 100644
--- a/libdrmutils/drm_interface.h
+++ b/libdrmutils/drm_interface.h
@@ -155,19 +155,48 @@
    *      uint32_t - core_clk
    */
   CRTC_SET_CORE_CLK,
-   /*
-   * Op: Sets overall SDE core average bandwidth
+  /*
+   * Op: Sets MNOC bus average bandwidth
    * Arg: uint32_t - CRTC ID
    *      uint32_t - core_ab
    */
   CRTC_SET_CORE_AB,
    /*
-   * Op: Sets overall SDE core instantaneous bandwidth
+   * Op: Sets MNOC bus instantaneous bandwidth
    * Arg: uint32_t - CRTC ID
    *      uint32_t - core_ib
    */
   CRTC_SET_CORE_IB,
   /*
+   * Op: Sets LLCC Bus average bandwidth
+   * Arg: uint32_t - CRTC ID
+   *      uint32_t - llcc_ab
+   */
+  CRTC_SET_LLCC_AB,
+  /*
+   * Op: Sets LLCC Bus instantaneous bandwidth
+   * Arg: uint32_t - CRTC ID
+   *      uint32_t - llcc_ib
+   */
+  CRTC_SET_LLCC_IB,
+  /*
+   * Op: Sets DRAM bus average bandwidth
+   * Arg: uint32_t - CRTC ID
+   *      uint32_t - dram_ab
+   */
+  CRTC_SET_DRAM_AB,
+  /*
+   * Op: Sets DRAM bus instantaneous bandwidth
+   * Arg: uint32_t - CRTC ID
+   *      uint32_t - dram_ib
+   */
+  CRTC_SET_DRAM_IB,
+  /*
+   * Op: Sets rotator clock for inline rotation
+   * Arg: uint32_t - CRTC ID
+   *      uint32_t - rot_clk
+   */
+  CRTC_SET_ROT_CLK,  /*
    * Op: Returns release fence for this frame. Should be called after Commit() on
    * DRMAtomicReqInterface.
    * Arg: uint32_t - CRTC ID
diff --git a/libgralloc1/gr_buf_mgr.cpp b/libgralloc1/gr_buf_mgr.cpp
index 7e0ba14..767a4e9 100644
--- a/libgralloc1/gr_buf_mgr.cpp
+++ b/libgralloc1/gr_buf_mgr.cpp
@@ -497,14 +497,14 @@
   BufferInfo info = GetBufferInfo(descriptor);
   GetBufferSizeAndDimensions(info, &size, &alignedw, &alignedh);
   size = (bufferSize >= size) ? bufferSize : size;
-  size = size * layer_count;
 
   int err = 0;
   int flags = 0;
   auto page_size = UINT(getpagesize());
   AllocData data;
   data.align = GetDataAlignment(format, prod_usage, cons_usage);
-  data.size = ALIGN(size, data.align);
+  size = ALIGN(size, data.align) * layer_count;
+  data.size = size;
   data.handle = (uintptr_t) handle;
   data.uncached = allocator_->UseUncached(prod_usage, cons_usage);
 
diff --git a/sdm/include/private/hw_info_types.h b/sdm/include/private/hw_info_types.h
index 64e8454..78dbfad 100644
--- a/sdm/include/private/hw_info_types.h
+++ b/sdm/include/private/hw_info_types.h
@@ -507,13 +507,22 @@
   Handle pvt_data = NULL;   // Private data used by sdm extension only.
 };
 
+struct HWQosData {
+  uint64_t core_ab_bps = 0;
+  uint64_t core_ib_bps = 0;
+  uint64_t llcc_ab_bps = 0;
+  uint64_t llcc_ib_bps = 0;
+  uint64_t dram_ab_bps = 0;
+  uint64_t dram_ib_bps = 0;
+  uint32_t clock_hz = 0;
+  uint32_t rot_clock_hz = 0;
+};
+
 struct HWLayers {
   HWLayersInfo info;
   HWLayerConfig config[kMaxSDELayers];
   float output_compression = 1.0f;
-  uint64_t ab_bps = 0;
-  uint64_t ib_bps = 0;
-  uint32_t clock_hz = 0;
+  HWQosData qos_data = {};
   HWAVRInfo hw_avr_info = {};
 };
 
diff --git a/sdm/libs/core/drm/hw_color_manager_drm.cpp b/sdm/libs/core/drm/hw_color_manager_drm.cpp
index 640a843..3438e77 100644
--- a/sdm/libs/core/drm/hw_color_manager_drm.cpp
+++ b/sdm/libs/core/drm/hw_color_manager_drm.cpp
@@ -270,9 +270,14 @@
       return kErrorParameters;
   }
 
-  if (sde_gamut->map_en)
-    std::memcpy(mdp_gamut->scale_off, sde_gamut->scale_off_data,
-                sizeof(uint32_t) * GAMUT_3D_SCALE_OFF_SZ * GAMUT_3D_SCALE_OFF_TBL_NUM);
+  if (sde_gamut->map_en) {
+    std::memcpy(&mdp_gamut->scale_off[0][0], sde_gamut->scale_off_data[0],
+                sizeof(uint32_t) * GAMUT_3D_SCALE_OFF_SZ);
+    std::memcpy(&mdp_gamut->scale_off[1][0], sde_gamut->scale_off_data[1],
+                sizeof(uint32_t) * GAMUT_3D_SCALE_OFF_SZ);
+    std::memcpy(&mdp_gamut->scale_off[2][0], sde_gamut->scale_off_data[2],
+                sizeof(uint32_t) * GAMUT_3D_SCALE_OFF_SZ);
+  }
 
   for (uint32_t row = 0; row < GAMUT_3D_TBL_NUM; row++) {
     for (uint32_t col = 0; col < size; col++) {
diff --git a/sdm/libs/core/drm/hw_device_drm.cpp b/sdm/libs/core/drm/hw_device_drm.cpp
index a6ed929..b244a2a 100644
--- a/sdm/libs/core/drm/hw_device_drm.cpp
+++ b/sdm/libs/core/drm/hw_device_drm.cpp
@@ -577,6 +577,11 @@
 
 DisplayError HWDeviceDRM::PowerOn() {
   DTRACE_SCOPED();
+  if (!drm_atomic_intf_) {
+    DLOGE("DRM Atomic Interface is null!");
+    return kErrorUndefined;
+  }
+
   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 */);
@@ -588,6 +593,11 @@
 }
 
 DisplayError HWDeviceDRM::PowerOff() {
+  if (!drm_atomic_intf_) {
+    DLOGE("DRM Atomic Interface is null!");
+    return kErrorUndefined;
+  }
+
   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 */);
@@ -620,6 +630,7 @@
 
   HWLayersInfo &hw_layer_info = hw_layers->info;
   uint32_t hw_layer_count = UINT32(hw_layer_info.hw_layers.size());
+  HWQosData &qos_data = hw_layers->qos_data;
 
   // TODO(user): Once destination scalar is enabled we can always send ROIs if driver allows
   if (hw_panel_info_.partial_update) {
@@ -712,12 +723,20 @@
       }
     }
 
-    drm_atomic_intf_->Perform(DRMOps::CRTC_SET_CORE_CLK, token_.crtc_id, hw_layers->clock_hz);
-    drm_atomic_intf_->Perform(DRMOps::CRTC_SET_CORE_AB, token_.crtc_id, hw_layers->ab_bps);
-    drm_atomic_intf_->Perform(DRMOps::CRTC_SET_CORE_IB, token_.crtc_id, hw_layers->ib_bps);
+    drm_atomic_intf_->Perform(DRMOps::CRTC_SET_CORE_CLK, token_.crtc_id, qos_data.clock_hz);
+    drm_atomic_intf_->Perform(DRMOps::CRTC_SET_CORE_AB, token_.crtc_id, qos_data.core_ab_bps);
+    drm_atomic_intf_->Perform(DRMOps::CRTC_SET_CORE_IB, token_.crtc_id, qos_data.core_ib_bps);
+    drm_atomic_intf_->Perform(DRMOps::CRTC_SET_LLCC_AB, token_.crtc_id, qos_data.llcc_ab_bps);
+    drm_atomic_intf_->Perform(DRMOps::CRTC_SET_LLCC_IB, token_.crtc_id, qos_data.llcc_ib_bps);
+    drm_atomic_intf_->Perform(DRMOps::CRTC_SET_DRAM_AB, token_.crtc_id, qos_data.dram_ab_bps);
+    drm_atomic_intf_->Perform(DRMOps::CRTC_SET_DRAM_IB, token_.crtc_id, qos_data.dram_ib_bps);
+    drm_atomic_intf_->Perform(DRMOps::CRTC_SET_ROT_CLK, token_.crtc_id, qos_data.rot_clock_hz);
 
-    DLOGI_IF(kTagDriverConfig, "System: clock=%d Hz, ab=%llu Bps ib=%llu Bps", hw_layers->clock_hz,
-             hw_layers->ab_bps, hw_layers->ib_bps);
+    DLOGI_IF(kTagDriverConfig, "System Clock=%d Hz, Core: AB=%llu Bps, IB=%llu Bps, " \
+             "LLCC: AB=%llu Bps, IB=%llu Bps, DRAM AB=%llu Bps, IB=%llu Bps Rot Clock=%d",
+             qos_data.clock_hz, qos_data.core_ab_bps, qos_data.core_ib_bps, qos_data.llcc_ab_bps,
+             qos_data.llcc_ib_bps, qos_data.dram_ab_bps, qos_data.dram_ib_bps,
+             qos_data.rot_clock_hz);
   }
 }
 
diff --git a/sdm/libs/core/drm/hw_info_drm.cpp b/sdm/libs/core/drm/hw_info_drm.cpp
index d5bd5cf..8843924 100644
--- a/sdm/libs/core/drm/hw_info_drm.cpp
+++ b/sdm/libs/core/drm/hw_info_drm.cpp
@@ -413,8 +413,7 @@
     case SDE_PIX_FMT_RGBX_1010102_UBWC: *sdm_format = kFormatRGBX1010102Ubwc;          break;
     case SDE_PIX_FMT_Y_CBCR_H2V2_P010:  *sdm_format = kFormatYCbCr420P010;             break;
     case SDE_PIX_FMT_Y_CBCR_H2V2_TP10_UBWC: *sdm_format = kFormatYCbCr420TP10Ubwc;     break;
-    /* TODO(user) : enable when defined in uapi
-      case SDE_PIX_FMT_Y_CBCR_H2V2_P010_UBWC: *sdm_format = kFormatYCbCr420P010Ubwc;     break; */
+    case SDE_PIX_FMT_Y_CBCR_H2V2_P010_UBWC: *sdm_format = kFormatYCbCr420P010Ubwc;     break;
     default: *sdm_format = kFormatInvalid;
   }
 }
diff --git a/sdm/libs/hwc2/hwc_color_manager.cpp b/sdm/libs/hwc2/hwc_color_manager.cpp
index b58acc6..afa9a4e 100644
--- a/sdm/libs/hwc2/hwc_color_manager.cpp
+++ b/sdm/libs/hwc2/hwc_color_manager.cpp
@@ -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
@@ -271,7 +271,6 @@
   PPDETuningCfgData *de_tuning_cfg_data = reinterpret_cast<PPDETuningCfgData*>(params);
   if (de_tuning_cfg_data->cfg_pending == true) {
     if (!de_tuning_cfg_data->cfg_en) {
-      de_data.override_flags = kOverrideDEEnable;
       de_data.enable = 0;
     } else {
       de_data.override_flags = kOverrideDEEnable;
diff --git a/sdm/libs/hwc2/hwc_tonemapper.cpp b/sdm/libs/hwc2/hwc_tonemapper.cpp
index 7bda725..74f4c6a 100644
--- a/sdm/libs/hwc2/hwc_tonemapper.cpp
+++ b/sdm/libs/hwc2/hwc_tonemapper.cpp
@@ -49,18 +49,57 @@
 
 namespace sdm {
 
-ToneMapSession::ToneMapSession(HWCBufferAllocator *buffer_allocator) :
-                buffer_allocator_(buffer_allocator) {
+ToneMapSession::ToneMapSession(HWCBufferAllocator *buffer_allocator)
+  : tone_map_task_(*this), buffer_allocator_(buffer_allocator) {
   buffer_info_.resize(kNumIntermediateBuffers);
 }
 
 ToneMapSession::~ToneMapSession() {
-  delete gpu_tone_mapper_;
-  gpu_tone_mapper_ = nullptr;
+  tone_map_task_.PerformTask(ToneMapTaskCode::kCodeDestroy, nullptr);
   FreeIntermediateBuffers();
   buffer_info_.clear();
 }
 
+void ToneMapSession::OnTask(const ToneMapTaskCode &task_code,
+                            SyncTask<ToneMapTaskCode>::TaskContext *task_context) {
+  switch (task_code) {
+    case ToneMapTaskCode::kCodeGetInstance: {
+        ToneMapGetInstanceContext *ctx = static_cast<ToneMapGetInstanceContext *>(task_context);
+        Lut3d &lut_3d = ctx->layer->lut_3d;
+        Color10Bit *grid_entries = NULL;
+        int grid_size = 0;
+        if (lut_3d.validGridEntries) {
+          grid_entries = lut_3d.gridEntries;
+          grid_size = INT(lut_3d.gridSize);
+        }
+        gpu_tone_mapper_ = TonemapperFactory_GetInstance(tone_map_config_.type,
+                                                         lut_3d.lutEntries, lut_3d.dim,
+                                                         grid_entries, grid_size,
+                                                         tone_map_config_.secure);
+      }
+      break;
+
+    case ToneMapTaskCode::kCodeBlit: {
+        ToneMapBlitContext *ctx = static_cast<ToneMapBlitContext *>(task_context);
+        uint8_t buffer_index = current_buffer_index_;
+        const void *dst_hnd = reinterpret_cast<const void *>
+                                (buffer_info_[buffer_index].private_data);
+        const void *src_hnd = reinterpret_cast<const void *>
+                                (ctx->layer->input_buffer.buffer_id);
+        ctx->fence_fd = gpu_tone_mapper_->blit(dst_hnd, src_hnd, ctx->merged_fd);
+      }
+      break;
+
+    case ToneMapTaskCode::kCodeDestroy: {
+        delete gpu_tone_mapper_;
+      }
+      break;
+
+    default:
+      break;
+  }
+}
+
 DisplayError ToneMapSession::AllocateIntermediateBuffers(const Layer *layer) {
   DisplayError error = kErrorNone;
   for (uint8_t i = 0; i < kNumIntermediateBuffers; i++) {
@@ -180,35 +219,30 @@
 }
 
 void HWCToneMapper::ToneMap(Layer* layer, ToneMapSession *session) {
-  int fence_fd = -1;
-  int acquire_fd = -1;
-  int merged_fd = -1;
+  ToneMapBlitContext ctx = {};
+  ctx.layer = layer;
 
   uint8_t buffer_index = session->current_buffer_index_;
-  const private_handle_t *dst_hnd = static_cast<private_handle_t *>
-                                    (session->buffer_info_[buffer_index].private_data);
-  const private_handle_t *src_hnd = reinterpret_cast<const private_handle_t *>
-                                    (layer->input_buffer.buffer_id);
+  int &release_fence_fd = session->release_fence_fd_[buffer_index];
 
   // use and close the layer->input_buffer acquire fence fd.
-  acquire_fd = layer->input_buffer.acquire_fence_fd;
-  buffer_sync_handler_.SyncMerge(session->release_fence_fd_[buffer_index], acquire_fd, &merged_fd);
+  int acquire_fd = layer->input_buffer.acquire_fence_fd;
+  buffer_sync_handler_.SyncMerge(release_fence_fd, acquire_fd, &ctx.merged_fd);
 
   if (acquire_fd >= 0) {
     CloseFd(&acquire_fd);
   }
 
-  if (session->release_fence_fd_[buffer_index] >= 0) {
-    CloseFd(&session->release_fence_fd_[buffer_index]);
+  if (release_fence_fd >= 0) {
+    CloseFd(&release_fence_fd);
   }
 
   DTRACE_BEGIN("GPU_TM_BLIT");
-  fence_fd = session->gpu_tone_mapper_->blit(reinterpret_cast<const void *>(dst_hnd),
-                                             reinterpret_cast<const void *>(src_hnd), merged_fd);
+  session->tone_map_task_.PerformTask(ToneMapTaskCode::kCodeBlit, &ctx);
   DTRACE_END();
 
-  DumpToneMapOutput(session, &fence_fd);
-  session->UpdateBuffer(fence_fd, &layer->input_buffer);
+  DumpToneMapOutput(session, &ctx.fence_fd);
+  session->UpdateBuffer(ctx.fence_fd, &layer->input_buffer);
 }
 
 void HWCToneMapper::PostCommit(LayerStack *layer_stack) {
@@ -281,14 +315,6 @@
 }
 
 DisplayError HWCToneMapper::AcquireToneMapSession(Layer *layer, uint32_t *session_index) {
-  Color10Bit *grid_entries = NULL;
-  int grid_size = 0;
-
-  if (layer->lut_3d.validGridEntries) {
-    grid_entries = layer->lut_3d.gridEntries;
-    grid_size = INT(layer->lut_3d.gridSize);
-  }
-
   // When the property sdm.disable_hdr_lut_gen is set, the lutEntries and gridEntries in
   // the Lut3d will be NULL, clients needs to allocate the memory and set correct 3D Lut
   // for Tonemapping.
@@ -311,13 +337,15 @@
   }
 
   ToneMapSession *session = new ToneMapSession(buffer_allocator_);
+  if (!session) {
+    return kErrorMemory;
+  }
 
   session->SetToneMapConfig(layer);
-  session->gpu_tone_mapper_ = TonemapperFactory_GetInstance(session->tone_map_config_.type,
-                                                            layer->lut_3d.lutEntries,
-                                                            layer->lut_3d.dim,
-                                                            grid_entries, grid_size,
-                                                            session->tone_map_config_.secure);
+
+  ToneMapGetInstanceContext ctx;
+  ctx.layer = layer;
+  session->tone_map_task_.PerformTask(ToneMapTaskCode::kCodeGetInstance, &ctx);
 
   if (session->gpu_tone_mapper_ == NULL) {
     DLOGE("Get Tonemapper failed!");
diff --git a/sdm/libs/hwc2/hwc_tonemapper.h b/sdm/libs/hwc2/hwc_tonemapper.h
index 8367c3e..e2c8ef4 100644
--- a/sdm/libs/hwc2/hwc_tonemapper.h
+++ b/sdm/libs/hwc2/hwc_tonemapper.h
@@ -37,6 +37,7 @@
 
 #include <core/layer_stack.h>
 #include <utils/sys.h>
+#include <utils/sync_task.h>
 #include <vector>
 #include "hwc_buffer_sync_handler.h"
 #include "hwc_buffer_allocator.h"
@@ -45,6 +46,22 @@
 
 namespace sdm {
 
+enum class ToneMapTaskCode : int32_t {
+  kCodeGetInstance,
+  kCodeBlit,
+  kCodeDestroy,
+};
+
+struct ToneMapGetInstanceContext : public SyncTask<ToneMapTaskCode>::TaskContext {
+  Layer *layer = nullptr;
+};
+
+struct ToneMapBlitContext : public SyncTask<ToneMapTaskCode>::TaskContext {
+  Layer *layer = nullptr;
+  int merged_fd = -1;
+  int fence_fd = -1;
+};
+
 struct ToneMapConfig {
   int type = 0;
   ColorPrimaries colorPrimaries = ColorPrimaries_Max;
@@ -53,7 +70,7 @@
   bool secure = false;
 };
 
-class ToneMapSession {
+class ToneMapSession : public SyncTask<ToneMapTaskCode>::TaskHandler {
  public:
   explicit ToneMapSession(HWCBufferAllocator *buffer_allocator);
   ~ToneMapSession();
@@ -64,7 +81,12 @@
   void SetToneMapConfig(Layer *layer);
   bool IsSameToneMapConfig(Layer *layer);
 
+  // TaskHandler methods implementation.
+  virtual void OnTask(const ToneMapTaskCode &task_code,
+                      SyncTask<ToneMapTaskCode>::TaskContext *task_context);
+
   static const uint8_t kNumIntermediateBuffers = 2;
+  SyncTask<ToneMapTaskCode> tone_map_task_;
   Tonemapper *gpu_tone_mapper_ = nullptr;
   HWCBufferAllocator *buffer_allocator_ = nullptr;
   ToneMapConfig tone_map_config_ = {};