Merge "gralloc1: Align buffer size for each layer"
diff --git a/libdrmutils/drm_interface.h b/libdrmutils/drm_interface.h
index 71767e7..97c8ad8 100644
--- a/libdrmutils/drm_interface.h
+++ b/libdrmutils/drm_interface.h
@@ -125,6 +125,12 @@
    */
   PLANE_SET_SCALER_CONFIG,
   /*
+   * Op: Sets plane rotation destination rect
+   * Arg: uint32_t - Plane ID
+   *      DRMRect - rotator dst Rectangle
+   */
+  PLANE_SET_ROTATION_DST_RECT,
+  /*
    * Op: Activate or deactivate a CRTC
    * Arg: uint32_t - CRTC ID
    *      uint32_t - 1 to enable, 0 to disable
@@ -149,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
@@ -315,17 +350,22 @@
   uint32_t max_horizontal_deci;
   uint32_t max_vertical_deci;
   uint64_t max_pipe_bandwidth;
+  uint32_t cache_size;  // cache size in bytes for inline rotation support.
 };
 
 // All DRM Planes as map<Plane_id , plane_type_info> listed from highest to lowest priority
 typedef std::vector<std::pair<uint32_t, DRMPlaneTypeInfo>>  DRMPlanesInfo;
 
 enum struct DRMTopology {
-  UNKNOWN,  // To be compat with driver defs in sde_kms.h
+  UNKNOWN,  // To be compat with driver defs in sde_rm.h
   SINGLE_LM,
+  SINGLE_LM_DSC,
   DUAL_LM,
-  PPSPLIT,
+  DUAL_LM_DSC,
   DUAL_LM_MERGE,
+  DUAL_LM_MERGE_DSC,
+  DUAL_LM_DSCMERGE,
+  PPSPLIT,
 };
 
 enum struct DRMPanelMode {
diff --git a/libgralloc1/Android.mk b/libgralloc1/Android.mk
index f4d4ba7..cdb651c 100644
--- a/libgralloc1/Android.mk
+++ b/libgralloc1/Android.mk
@@ -31,7 +31,7 @@
 LOCAL_MODULE_TAGS             := optional
 LOCAL_C_INCLUDES              := $(common_includes) $(kernel_includes)
 LOCAL_HEADER_LIBRARIES        := display_headers
-LOCAL_SHARED_LIBRARIES        := $(common_libs) libqdutils libqdMetaData libdl
+LOCAL_SHARED_LIBRARIES        := $(common_libs) libqdMetaData libdl
 LOCAL_CFLAGS                  := $(common_flags) -DLOG_TAG=\"grallocutils\" -Wno-sign-conversion
 LOCAL_ADDITIONAL_DEPENDENCIES := $(common_deps) $(kernel_deps)
 LOCAL_SRC_FILES               := gr_utils.cpp gr_adreno_info.cpp
diff --git a/sdm/include/core/sdm_types.h b/sdm/include/core/sdm_types.h
index fae1153..ce356bf 100644
--- a/sdm/include/core/sdm_types.h
+++ b/sdm/include/core/sdm_types.h
@@ -55,6 +55,7 @@
   kErrorShutDown,         //!< Driver is processing shutdown sequence
   kErrorPerfValidation,   //!< Bandwidth or Clock requirement validation failure.
   kErrorNoAppLayers,      //!< No App layer(s) in the draw cycle.
+  kErrorRotatorValidation,  //!< Rotator configuration validation failure.
 };
 
 /*! @brief This structure is defined for client and library compatibility check purpose only. This
diff --git a/sdm/include/private/hw_info_types.h b/sdm/include/private/hw_info_types.h
index cdfec2e..78dbfad 100644
--- a/sdm/include/private/hw_info_types.h
+++ b/sdm/include/private/hw_info_types.h
@@ -205,6 +205,7 @@
   uint32_t undersized_prefill_lines = 0;
   CompRatioMap comp_ratio_rt_map;
   CompRatioMap comp_ratio_nrt_map;
+  uint32_t cache_size = 0;  // cache size in bytes
 
   void Reset() { *this = HWResourceInfo(); }
 };
@@ -321,6 +322,12 @@
   }
 };
 
+enum HWRotatorMode {
+  kRotatorNone,
+  kRotatorOffline,
+  kRotatorInline
+};
+
 struct HWRotateInfo {
   int pipe_id = -1;  // Not actual pipe id, but the relative DMA id
   int writeback_id = -1;  // Writeback block id, but this is the same as DMA id
@@ -342,6 +349,7 @@
   float input_compression = 1.0f;
   float output_compression = 1.0f;
   bool is_buffer_cached = false;
+  HWRotatorMode mode = kRotatorNone;
 };
 
 struct HWScaleLutInfo {
@@ -499,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/include/utils/formats.h b/sdm/include/utils/formats.h
index dd819dc..2d43850 100644
--- a/sdm/include/utils/formats.h
+++ b/sdm/include/utils/formats.h
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2016, The Linux Foundation. All rights reserved.
+* Copyright (c) 2016 - 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
@@ -34,10 +34,28 @@
 
 namespace sdm {
 
+struct FormatTileSize {
+  /*< Tile width in pixels. For YUV formats this will give only the
+      tile width for Y plane*/
+  uint32_t tile_width = 0;
+  /*< Tile height in pixels. For YUV formats this will give only the
+      tile height for Y plane*/
+  uint32_t tile_height = 0;
+
+  /*< Tile width in pixels. Only valid for YUV formats where this will
+      give tile width for UV plane*/
+  uint32_t uv_tile_width = 0;
+  /*< Tile height in pixels. Only valid for YUV formats where this will
+       give tile height for UV plane*/
+  uint32_t uv_tile_height = 0;
+};
+
 bool IsUBWCFormat(LayerBufferFormat format);
 bool Is10BitFormat(LayerBufferFormat format);
 const char *GetFormatString(const LayerBufferFormat &format);
 BufferLayout GetBufferLayout(LayerBufferFormat format);
+DisplayError GetBufferFormatTileSize(LayerBufferFormat format, FormatTileSize *tile_size);
+float GetBufferFormatBpp(LayerBufferFormat format);
 
 }  // namespace sdm
 
diff --git a/sdm/include/utils/rect.h b/sdm/include/utils/rect.h
index ea6edfb..303fc9f 100644
--- a/sdm/include/utils/rect.h
+++ b/sdm/include/utils/rect.h
@@ -60,6 +60,11 @@
   void TransformHV(const LayerRect &src_domain, const LayerRect &in_rect,
                    const LayerTransform &transform, LayerRect *out_rect);
   RectOrientation GetOrientation(const LayerRect &in_rect);
+  DisplayError GetCropAndDestination(const LayerRect &crop, const LayerRect &dst,
+                                     bool rotate90, float *crop_width, float *crop_height,
+                                     float *dst_width, float *dst_height);
+  DisplayError GetScaleFactor(const LayerRect &crop, const LayerRect &dst, bool rotate90,
+                              float *scale_x, float *scale_y);
 }  // namespace sdm
 
 #endif  // __RECT_H__
diff --git a/sdm/libs/core/display_base.cpp b/sdm/libs/core/display_base.cpp
index 618dd2e..f6540cd 100644
--- a/sdm/libs/core/display_base.cpp
+++ b/sdm/libs/core/display_base.cpp
@@ -590,21 +590,24 @@
     char idx[8] = { 0 };
     const char *comp_type = GetName(sdm_layer->composition);
     const char *buffer_format = GetFormatString(input_buffer->format);
-    const char *rotate_split[2] = { "Rot-1", "Rot-2" };
     const char *comp_split[2] = { "Comp-1", "Comp-2" };
 
     snprintf(idx, sizeof(idx), "%d", layer_index);
 
     for (uint32_t count = 0; count < hw_rotator_session.hw_block_count; count++) {
-      char writeback_id[8] = { 0 };
+      char writeback_id[8] = { "I" };
       HWRotateInfo &rotate = hw_rotator_session.hw_rotate_info[count];
       LayerRect &src_roi = rotate.src_roi;
       LayerRect &dst_roi = rotate.dst_roi;
+      const char *rotate_split[2] = { "Rot-1", "Rot-2" };
+      int pipe_id = 0;
 
-      snprintf(writeback_id, sizeof(writeback_id), "%d", rotate.writeback_id);
-
+      if (hw_rotator_session.mode == kRotatorOffline) {
+        snprintf(writeback_id, sizeof(writeback_id), "%d", rotate.writeback_id);
+        pipe_id = rotate.pipe_id;
+      }
       DumpImpl::AppendString(buffer, length, format, idx, comp_type, rotate_split[count],
-                             writeback_id, rotate.pipe_id, input_buffer->width,
+                             writeback_id, pipe_id, input_buffer->width,
                              input_buffer->height, buffer_format, INT(src_roi.left),
                              INT(src_roi.top), INT(src_roi.right), INT(src_roi.bottom),
                              INT(dst_roi.left), INT(dst_roi.top), INT(dst_roi.right),
@@ -633,8 +636,11 @@
         continue;
       }
 
-      LayerRect &src_roi = pipe.src_roi;
+      LayerRect src_roi = pipe.src_roi;
       LayerRect &dst_roi = pipe.dst_roi;
+      if (hw_rotator_session.mode == kRotatorInline) {
+        src_roi = hw_rotator_session.hw_rotate_info[count].dst_roi;
+      }
 
       snprintf(z_order, sizeof(z_order), "%d", pipe.z_order);
       snprintf(flags, sizeof(flags), "0x%08x", hw_layer.flags.flags);
diff --git a/sdm/libs/core/display_hdmi.cpp b/sdm/libs/core/display_hdmi.cpp
index b31ac94..a6c5c47 100644
--- a/sdm/libs/core/display_hdmi.cpp
+++ b/sdm/libs/core/display_hdmi.cpp
@@ -87,7 +87,8 @@
   s3d_format_to_mode_.insert(std::pair<LayerBufferS3DFormat, HWS3DMode>
                             (kS3dFormatFramePacking, kS3DModeFP));
 
-  error = HWEventsInterface::Create(INT(display_type_), this, event_list_, &hw_events_intf_);
+  error = HWEventsInterface::Create(INT(display_type_), this, event_list_, hw_intf_,
+                                    &hw_events_intf_);
   if (error != kErrorNone) {
     DisplayBase::Deinit();
     HWInterface::Destroy(hw_intf_);
diff --git a/sdm/libs/core/display_primary.cpp b/sdm/libs/core/display_primary.cpp
index 53a4fd9..bb467fa 100644
--- a/sdm/libs/core/display_primary.cpp
+++ b/sdm/libs/core/display_primary.cpp
@@ -70,7 +70,8 @@
 
   avr_prop_disabled_ = Debug::IsAVRDisabled();
 
-  error = HWEventsInterface::Create(INT(display_type_), this, event_list_, &hw_events_intf_);
+  error = HWEventsInterface::Create(INT(display_type_), this, event_list_, hw_intf_,
+                                    &hw_events_intf_);
   if (error != kErrorNone) {
     DLOGE("Failed to create hardware events interface. Error = %d", error);
     DisplayBase::Deinit();
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 1028663..b244a2a 100644
--- a/sdm/libs/core/drm/hw_device_drm.cpp
+++ b/sdm/libs/core/drm/hw_device_drm.cpp
@@ -50,6 +50,7 @@
 #include <utils/sys.h>
 #include <drm/sde_drm.h>
 #include <private/color_params.h>
+#include <utils/rect.h>
 
 #include <algorithm>
 #include <string>
@@ -225,7 +226,7 @@
     HWRotatorSession *hw_rotator_session = &hw_layers->config[i].hw_rotator_session;
     HWRotateInfo *hw_rotate_info = &hw_rotator_session->hw_rotate_info[0];
 
-    if (hw_rotate_info->valid) {
+    if (hw_rotator_session->mode == kRotatorOffline && hw_rotate_info->valid) {
       input_buffer = &hw_rotator_session->output_buffer;
     }
 
@@ -414,7 +415,9 @@
   display_attributes_.h_total = mode.htotal;
   uint32_t h_blanking = mode.htotal - mode.hdisplay;
   display_attributes_.is_device_split =
-      (topology == DRMTopology::DUAL_LM || topology == DRMTopology::DUAL_LM_MERGE);
+      (topology == DRMTopology::DUAL_LM || topology == DRMTopology::DUAL_LM_MERGE ||
+       topology == DRMTopology::DUAL_LM_MERGE_DSC || topology == DRMTopology::DUAL_LM_DSC ||
+       topology == DRMTopology::DUAL_LM_DSCMERGE);
   display_attributes_.h_total += display_attributes_.is_device_split ? h_blanking : 0;
 
   display_attributes_.x_dpi = (FLOAT(mode.hdisplay) * 25.4f) / FLOAT(mm_width);
@@ -574,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 */);
@@ -585,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 */);
@@ -617,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) {
@@ -652,15 +666,13 @@
     HWPipeInfo *left_pipe = &hw_layers->config[i].left_pipe;
     HWPipeInfo *right_pipe = &hw_layers->config[i].right_pipe;
     HWRotatorSession *hw_rotator_session = &hw_layers->config[i].hw_rotator_session;
-    bool needs_rotation = false;
 
     for (uint32_t count = 0; count < 2; count++) {
       HWPipeInfo *pipe_info = (count == 0) ? left_pipe : right_pipe;
       HWRotateInfo *hw_rotate_info = &hw_rotator_session->hw_rotate_info[count];
 
-      if (hw_rotate_info->valid) {
+      if (hw_rotator_session->mode == kRotatorOffline && hw_rotate_info->valid) {
         input_buffer = &hw_rotator_session->output_buffer;
-        needs_rotation = true;
       }
 
       uint32_t fb_id = registry_.GetFbId(input_buffer->planes[0].fd);
@@ -674,21 +686,17 @@
         DRMRect src = {};
         SetRect(pipe_info->src_roi, &src);
         drm_atomic_intf_->Perform(DRMOps::PLANE_SET_SRC_RECT, pipe_id, src);
+        DRMRect rot_dst = {0, 0, 0, 0};
+        if (hw_rotator_session->mode == kRotatorInline && hw_rotate_info->valid) {
+          SetRect(hw_rotate_info->dst_roi, &rot_dst);
+          drm_atomic_intf_->Perform(DRMOps::PLANE_SET_ROTATION_DST_RECT, pipe_id, rot_dst);
+        }
         DRMRect dst = {};
         SetRect(pipe_info->dst_roi, &dst);
         drm_atomic_intf_->Perform(DRMOps::PLANE_SET_DST_RECT, pipe_id, dst);
 
         uint32_t rot_bit_mask = 0;
-        // In case of rotation, rotator handles flips
-        if (!needs_rotation) {
-          if (layer.transform.flip_horizontal) {
-            rot_bit_mask |= UINT32(DRMRotation::FLIP_H);
-          }
-          if (layer.transform.flip_vertical) {
-            rot_bit_mask |= UINT32(DRMRotation::FLIP_V);
-          }
-        }
-
+        SetRotation(layer.transform, hw_rotator_session->mode, &rot_bit_mask);
         drm_atomic_intf_->Perform(DRMOps::PLANE_SET_ROTATION, pipe_id, rot_bit_mask);
         drm_atomic_intf_->Perform(DRMOps::PLANE_SET_H_DECIMATION, pipe_id,
                                   pipe_info->horizontal_decimation);
@@ -715,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);
   }
 }
 
@@ -828,7 +844,7 @@
   for (uint32_t i = 0; i < hw_layer_info.hw_layers.size(); i++) {
     Layer &layer = hw_layer_info.hw_layers.at(i);
     HWRotatorSession *hw_rotator_session = &hw_layers->config[i].hw_rotator_session;
-    if (hw_rotator_session->hw_block_count) {
+    if (hw_rotator_session->mode == kRotatorOffline) {
       hw_rotator_session->output_buffer.release_fence_fd = Sys::dup_(release_fence);
     } else {
       layer.input_buffer.release_fence_fd = Sys::dup_(release_fence);
@@ -874,6 +890,36 @@
   target->bottom = UINT32(source.bottom);
 }
 
+void HWDeviceDRM::SetRotation(LayerTransform transform, const HWRotatorMode &mode,
+                              uint32_t* rot_bit_mask) {
+  // In offline rotation case, rotator will handle flips set via offline rotator interface.
+  if (mode == kRotatorOffline) {
+    *rot_bit_mask = 0;
+    return;
+  }
+
+  // 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) {
+    // 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
+    // c) hflip + rotate 90 clockwise = vflip + rotate 90 counter-clockwise in DRM
+    // d) vflip + rotate 90 clockwise = hflip + rotate 90 counter-clockwise in DRM
+    *rot_bit_mask = UINT32(DRMRotation::ROT_90);
+    transform.flip_horizontal = !transform.flip_horizontal;
+    transform.flip_vertical = !transform.flip_vertical;
+  }
+
+  if (transform.flip_horizontal) {
+    *rot_bit_mask |= UINT32(DRMRotation::FLIP_H);
+  }
+
+  if (transform.flip_vertical) {
+    *rot_bit_mask |= UINT32(DRMRotation::FLIP_V);
+  }
+}
+
 bool HWDeviceDRM::EnableHotPlugDetection(int enable) {
   return true;
 }
@@ -1104,6 +1150,11 @@
   return kErrorNone;
 }
 
+void HWDeviceDRM::GetDRMDisplayToken(sde_drm::DRMDisplayToken *token) const {
+  token->conn_id = token_.conn_id;
+  token->crtc_id = token_.crtc_id;
+}
+
 void HWDeviceDRM::UpdateMixerAttributes() {
   mixer_attributes_.width = display_attributes_.x_pixels;
   mixer_attributes_.height = display_attributes_.y_pixels;
diff --git a/sdm/libs/core/drm/hw_device_drm.h b/sdm/libs/core/drm/hw_device_drm.h
index ad7a3e3..2199426 100644
--- a/sdm/libs/core/drm/hw_device_drm.h
+++ b/sdm/libs/core/drm/hw_device_drm.h
@@ -54,6 +54,7 @@
   virtual ~HWDeviceDRM() {}
   virtual DisplayError Init();
   virtual DisplayError Deinit();
+  void GetDRMDisplayToken(sde_drm::DRMDisplayToken *token) const;
 
  protected:
   // From HWInterface
@@ -119,6 +120,7 @@
   void SetBlending(const LayerBlending &source, sde_drm::DRMBlendType *target);
   void SetSrcConfig(const LayerBuffer &input_buffer, uint32_t *config);
   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);
   DisplayError AtomicCommit(HWLayers *hw_layers);
   void SetupAtomic(HWLayers *hw_layers, bool validate);
diff --git a/sdm/libs/core/drm/hw_events_drm.cpp b/sdm/libs/core/drm/hw_events_drm.cpp
index cea76fc..e6c65f4 100644
--- a/sdm/libs/core/drm/hw_events_drm.cpp
+++ b/sdm/libs/core/drm/hw_events_drm.cpp
@@ -139,10 +139,16 @@
 }
 
 DisplayError HWEventsDRM::Init(int display_type, HWEventHandler *event_handler,
-                               const vector<HWEvent> &event_list) {
+                               const vector<HWEvent> &event_list,
+                               const HWInterface *hw_intf) {
   if (!event_handler)
     return kErrorParameters;
 
+  static_cast<const HWDeviceDRM *>(hw_intf)->GetDRMDisplayToken(&token_);
+
+  DLOGI("Setup event handler for display %d, CRTC %d, Connector %d",
+        display_type, token_.crtc_id, token_.conn_id);
+
   event_handler_ = event_handler;
   poll_fds_.resize(event_list.size());
   event_thread_name_ += " - " + std::to_string(display_type);
diff --git a/sdm/libs/core/drm/hw_events_drm.h b/sdm/libs/core/drm/hw_events_drm.h
index 41050c7..206751b 100644
--- a/sdm/libs/core/drm/hw_events_drm.h
+++ b/sdm/libs/core/drm/hw_events_drm.h
@@ -30,6 +30,7 @@
 #ifndef __HW_EVENTS_DRM_H__
 #define __HW_EVENTS_DRM_H__
 
+#include <drm_interface.h>
 #include <sys/poll.h>
 #include <map>
 #include <string>
@@ -38,6 +39,7 @@
 
 #include "hw_events_interface.h"
 #include "hw_interface.h"
+#include "hw_device_drm.h"
 
 namespace sdm {
 
@@ -46,7 +48,8 @@
 class HWEventsDRM : public HWEventsInterface {
  public:
   virtual DisplayError Init(int display_type, HWEventHandler *event_handler,
-                            const vector<HWEvent> &event_list);
+                            const vector<HWEvent> &event_list,
+                            const HWInterface *hw_intf);
   virtual DisplayError Deinit();
   virtual DisplayError SetEventState(HWEvent event, bool enable, void *aux = nullptr);
 
@@ -87,6 +90,7 @@
   bool exit_threads_ = false;
   uint32_t vsync_index_ = 0;
   bool vsync_enabled_ = true;
+  sde_drm::DRMDisplayToken token_ = {};
 };
 
 }  // namespace sdm
diff --git a/sdm/libs/core/drm/hw_info_drm.cpp b/sdm/libs/core/drm/hw_info_drm.cpp
index 6258d73..8843924 100644
--- a/sdm/libs/core/drm/hw_info_drm.cpp
+++ b/sdm/libs/core/drm/hw_info_drm.cpp
@@ -332,6 +332,7 @@
   hw_resource->max_scale_up = info.max_upscale;
   hw_resource->has_decimation = info.max_horizontal_deci > 1 && info.max_vertical_deci > 1;
   hw_resource->max_pipe_bw = info.max_pipe_bandwidth / kKiloUnit;
+  hw_resource->cache_size = info.cache_size;
 }
 
 void HWInfoDRM::PopulateSupportedFmts(HWSubBlockType sub_blk_type,
@@ -412,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/core/fb/hw_events.cpp b/sdm/libs/core/fb/hw_events.cpp
index c0467f9..7a1988c 100644
--- a/sdm/libs/core/fb/hw_events.cpp
+++ b/sdm/libs/core/fb/hw_events.cpp
@@ -123,7 +123,8 @@
 }
 
 DisplayError HWEvents::Init(int fb_num, HWEventHandler *event_handler,
-                            const vector<HWEvent> &event_list) {
+                            const vector<HWEvent> &event_list,
+                            const HWInterface *hw_intf) {
   if (!event_handler)
     return kErrorParameters;
 
diff --git a/sdm/libs/core/fb/hw_events.h b/sdm/libs/core/fb/hw_events.h
index 3d9cec8..0fa86fb 100644
--- a/sdm/libs/core/fb/hw_events.h
+++ b/sdm/libs/core/fb/hw_events.h
@@ -42,7 +42,8 @@
 class HWEvents : public HWEventsInterface {
  public:
   virtual DisplayError Init(int fb_num, HWEventHandler *event_handler,
-                            const vector<HWEvent> &event_list);
+                            const vector<HWEvent> &event_list,
+                            const HWInterface *hw_intf);
   virtual DisplayError Deinit();
   virtual DisplayError SetEventState(HWEvent event, bool enable, void *aux = nullptr) {
     return kErrorNotSupported;
diff --git a/sdm/libs/core/hw_events_interface.cpp b/sdm/libs/core/hw_events_interface.cpp
index ed62b86..5817cdb 100644
--- a/sdm/libs/core/hw_events_interface.cpp
+++ b/sdm/libs/core/hw_events_interface.cpp
@@ -42,7 +42,7 @@
 
 DisplayError HWEventsInterface::Create(int display_type, HWEventHandler *event_handler,
                                        const std::vector<HWEvent> &event_list,
-                                       HWEventsInterface **intf) {
+                                       const HWInterface *hw_intf, HWEventsInterface **intf) {
   DisplayError error = kErrorNone;
   HWEventsInterface *hw_events = nullptr;
   if (GetDriverType() == DriverType::FB) {
@@ -53,7 +53,7 @@
 #endif
   }
 
-  error = hw_events->Init(display_type, event_handler, event_list);
+  error = hw_events->Init(display_type, event_handler, event_list, hw_intf);
   if (error != kErrorNone) {
     delete hw_events;
   } else {
diff --git a/sdm/libs/core/hw_events_interface.h b/sdm/libs/core/hw_events_interface.h
index 482e077..6f4cebd 100644
--- a/sdm/libs/core/hw_events_interface.h
+++ b/sdm/libs/core/hw_events_interface.h
@@ -33,6 +33,7 @@
 namespace sdm {
 
 class HWEventHandler;
+class HWInterface;
 
 enum HWEvent {
   VSYNC = 0,
@@ -47,12 +48,14 @@
 class HWEventsInterface {
  public:
   virtual DisplayError Init(int display_type, HWEventHandler *event_handler,
-                            const std::vector<HWEvent> &event_list) = 0;
+                            const std::vector<HWEvent> &event_list,
+                            const HWInterface *hw_intf) = 0;
   virtual DisplayError Deinit() = 0;
   virtual DisplayError SetEventState(HWEvent event, bool enable, void *aux = nullptr) = 0;
 
   static DisplayError Create(int display_type, HWEventHandler *event_handler,
-                             const std::vector<HWEvent> &event_list, HWEventsInterface **intf);
+                             const std::vector<HWEvent> &event_list,
+                             const HWInterface *hw_intf, HWEventsInterface **intf);
   static DisplayError Destroy(HWEventsInterface *intf);
 
  protected:
diff --git a/sdm/libs/hwc2/Android.mk b/sdm/libs/hwc2/Android.mk
index 557b55f..81271b0 100644
--- a/sdm/libs/hwc2/Android.mk
+++ b/sdm/libs/hwc2/Android.mk
@@ -19,7 +19,7 @@
 
 LOCAL_SHARED_LIBRARIES        := libsdmcore libqservice libbinder libhardware libhardware_legacy \
                                  libutils libcutils libsync libqdutils libqdMetaData libdl \
-                                 libpowermanager libsdmutils libc++ liblog libgrallocutils \
+                                 libsdmutils libc++ liblog libgrallocutils \
                                  libui libgpu_tonemapper
 
 ifneq ($(TARGET_USES_GRALLOC1), true)
diff --git a/sdm/libs/hwc2/hwc_color_manager.cpp b/sdm/libs/hwc2/hwc_color_manager.cpp
index 9f336a0..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
@@ -28,7 +28,6 @@
 */
 
 #include <dlfcn.h>
-#include <powermanager/IPowerManager.h>
 #include <cutils/sockets.h>
 #include <cutils/native_handle.h>
 #include <utils/String16.h>
@@ -272,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;
@@ -386,17 +384,6 @@
 
     // retrieve system GPU idle timeout value for later to recover.
     mode_mgr->entry_timeout_ = UINT32(HWCDebugHandler::GetIdleTimeoutMs());
-
-    // acquire the binder handle to Android system PowerManager for later use.
-    android::sp<android::IBinder> binder =
-        android::defaultServiceManager()->checkService(android::String16("power"));
-    if (binder == NULL) {
-      DLOGW("Application can't connect to  power manager service");
-      delete mode_mgr;
-      mode_mgr = NULL;
-    } else {
-      mode_mgr->power_mgr_ = android::interface_cast<android::IPowerManager>(binder);
-    }
   }
 
   return mode_mgr;
@@ -407,30 +394,6 @@
     ::close(socket_fd_);
 }
 
-int HWCQDCMModeManager::AcquireAndroidWakeLock(bool enable) {
-  int ret = 0;
-
-  if (enable) {
-    if (wakelock_token_ == NULL) {
-      android::sp<android::IBinder> binder = new android::BBinder();
-      android::status_t status = power_mgr_->acquireWakeLock(
-          (kFullWakeLock | kAcquireCauseWakeup | kONAfterRelease), binder,
-          android::String16(kTagName), android::String16(kPackageName));
-      if (status == android::NO_ERROR) {
-        wakelock_token_ = binder;
-      }
-    }
-  } else {
-    if (wakelock_token_ != NULL && power_mgr_ != NULL) {
-      power_mgr_->releaseWakeLock(wakelock_token_, 0);
-      wakelock_token_.clear();
-      wakelock_token_ = NULL;
-    }
-  }
-
-  return ret;
-}
-
 int HWCQDCMModeManager::EnableActiveFeatures(bool enable,
                                              const HWCQDCMModeManager::ActiveFeatureCMD &cmds,
                                              bool *was_running) {
@@ -486,7 +449,6 @@
 
   ret = EnableActiveFeatures((enable ? false : true), kActiveFeatureCMD[kCABLFeature],
                              &cabl_was_running_);
-  ret = AcquireAndroidWakeLock(enable);
 
   // if enter QDCM mode, disable GPU fallback idle timeout.
   if (hwc_display) {
diff --git a/sdm/libs/hwc2/hwc_color_manager.h b/sdm/libs/hwc2/hwc_color_manager.h
index 32f7f5f..0bfd29f 100644
--- a/sdm/libs/hwc2/hwc_color_manager.h
+++ b/sdm/libs/hwc2/hwc_color_manager.h
@@ -32,7 +32,6 @@
 
 #include <stdlib.h>
 #include <binder/Parcel.h>
-#include <powermanager/IPowerManager.h>
 #include <binder/BinderService.h>
 #include <core/sdm_types.h>
 #include <utils/locker.h>
@@ -94,7 +93,6 @@
   bool cabl_was_running_ = false;
   int socket_fd_ = -1;
   android::sp<android::IBinder> wakelock_token_ = NULL;
-  android::sp<android::IPowerManager> power_mgr_ = NULL;
   uint32_t entry_timeout_ = 0;
   static const char *const kSocketName;
   static const char *const kTagName;
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_ = {};
diff --git a/sdm/libs/utils/formats.cpp b/sdm/libs/utils/formats.cpp
index b7deb18..4b7190b 100644
--- a/sdm/libs/utils/formats.cpp
+++ b/sdm/libs/utils/formats.cpp
@@ -127,5 +127,87 @@
   }
 }
 
+float GetBufferFormatBpp(LayerBufferFormat format) {
+  float bpp = 0.0f;
+  switch (format) {
+    case kFormatARGB8888:
+    case kFormatRGBA8888:
+    case kFormatBGRA8888:
+    case kFormatXRGB8888:
+    case kFormatRGBX8888:
+    case kFormatBGRX8888:
+    case kFormatRGBA8888Ubwc:
+    case kFormatRGBX8888Ubwc:
+    case kFormatRGBA1010102:
+    case kFormatARGB2101010:
+    case kFormatRGBX1010102:
+    case kFormatXRGB2101010:
+    case kFormatBGRA1010102:
+    case kFormatABGR2101010:
+    case kFormatBGRX1010102:
+    case kFormatXBGR2101010:
+    case kFormatRGBA1010102Ubwc:
+    case kFormatRGBX1010102Ubwc:
+      return 4.0f;
+    case kFormatRGB888:
+    case kFormatBGR888:
+    case kFormatYCbCr420P010:
+    case kFormatYCbCr420P010Ubwc:
+      return 3.0f;
+    case kFormatRGB565:
+    case kFormatBGR565:
+    case kFormatRGBA5551:
+    case kFormatRGBA4444:
+    case kFormatBGR565Ubwc:
+    case kFormatYCbCr422H2V1Packed:
+    case kFormatCbYCrY422H2V1Packed:
+    case kFormatYCrCb422H2V1SemiPlanar:
+    case kFormatYCbCr422H2V1SemiPlanar:
+    case kFormatYCbCr420TP10Ubwc:
+    case kFormatYCbCr422H1V2SemiPlanar:
+    case kFormatYCrCb422H1V2SemiPlanar:
+      return 2.0f;
+    case kFormatYCbCr420Planar:
+    case kFormatYCrCb420Planar:
+    case kFormatYCrCb420PlanarStride16:
+    case kFormatYCbCr420SemiPlanar:
+    case kFormatYCrCb420SemiPlanar:
+    case kFormatYCbCr420SemiPlanarVenus:
+    case kFormatYCrCb420SemiPlanarVenus:
+    case kFormatYCbCr420SPVenusUbwc:
+      return 1.5f;
+    default:
+      return 0.0f;
+  }
+
+  return bpp;
+}
+
+DisplayError GetBufferFormatTileSize(LayerBufferFormat format, FormatTileSize *tile_size) {
+  switch (format) {
+  case kFormatYCbCr420SPVenusUbwc:
+    tile_size->tile_width = 32;
+    tile_size->tile_height = 8;
+    tile_size->uv_tile_width = 16;
+    tile_size->uv_tile_height = 8;
+    break;
+  case kFormatYCbCr420TP10Ubwc:
+    tile_size->tile_width = 48;
+    tile_size->tile_height = 4;
+    tile_size->uv_tile_width = 24;
+    tile_size->uv_tile_height = 4;
+    break;
+  case kFormatYCbCr420P010Ubwc:
+    tile_size->tile_width = 32;
+    tile_size->tile_height = 4;
+    tile_size->uv_tile_width = 16;
+    tile_size->uv_tile_height = 4;
+    break;
+  default:
+    return kErrorNotSupported;
+  }
+  return kErrorNone;
+}
+
 }  // namespace sdm
 
diff --git a/sdm/libs/utils/rect.cpp b/sdm/libs/utils/rect.cpp
index b0cd536..c227cb3 100644
--- a/sdm/libs/utils/rect.cpp
+++ b/sdm/libs/utils/rect.cpp
@@ -261,5 +261,47 @@
   return kOrientationLandscape;
 }
 
+DisplayError GetCropAndDestination(const LayerRect &crop, const LayerRect &dst,
+                                   const bool rotated90, float *crop_width,
+                                   float *crop_height, float *dst_width,
+                                   float *dst_height) {
+  if (!IsValid(crop)) {
+    Log(kTagResources, "Invalid crop rect", crop);
+    return kErrorNotSupported;
+  }
+
+  if (!IsValid(dst)) {
+    Log(kTagResources, "Invalid dst rect", dst);
+    return kErrorNotSupported;
+  }
+
+  *crop_width = crop.right - crop.left;
+  *crop_height = crop.bottom - crop.top;
+  if (rotated90) {
+    std::swap(*crop_width, *crop_height);
+  }
+
+  *dst_width = dst.right - dst.left;
+  *dst_height = dst.bottom - dst.top;
+
+  return kErrorNone;
+}
+
+DisplayError GetScaleFactor(const LayerRect &crop, const LayerRect &dst,
+                            bool rotated90, float *scale_x, float *scale_y) {
+  float crop_width = 1.0f, crop_height = 1.0f, dst_width = 1.0f, dst_height = 1.0f;
+
+  DisplayError error = GetCropAndDestination(crop, dst, rotated90, &crop_width, &crop_height,
+                                             &dst_width, &dst_height);
+  if (error != kErrorNone) {
+    return error;
+  }
+
+  *scale_x = crop_width / dst_width;
+  *scale_y = crop_height / dst_height;
+
+  return kErrorNone;
+}
+
 }  // namespace sdm