Merge "cec: Calculate buffer length to protect from overflow"
diff --git a/gpu_tonemapper/Android.mk b/gpu_tonemapper/Android.mk
index 6af401e..769d0ab 100644
--- a/gpu_tonemapper/Android.mk
+++ b/gpu_tonemapper/Android.mk
@@ -8,12 +8,7 @@
 
 include $(CLEAR_VARS)
 LOCAL_MODULE              := libgpu_tonemapper
-
-ifneq ($(TARGET_IS_HEADLESS), true)
-LOCAL_MODULE_PATH_32      := $(TARGET_OUT_VENDOR)/lib
-LOCAL_MODULE_PATH_64      := $(TARGET_OUT_VENDOR)/lib64
-endif
-
+LOCAL_VENDOR_MODULE       := true
 LOCAL_MODULE_TAGS         := optional
 LOCAL_C_INCLUDES          := $(TARGET_OUT_HEADERS)/qcom/display/
 LOCAL_C_INCLUDES          += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr/include
diff --git a/gpu_tonemapper/EGLImageWrapper.cpp b/gpu_tonemapper/EGLImageWrapper.cpp
index 84f4343..dfc16d8 100644
--- a/gpu_tonemapper/EGLImageWrapper.cpp
+++ b/gpu_tonemapper/EGLImageWrapper.cpp
@@ -121,7 +121,7 @@
     }
 
     android::sp<android::GraphicBuffer> graphicBuffer =
-        new android::GraphicBuffer(src->width, src->height, src->format,
+        new android::GraphicBuffer(src->unaligned_width, src->unaligned_height, src->format,
 #ifndef __NOUGAT__
                                    1, // Layer count
 #endif
diff --git a/hdmi_cec/Android.mk b/hdmi_cec/Android.mk
index 6cfb856..a333654 100644
--- a/hdmi_cec/Android.mk
+++ b/hdmi_cec/Android.mk
@@ -3,12 +3,7 @@
 include $(CLEAR_VARS)
 
 LOCAL_MODULE                  := hdmi_cec.$(TARGET_BOARD_PLATFORM)
-
-ifneq ($(TARGET_IS_HEADLESS), true)
-LOCAL_MODULE_PATH_32          := $(TARGET_OUT_VENDOR)/lib
-LOCAL_MODULE_PATH_64          := $(TARGET_OUT_VENDOR)/lib64
-endif
-
+LOCAL_VENDOR_MODULE           := true
 LOCAL_MODULE_RELATIVE_PATH    := hw
 LOCAL_MODULE_TAGS             := optional
 LOCAL_C_INCLUDES              := $(common_includes)
diff --git a/libcopybit/Android.mk b/libcopybit/Android.mk
index 0bce602..6e906c3 100644
--- a/libcopybit/Android.mk
+++ b/libcopybit/Android.mk
@@ -24,12 +24,7 @@
 include $(CLEAR_VARS)
 ifneq ($(TARGET_USES_GRALLOC1), true)
 LOCAL_MODULE                  := copybit.$(TARGET_BOARD_PLATFORM)
-
-ifneq ($(TARGET_IS_HEADLESS), true)
-LOCAL_MODULE_PATH_32          := $(TARGET_OUT_VENDOR)/lib
-LOCAL_MODULE_PATH_64          := $(TARGET_OUT_VENDOR)/lib64
-endif
-
+LOCAL_VENDOR_MODULE           := true
 LOCAL_MODULE_RELATIVE_PATH    := hw
 LOCAL_MODULE_TAGS             := optional
 LOCAL_C_INCLUDES              := $(common_includes) $(kernel_includes)
diff --git a/libdrmutils/Android.mk b/libdrmutils/Android.mk
index 36beea2..ebcfc8a 100644
--- a/libdrmutils/Android.mk
+++ b/libdrmutils/Android.mk
@@ -2,12 +2,7 @@
 include $(CLEAR_VARS)
 
 LOCAL_MODULE                  := libdrmutils
-
-ifneq ($(TARGET_IS_HEADLESS), true)
-LOCAL_MODULE_PATH_32          := $(TARGET_OUT_VENDOR)/lib
-LOCAL_MODULE_PATH_64          := $(TARGET_OUT_VENDOR)/lib64
-endif
-
+LOCAL_VENDOR_MODULE           := true
 LOCAL_MODULE_TAGS             := optional
 LOCAL_C_INCLUDES              := external/libdrm \
                                  $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr/include
diff --git a/libdrmutils/drm_interface.h b/libdrmutils/drm_interface.h
index d41181f..46ab782 100644
--- a/libdrmutils/drm_interface.h
+++ b/libdrmutils/drm_interface.h
@@ -39,6 +39,9 @@
 #include "xf86drmMode.h"
 
 namespace sde_drm {
+
+typedef std::map<std::pair<uint32_t, uint64_t>, float> CompRatioMap;
+
 /*
  * Drm Atomic Operation Codes
  */
@@ -141,6 +144,24 @@
    */
   CRTC_SET_OUTPUT_FENCE_OFFSET,
   /*
+   * Op: Sets overall SDE core clock
+   * Arg: uint32_t - CRTC ID
+   *      uint32_t - core_clk
+   */
+  CRTC_SET_CORE_CLK,
+   /*
+   * Op: Sets overall SDE core average bandwidth
+   * Arg: uint32_t - CRTC ID
+   *      uint32_t - core_ab
+   */
+  CRTC_SET_CORE_AB,
+   /*
+   * Op: Sets overall SDE core instantaneous bandwidth
+   * Arg: uint32_t - CRTC ID
+   *      uint32_t - core_ib
+   */
+  CRTC_SET_CORE_IB,
+  /*
    * Op: Returns release fence for this frame. Should be called after Commit() on
    * DRMAtomicReqInterface.
    * Arg: uint32_t - CRTC ID
@@ -154,6 +175,13 @@
    */
   CRTC_SET_POST_PROC,
   /*
+   * Op: Sets CRTC ROIs.
+   * Arg: uint32_t - CRTC ID
+   *      uint32_t - number of ROIs
+   *      DRMRect * - Array of CRTC ROIs
+   */
+  CRTC_SET_ROI,
+  /*
    * Op: Returns retire fence for this commit. Should be called after Commit() on
    * DRMAtomicReqInterface.
    * Arg: uint32_t - Connector ID
@@ -178,6 +206,13 @@
    *      uint32_t - Power Mode
    */
   CONNECTOR_SET_POWER_MODE,
+  /*
+   * Op: Sets panel ROIs.
+   * Arg: uint32_t - Connector ID
+   *      uint32_t - number of ROIs
+   *      DRMRect * - Array of Connector ROIs
+   */
+  CONNECTOR_SET_ROI,
 };
 
 enum struct DRMRotation {
@@ -239,6 +274,21 @@
   uint32_t max_blend_stages;
   QSEEDVersion qseed_version;
   SmartDMARevision smart_dma_rev;
+  float ib_fudge_factor;
+  float clk_fudge_factor;
+  uint32_t dest_scale_prefill_lines;
+  uint32_t undersized_prefill_lines;
+  uint32_t macrotile_prefill_lines;
+  uint32_t nv12_prefill_lines;
+  uint32_t linear_prefill_lines;
+  uint32_t downscale_prefill_lines;
+  uint32_t extra_prefill_lines;
+  uint32_t amortized_threshold;
+  uint64_t max_bandwidth_low;
+  uint64_t max_bandwidth_high;
+  uint32_t max_sde_clk;
+  CompRatioMap comp_ratio_rt_map;
+  CompRatioMap comp_ratio_nrt_map;
 };
 
 enum struct DRMPlaneType {
@@ -263,6 +313,7 @@
   uint32_t max_downscale;
   uint32_t max_horizontal_deci;
   uint32_t max_vertical_deci;
+  uint64_t max_pipe_bandwidth;
 };
 
 // All DRM Planes as map<Plane_id , plane_type_info> listed from highest to lowest priority
@@ -298,6 +349,15 @@
   std::vector<std::pair<uint32_t, uint64_t>> formats_supported;
   // Valid only if type is DRM_MODE_CONNECTOR_VIRTUAL
   uint32_t max_linewidth;
+  // Valid only if mode is command
+  int num_roi;
+  int xstart;
+  int ystart;
+  int walign;
+  int halign;
+  int wmin;
+  int hmin;
+  bool roi_merge;
 };
 
 /* Identifier token for a display */
@@ -414,7 +474,7 @@
    * Will query post propcessing feature info of a CRTC.
    * [output]: DRMPPFeatureInfo: CRTC post processing feature info
    */
-   virtual void GetCrtcPPInfo(uint32_t crtc_id, DRMPPFeatureInfo &info) = 0;
+  virtual void GetCrtcPPInfo(uint32_t crtc_id, DRMPPFeatureInfo &info) = 0;
   /*
    * Register a logical display to receive a token.
    * Each display pipeline in DRM is identified by its CRTC and Connector(s).
diff --git a/libgralloc/Android.mk b/libgralloc/Android.mk
index 76be57d..86c0f04 100644
--- a/libgralloc/Android.mk
+++ b/libgralloc/Android.mk
@@ -18,12 +18,7 @@
 include $(CLEAR_VARS)
 
 LOCAL_MODULE                  := gralloc.$(TARGET_BOARD_PLATFORM)
-
-ifneq ($(TARGET_IS_HEADLESS), true)
-LOCAL_MODULE_PATH_32          := $(TARGET_OUT_VENDOR)/lib
-LOCAL_MODULE_PATH_64          := $(TARGET_OUT_VENDOR)/lib64
-endif
-
+LOCAL_VENDOR_MODULE           := true
 LOCAL_MODULE_RELATIVE_PATH    := hw
 LOCAL_MODULE_TAGS             := optional
 LOCAL_C_INCLUDES              := $(common_includes) $(kernel_includes)
@@ -44,12 +39,7 @@
 include $(CLEAR_VARS)
 
 LOCAL_MODULE                  := libmemalloc
-
-ifneq ($(TARGET_IS_HEADLESS), true)
-LOCAL_MODULE_PATH_32          := $(TARGET_OUT_VENDOR)/lib
-LOCAL_MODULE_PATH_64          := $(TARGET_OUT_VENDOR)/lib64
-endif
-
+LOCAL_VENDOR_MODULE           := true
 LOCAL_MODULE_TAGS             := optional
 LOCAL_C_INCLUDES              := $(common_includes) $(kernel_includes)
 LOCAL_HEADER_LIBRARIES        := display_headers
diff --git a/libgralloc1/Android.mk b/libgralloc1/Android.mk
index d8ee429..f4d4ba7 100644
--- a/libgralloc1/Android.mk
+++ b/libgralloc1/Android.mk
@@ -4,12 +4,7 @@
 include $(CLEAR_VARS)
 
 LOCAL_MODULE                  := gralloc.$(TARGET_BOARD_PLATFORM)
-
-ifneq ($(TARGET_IS_HEADLESS), true)
-LOCAL_MODULE_PATH_32          := $(TARGET_OUT_VENDOR)/lib
-LOCAL_MODULE_PATH_64          := $(TARGET_OUT_VENDOR)/lib64
-endif
-
+LOCAL_VENDOR_MODULE           := true
 LOCAL_MODULE_RELATIVE_PATH    := hw
 LOCAL_MODULE_TAGS             := optional
 LOCAL_C_INCLUDES              := $(common_includes) \
@@ -32,10 +27,7 @@
 #libgrallocutils
 include $(CLEAR_VARS)
 LOCAL_MODULE                  := libgrallocutils
-ifneq ($(TARGET_IS_HEADLESS), true)
-LOCAL_MODULE_PATH_32          := $(TARGET_OUT_VENDOR)/lib
-LOCAL_MODULE_PATH_64          := $(TARGET_OUT_VENDOR)/lib64
-endif
+LOCAL_VENDOR_MODULE           := true
 LOCAL_MODULE_TAGS             := optional
 LOCAL_C_INCLUDES              := $(common_includes) $(kernel_includes)
 LOCAL_HEADER_LIBRARIES        := display_headers
diff --git a/libgralloc1/gr_adreno_info.cpp b/libgralloc1/gr_adreno_info.cpp
index 1d0ed48..ecac238 100644
--- a/libgralloc1/gr_adreno_info.cpp
+++ b/libgralloc1/gr_adreno_info.cpp
@@ -115,6 +115,7 @@
   int bpp = 4;
   switch (format) {
     case HAL_PIXEL_FORMAT_RGB_888:
+    case HAL_PIXEL_FORMAT_BGR_888:
       bpp = 3;
       break;
     case HAL_PIXEL_FORMAT_RGB_565:
diff --git a/libgralloc1/gr_utils.cpp b/libgralloc1/gr_utils.cpp
index 444de8c..28fe4f6 100644
--- a/libgralloc1/gr_utils.cpp
+++ b/libgralloc1/gr_utils.cpp
@@ -64,6 +64,7 @@
     case HAL_PIXEL_FORMAT_BGRX_1010102:
     case HAL_PIXEL_FORMAT_XBGR_2101010:
     case HAL_PIXEL_FORMAT_RGBA_FP16:
+    case HAL_PIXEL_FORMAT_BGR_888:
       return true;
     default:
       break;
@@ -131,6 +132,7 @@
       bpp = 4;
       break;
     case HAL_PIXEL_FORMAT_RGB_888:
+    case HAL_PIXEL_FORMAT_BGR_888:
       bpp = 3;
       break;
     case HAL_PIXEL_FORMAT_RGB_565:
@@ -240,6 +242,7 @@
     case HAL_PIXEL_FORMAT_YCrCb_422_SP:
     case HAL_PIXEL_FORMAT_YCbCr_422_I:
     case HAL_PIXEL_FORMAT_YCrCb_422_I:
+    case HAL_PIXEL_FORMAT_CbYCrY_422_I:
       if (width & 1) {
         ALOGE("width is odd for the YUV422_SP format");
         return 0;
@@ -403,7 +406,16 @@
       ycbcr->cstride = cstride;
       ycbcr->chroma_step = 1;
       break;
-
+    case HAL_PIXEL_FORMAT_CbYCrY_422_I:
+      ystride = width * 2;
+      cstride = 0;
+      ycbcr->y  = reinterpret_cast<void *>(hnd->base);
+      ycbcr->cr = NULL;
+      ycbcr->cb = NULL;
+      ycbcr->ystride = ystride;
+      ycbcr->cstride = 0;
+      ycbcr->chroma_step = 0;
+      break;
       // Unsupported formats
     case HAL_PIXEL_FORMAT_YCbCr_422_I:
     case HAL_PIXEL_FORMAT_YCrCb_422_I:
diff --git a/libgralloc1/gralloc_priv.h b/libgralloc1/gralloc_priv.h
index ea2d57c..ba156b6 100644
--- a/libgralloc1/gralloc_priv.h
+++ b/libgralloc1/gralloc_priv.h
@@ -129,6 +129,9 @@
 #define HAL_PIXEL_FORMAT_YCbCr_420_P010 0x11F
 #define HAL_PIXEL_FORMAT_YCbCr_420_P010_UBWC 0x124
 
+#define HAL_PIXEL_FORMAT_CbYCrY_422_I            0x120
+#define HAL_PIXEL_FORMAT_BGR_888                 0x121
+
 #define HAL_PIXEL_FORMAT_INTERLACE 0x180
 
 // v4l2_fourcc('Y', 'U', 'Y', 'L'). 24 bpp YUYV 4:2:2 10 bit per component
diff --git a/liblight/Android.mk b/liblight/Android.mk
index 1fa05f7..f627286 100644
--- a/liblight/Android.mk
+++ b/liblight/Android.mk
@@ -27,10 +27,6 @@
 LOCAL_CLANG  := true
 LOCAL_MODULE := lights.$(TARGET_BOARD_PLATFORM)
 LOCAL_MODULE_TAGS := optional
-
-ifneq ($(TARGET_IS_HEADLESS), true)
-LOCAL_MODULE_PATH_32          := $(TARGET_OUT_VENDOR)/lib
-LOCAL_MODULE_PATH_64          := $(TARGET_OUT_VENDOR)/lib64
-endif
+LOCAL_VENDOR_MODULE := true
 
 include $(BUILD_SHARED_LIBRARY)
diff --git a/libmemtrack/Android.mk b/libmemtrack/Android.mk
index 12475c3..d4014bb 100644
--- a/libmemtrack/Android.mk
+++ b/libmemtrack/Android.mk
@@ -19,12 +19,7 @@
 include $(CLEAR_VARS)
 
 LOCAL_MODULE_RELATIVE_PATH := hw
-
-ifneq ($(TARGET_IS_HEADLESS), true)
-LOCAL_MODULE_PATH_32          := $(TARGET_OUT_VENDOR)/lib
-LOCAL_MODULE_PATH_64          := $(TARGET_OUT_VENDOR)/lib64
-endif
-
+LOCAL_VENDOR_MODULE := true
 LOCAL_C_INCLUDES += hardware/libhardware/include
 LOCAL_CFLAGS := -Wconversion -Wall -Werror -Wno-sign-conversion
 LOCAL_CLANG  := true
diff --git a/libqdutils/Android.mk b/libqdutils/Android.mk
index c7f428b..7afd00f 100644
--- a/libqdutils/Android.mk
+++ b/libqdutils/Android.mk
@@ -3,12 +3,7 @@
 include $(CLEAR_VARS)
 
 LOCAL_MODULE                  := libqdutils
-
-ifneq ($(TARGET_IS_HEADLESS), true)
-LOCAL_MODULE_PATH_32          := $(TARGET_OUT_VENDOR)/lib
-LOCAL_MODULE_PATH_64          := $(TARGET_OUT_VENDOR)/lib64
-endif
-
+LOCAL_VENDOR_MODULE           := true
 LOCAL_MODULE_TAGS             := optional
 LOCAL_SHARED_LIBRARIES        := $(common_libs) libbinder libqservice
 LOCAL_C_INCLUDES              := $(common_includes) $(kernel_includes)
@@ -36,11 +31,6 @@
 
 LOCAL_MODULE_TAGS               := optional
 LOCAL_MODULE                    := libqdMetaData
-
-ifneq ($(TARGET_IS_HEADLESS), true)
-LOCAL_MODULE_PATH_32          := $(TARGET_OUT_VENDOR)/lib
-LOCAL_MODULE_PATH_64          := $(TARGET_OUT_VENDOR)/lib64
-endif
-
+LOCAL_VENDOR_MODULE             := true
 include $(BUILD_SHARED_LIBRARY)
 
diff --git a/libqservice/Android.mk b/libqservice/Android.mk
index 0f77d4f..9cfdf97 100644
--- a/libqservice/Android.mk
+++ b/libqservice/Android.mk
@@ -3,12 +3,7 @@
 include $(CLEAR_VARS)
 
 LOCAL_MODULE                  := libqservice
-
-ifneq ($(TARGET_IS_HEADLESS), true)
-LOCAL_MODULE_PATH_32          := $(TARGET_OUT_VENDOR)/lib
-LOCAL_MODULE_PATH_64          := $(TARGET_OUT_VENDOR)/lib64
-endif
-
+LOCAL_VENDOR_MODULE           := true
 LOCAL_MODULE_TAGS             := optional
 LOCAL_C_INCLUDES              := $(common_includes) $(kernel_includes)
 LOCAL_SHARED_LIBRARIES        := $(common_libs) libbinder
diff --git a/sdm/include/core/buffer_allocator.h b/sdm/include/core/buffer_allocator.h
index ccb9a1b..6d77bcd 100644
--- a/sdm/include/core/buffer_allocator.h
+++ b/sdm/include/core/buffer_allocator.h
@@ -54,6 +54,7 @@
   bool cache = false;                         //!< Specifies whether the buffer needs to be cache.
   bool secure_camera = false;                 //!< Specifies buffer to be allocated from specific
                                               //!< secure heap and with a specific alignment.
+  bool gfx_client = false;                    //!< Specifies whether buffer is used by gfx.
 };
 
 /*! @brief Holds the information about the allocated buffer.
diff --git a/sdm/include/core/debug_interface.h b/sdm/include/core/debug_interface.h
index f4e3fc3..da21944 100644
--- a/sdm/include/core/debug_interface.h
+++ b/sdm/include/core/debug_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
@@ -49,6 +49,7 @@
   kTagRotator,          //!< Debug log is tagged for rotator.
   kTagScalar,           //!< Debug log is tagged for Scalar Helper.
   kTagQDCM,             //!< Debug log is tagged for display QDCM color managing.
+  kTagQOSClient,        //!< Debug log is tagged for Qos client
 };
 
 /*! @brief Display debug handler class.
diff --git a/sdm/include/core/display_interface.h b/sdm/include/core/display_interface.h
index f4054bb..524141e 100644
--- a/sdm/include/core/display_interface.h
+++ b/sdm/include/core/display_interface.h
@@ -455,11 +455,13 @@
 
   /*! @brief Method to set the refresh rate of a display.
 
-    @param[in] new refresh rate of the display.
+    @param[in] refresh_rate new refresh rate of the display.
+
+    @param[in] final_rate indicates whether refresh rate is final rate or can be changed by sdm
 
     @return \link DisplayError \endlink
   */
-  virtual DisplayError SetRefreshRate(uint32_t refresh_rate) = 0;
+  virtual DisplayError SetRefreshRate(uint32_t refresh_rate, bool final_rate) = 0;
 
   /*! @brief Method to query whether scanning is support for the HDMI display.
 
diff --git a/sdm/include/core/layer_stack.h b/sdm/include/core/layer_stack.h
index 6ee2e75..b8977e2 100644
--- a/sdm/include/core/layer_stack.h
+++ b/sdm/include/core/layer_stack.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:
@@ -85,8 +85,8 @@
   kCompositionSDE,          //!< This layer will be composed by SDE. It must not be composed by
                             //!< GPU or Blit.
 
-  kCompositionHWCursor,     //!< This layer will be composed by SDE using HW Cursor. It must not be
-                            //!< composed by GPU or Blit.
+  kCompositionCursor,       // This cursor layer can receive async position updates irrespective of
+                            // dedicated h/w cursor usage. It must not be composed by GPU or Blit
 
   kCompositionHybrid,       //!< This layer will be drawn by a blit engine and SDE together.
                             //!< Display device will split the layer, update the blit rectangle
@@ -189,6 +189,7 @@
     struct {
       uint32_t tone_map : 1;  //!< This flag will be set by SDM when the layer needs tone map
       uint32_t secure: 1;  //!< This flag will be set by SDM when the layer must be secure
+      uint32_t flip_buffer: 1;  //!< This flag will be set by SDM when the layer needs FBT flip
     };
     uint32_t request_flags = 0;  //!< For initialization purpose only.
                                  //!< Shall not be refered directly.
diff --git a/sdm/include/private/extension_interface.h b/sdm/include/private/extension_interface.h
index a10a2c8..2e5bd49 100644
--- a/sdm/include/private/extension_interface.h
+++ b/sdm/include/private/extension_interface.h
@@ -69,9 +69,9 @@
   virtual DisplayError DestroyStrategyExtn(StrategyInterface *interface) = 0;
 
   virtual DisplayError CreateResourceExtn(const HWResourceInfo &hw_resource_info,
-                                          ResourceInterface **interface,
                                           BufferAllocator *buffer_allocator,
-                                          BufferSyncHandler *buffer_sync_handler) = 0;
+                                          BufferSyncHandler *buffer_sync_handler,
+                                          ResourceInterface **interface) = 0;
   virtual DisplayError DestroyResourceExtn(ResourceInterface *interface) = 0;
   virtual DisplayError CreateDppsControlExtn(DppsControlInterface **dpps_control_interface,
                                              SocketHandler *socket_handler) = 0;
diff --git a/sdm/include/private/hw_info_types.h b/sdm/include/private/hw_info_types.h
index 4ab50a2..cdfec2e 100644
--- a/sdm/include/private/hw_info_types.h
+++ b/sdm/include/private/hw_info_types.h
@@ -36,8 +36,10 @@
 namespace sdm {
 using std::string;
 
-const int kMaxSDELayers = 16;   // Maximum number of layers that can be handled by hardware in a
-                                // given layer stack.
+const int kMaxSDELayers = 16;   // Maximum number of layers that can be handled by MDP5 hardware
+                                // in a given layer stack.
+const int kMaxBlitLayers = 32;   // Maximum number of layers that can be handled by MDP3 hardware
+                                // in a given layer stack.
 #define MAX_PLANES 4
 
 #define MAX_DETAIL_ENHANCE_CURVE 3
@@ -109,11 +111,12 @@
 };
 
 typedef std::map<HWSubBlockType, std::vector<LayerBufferFormat>> FormatsMap;
+typedef std::map<LayerBufferFormat, float> CompRatioMap;
 
 struct HWDynBwLimitInfo {
   uint32_t cur_mode = kBwDefault;
-  uint32_t total_bw_limit[kBwModeMax] = { 0 };
-  uint32_t pipe_bw_limit[kBwModeMax] = { 0 };
+  uint64_t total_bw_limit[kBwModeMax] = { 0 };
+  uint64_t pipe_bw_limit[kBwModeMax] = { 0 };
 };
 
 struct HWPipeCaps {
@@ -140,6 +143,7 @@
   uint32_t max_input_width = 0;
   uint32_t max_output_width = 0;
   uint32_t max_scale_up = 1;
+  uint32_t prefill_lines = 4;
 };
 
 enum SmartDMARevision {
@@ -167,7 +171,7 @@
   uint32_t max_mixer_width = 2048;
   uint32_t max_pipe_width = 2048;
   uint32_t max_cursor_size = 0;
-  uint32_t max_pipe_bw =  0;
+  uint64_t max_pipe_bw =  0;
   uint32_t max_sde_clk = 0;
   float clk_fudge_factor = 1.0f;
   uint32_t macrotile_nv12_factor = 0;
@@ -183,7 +187,6 @@
   bool has_macrotile = false;
   bool has_non_scalar_rgb = false;
   bool is_src_split = false;
-  bool perf_calc = false;
   bool has_dyn_bw_support = false;
   bool separate_rotator = false;
   bool has_qseed3 = false;
@@ -198,6 +201,11 @@
   bool has_avr = false;
   bool has_hdr = false;
   SmartDMARevision smart_dma_rev = SmartDMARevision::V1;
+  float ib_fudge_factor = 1.0f;
+  uint32_t undersized_prefill_lines = 0;
+  CompRatioMap comp_ratio_rt_map;
+  CompRatioMap comp_ratio_nrt_map;
+
   void Reset() { *this = HWResourceInfo(); }
 };
 
@@ -430,6 +438,8 @@
 };
 
 struct HWPipeInfo {
+  HWPipeInfo *pair = NULL;
+  uint8_t rect = 255;
   uint32_t pipe_id = 0;
   HWSubBlockType sub_block_type = kHWSubBlockMax;
   LayerRect src_roi;
@@ -482,20 +492,20 @@
   std::vector<LayerRect> left_frame_roi = {};   // Left ROI.
   std::vector<LayerRect> right_frame_roi = {};  // Right ROI.
   LayerRect partial_fb_roi = {};   // Damaged area in framebuffer.
-
   bool roi_split = false;          // Indicates separated left and right ROI
-
-  bool use_hw_cursor = false;      // Indicates that HWCursor pipe needs to be used for cursor layer
+  bool async_cursor_updates = false;  // Cursor layer allowed to have async updates
   DestScaleInfoMap dest_scale_info_map = {};
   HWHDRLayerInfo hdr_layer_info = {};
+  Handle pvt_data = NULL;   // Private data used by sdm extension only.
 };
 
 struct HWLayers {
   HWLayersInfo info;
   HWLayerConfig config[kMaxSDELayers];
   float output_compression = 1.0f;
-  uint32_t bandwidth = 0;
-  uint32_t clock = 0;
+  uint64_t ab_bps = 0;
+  uint64_t ib_bps = 0;
+  uint32_t clock_hz = 0;
   HWAVRInfo hw_avr_info = {};
 };
 
diff --git a/sdm/include/private/partial_update_interface.h b/sdm/include/private/partial_update_interface.h
index b753587..a1c2382 100644
--- a/sdm/include/private/partial_update_interface.h
+++ b/sdm/include/private/partial_update_interface.h
@@ -35,8 +35,6 @@
 
 struct PUConstraints {
   bool enable = true;             //!< If this is set, PU will be enabled or it will be disabled
-  bool enable_cursor_pu = false;  //!< If this is set, PU will consider cursor layer in the layer
-                                   //!< stack for cursor partial update
 };
 
 class PartialUpdateInterface {
diff --git a/sdm/include/private/resource_interface.h b/sdm/include/private/resource_interface.h
index e32af41..e140c33 100644
--- a/sdm/include/private/resource_interface.h
+++ b/sdm/include/private/resource_interface.h
@@ -58,8 +58,6 @@
   virtual DisplayError ValidateScaling(const LayerRect &crop, const LayerRect &dst,
                                        bool rotate90, BufferLayout layout,
                                        bool use_rotator_downscale) = 0;
-  virtual DisplayError ValidateCursorConfig(Handle display_ctx, const Layer *layer,
-                                            bool is_top) = 0;
   virtual DisplayError ValidateCursorPosition(Handle display_ctx, HWLayers *hw_layers,
                                               int x, int y) = 0;
   virtual DisplayError SetMaxBandwidthMode(HWBwModes mode) = 0;
@@ -67,8 +65,6 @@
   virtual DisplayError SetDetailEnhancerData(Handle display_ctx,
                                              const DisplayDetailEnhancerData &de_data) = 0;
   virtual DisplayError Perform(int cmd, ...) = 0;
-
- protected:
   virtual ~ResourceInterface() { }
 };
 
diff --git a/sdm/include/private/strategy_interface.h b/sdm/include/private/strategy_interface.h
index 6aec9cf..1174e7f 100644
--- a/sdm/include/private/strategy_interface.h
+++ b/sdm/include/private/strategy_interface.h
@@ -36,9 +36,6 @@
                             //!< that requires minimum number of pipe for the current frame. i.e.,
                             //!< video only composition, secure only composition or GPU composition
 
-  bool use_cursor = false;  //!< If this is set, strategy manager will configure cursor layer in the
-                            //!< layer stack as hw cursor else it will be treated as a normal layer
-
   uint32_t max_layers = kMaxSDELayers;  //!< Maximum number of layers that shall be programmed
                                         //!< on hardware for the given layer stack.
 };
@@ -56,7 +53,6 @@
   virtual DisplayError Purge() = 0;
   virtual DisplayError SetIdleTimeoutMs(uint32_t active_ms) = 0;
 
- protected:
   virtual ~StrategyInterface() { }
 };
 
diff --git a/sdm/include/utils/factory.h b/sdm/include/utils/factory.h
new file mode 100644
index 0000000..f77a299
--- /dev/null
+++ b/sdm/include/utils/factory.h
@@ -0,0 +1,63 @@
+/*
+* Copyright (c) 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:
+*   * Redistributions of source code must retain the above copyright
+*     notice, this list of conditions and the following disclaimer.
+*   * Redistributions in binary form must reproduce the above
+*     copyright notice, this list of conditions and the following
+*     disclaimer in the documentation and/or other materials provided
+*     with the distribution.
+*   * Neither the name of The Linux Foundation nor the names of its
+*     contributors may be used to endorse or promote products derived
+*     from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+* ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef __FACTORY_H__
+#define __FACTORY_H__
+
+#include <utility>
+#include <map>
+#include <string>
+
+namespace sdm {
+
+template <class Creator>
+class Factory {
+ public:
+  int Add(const std::string &name, const Creator &creator) {
+    map_.insert(std::pair<std::string, Creator>(name, creator));
+
+    return 0;
+  }
+
+  Creator Get(const std::string &name) {
+    typename std::map<std::string, Creator>::iterator it = map_.find(name);
+    if (it != map_.end()) {
+      return it->second;
+    }
+
+    return nullptr;
+  }
+
+ private:
+  std::map<std::string, Creator> map_;
+};
+
+}  // namespace sdm
+
+#endif  // __FACTORY_H__
diff --git a/sdm/libs/core/Android.mk b/sdm/libs/core/Android.mk
index 47e6f3e..1d55d96 100644
--- a/sdm/libs/core/Android.mk
+++ b/sdm/libs/core/Android.mk
@@ -3,12 +3,7 @@
 include $(LOCAL_PATH)/../../../common.mk
 
 LOCAL_MODULE                  := libsdmcore
-
-ifneq ($(TARGET_IS_HEADLESS), true)
-LOCAL_MODULE_PATH_32          := $(TARGET_OUT_VENDOR)/lib
-LOCAL_MODULE_PATH_64          := $(TARGET_OUT_VENDOR)/lib64
-endif
-
+LOCAL_VENDOR_MODULE           := true
 LOCAL_MODULE_TAGS             := optional
 LOCAL_C_INCLUDES              := $(common_includes) $(kernel_includes)
 LOCAL_HEADER_LIBRARIES        := display_headers
diff --git a/sdm/libs/core/comp_manager.cpp b/sdm/libs/core/comp_manager.cpp
index 578d04a..d18b5b8 100644
--- a/sdm/libs/core/comp_manager.cpp
+++ b/sdm/libs/core/comp_manager.cpp
@@ -33,12 +33,6 @@
 
 namespace sdm {
 
-static bool NeedsScaledComposition(const DisplayConfigVariableInfo &fb_config,
-                                   const HWMixerAttributes &mixer_attributes) {
-  return ((fb_config.x_pixels != mixer_attributes.width) ||
-          (fb_config.y_pixels != mixer_attributes.height));
-}
-
 DisplayError CompManager::Init(const HWResourceInfo &hw_res_info,
                                ExtensionInterface *extension_intf,
                                BufferAllocator *buffer_allocator,
@@ -49,8 +43,8 @@
   DisplayError error = kErrorNone;
 
   if (extension_intf) {
-    error = extension_intf->CreateResourceExtn(hw_res_info, &resource_intf_, buffer_allocator,
-                                               buffer_sync_handler);
+    error = extension_intf->CreateResourceExtn(hw_res_info, buffer_allocator, buffer_sync_handler,
+                                               &resource_intf_);
     extension_intf->CreateDppsControlExtn(&dpps_ctrl_intf_, socket_handler);
   } else {
     error = ResourceDefault::CreateResourceDefault(hw_res_info, &resource_intf_);
@@ -135,7 +129,6 @@
     max_sde_ext_layers_ = UINT32(Debug::GetExtMaxlayers());
   }
 
-  display_comp_ctx->scaled_composition = NeedsScaledComposition(fb_config, mixer_attributes);
   DLOGV_IF(kTagCompManager, "registered display bit mask 0x%x, configured display bit mask 0x%x, " \
            "display type %d", registered_displays_.to_ulong(), configured_displays_.to_ulong(),
            display_comp_ctx->display_type);
@@ -214,8 +207,6 @@
     }
   }
 
-  display_comp_ctx->scaled_composition = NeedsScaledComposition(fb_config, mixer_attributes);
-
   return error;
 }
 
@@ -225,7 +216,6 @@
   StrategyConstraints *constraints = &display_comp_ctx->constraints;
 
   constraints->safe_mode = safe_mode_;
-  constraints->use_cursor = false;
   constraints->max_layers = max_layers_;
 
   // Limit 2 layer SDE Comp if its not a Primary Display.
@@ -242,9 +232,6 @@
     constraints->safe_mode = true;
   }
 
-  // Set use_cursor constraint to Strategy
-  constraints->use_cursor = display_comp_ctx->valid_cursor;
-
   // TODO(user): App layer count will change for hybrid composition
   uint32_t app_layer_count = UINT32(hw_layers->info.stack->layers.size()) - 1;
   if (display_comp_ctx->idle_fallback || display_comp_ctx->thermal_fallback_) {
@@ -262,11 +249,6 @@
   SCOPE_LOCK(locker_);
   DisplayCompositionContext *display_comp_ctx =
                              reinterpret_cast<DisplayCompositionContext *>(display_ctx);
-  display_comp_ctx->valid_cursor = SupportLayerAsCursor(display_comp_ctx, hw_layers);
-
-  // pu constraints
-  display_comp_ctx->pu_constraints.enable_cursor_pu = display_comp_ctx->valid_cursor;
-
   display_comp_ctx->strategy->Start(&hw_layers->info, &display_comp_ctx->max_strategies,
                                     display_comp_ctx->pu_constraints);
   display_comp_ctx->remaining_strategies = display_comp_ctx->max_strategies;
@@ -486,39 +468,6 @@
   return resource_intf_->ValidateCursorPosition(display_resource_ctx, hw_layers, x, y);
 }
 
-bool CompManager::SupportLayerAsCursor(Handle comp_handle, HWLayers *hw_layers) {
-  DisplayCompositionContext *display_comp_ctx =
-                             reinterpret_cast<DisplayCompositionContext *>(comp_handle);
-  Handle &display_resource_ctx = display_comp_ctx->display_resource_ctx;
-  LayerStack *layer_stack = hw_layers->info.stack;
-  bool supported = false;
-  int32_t gpu_index = -1;
-
-  // HW Cursor cannot be used, if Display configuration needs scaled composition.
-  if (display_comp_ctx->scaled_composition || !layer_stack->flags.cursor_present) {
-    return supported;
-  }
-
-  for (int32_t i = INT32(layer_stack->layers.size() - 1); i >= 0; i--) {
-    Layer *layer = layer_stack->layers.at(UINT32(i));
-    if (layer->composition == kCompositionGPUTarget) {
-      gpu_index = i;
-      break;
-    }
-  }
-  if (gpu_index <= 0) {
-    return supported;
-  }
-  Layer *cursor_layer = layer_stack->layers.at(UINT32(gpu_index) - 1);
-  if (cursor_layer->flags.cursor && !cursor_layer->flags.skip &&
-      resource_intf_->ValidateCursorConfig(display_resource_ctx,
-                                           cursor_layer, true) == kErrorNone) {
-    supported = true;
-  }
-
-  return supported;
-}
-
 DisplayError CompManager::SetMaxBandwidthMode(HWBwModes mode) {
   if ((hw_res_info_.has_dyn_bw_support == false) || (mode >= kBwModeMax)) {
     return kErrorNotSupported;
diff --git a/sdm/libs/core/comp_manager.h b/sdm/libs/core/comp_manager.h
index c8646fe..c6b8972 100644
--- a/sdm/libs/core/comp_manager.h
+++ b/sdm/libs/core/comp_manager.h
@@ -67,7 +67,6 @@
   void ControlPartialUpdate(Handle display_ctx, bool enable);
   DisplayError ValidateScaling(const LayerRect &crop, const LayerRect &dst, bool rotate90);
   DisplayError ValidateCursorPosition(Handle display_ctx, HWLayers *hw_layers, int x, int y);
-  bool SupportLayerAsCursor(Handle display_ctx, HWLayers *hw_layers);
   bool SetDisplayState(Handle display_ctx, DisplayState state, DisplayType display_type);
   DisplayError SetMaxBandwidthMode(HWBwModes mode);
   DisplayError GetScaleLutConfig(HWScaleLutInfo *lut_info);
@@ -97,9 +96,7 @@
     // Using primary panel flag of hw panel to configure Constraints. We do not need other hw
     // panel parameters for now.
     bool is_primary_panel = false;
-    bool valid_cursor = false;
     PUConstraints pu_constraints = {};
-    bool scaled_composition = false;
   };
 
   Locker locker_;
diff --git a/sdm/libs/core/display_base.cpp b/sdm/libs/core/display_base.cpp
index c268183..618dd2e 100644
--- a/sdm/libs/core/display_base.cpp
+++ b/sdm/libs/core/display_base.cpp
@@ -77,10 +77,9 @@
   error = comp_manager_->GetScaleLutConfig(&lut_info);
   if (error == kErrorNone) {
     error = hw_intf_->SetScaleLutConfig(&lut_info);
-  }
-
-  if (error != kErrorNone) {
-    goto CleanupOnError;
+    if (error != kErrorNone) {
+      goto CleanupOnError;
+    }
   }
 
   error = comp_manager_->RegisterDisplay(display_type_, display_attributes_, hw_panel_info_,
@@ -665,7 +664,7 @@
   switch (composition) {
   case kCompositionGPU:         return "GPU";
   case kCompositionSDE:         return "SDE";
-  case kCompositionHWCursor:    return "CURSOR";
+  case kCompositionCursor:      return "CURSOR";
   case kCompositionHybrid:      return "HYBRID";
   case kCompositionBlit:        return "BLIT";
   case kCompositionGPUTarget:   return "GPU_TARGET";
@@ -987,10 +986,14 @@
   DisplayError error = kErrorNone;
   if (vsync_enable_ != enable) {
     error = hw_intf_->SetVSyncState(enable);
+    if (error == kErrorNotSupported) {
+      error = hw_events_intf_->SetEventState(HWEvent::VSYNC, enable);
+    }
     if (error == kErrorNone) {
       vsync_enable_ = enable;
     }
   }
+
   return error;
 }
 
diff --git a/sdm/libs/core/display_hdmi.cpp b/sdm/libs/core/display_hdmi.cpp
index 2ee863c..b31ac94 100644
--- a/sdm/libs/core/display_hdmi.cpp
+++ b/sdm/libs/core/display_hdmi.cpp
@@ -94,6 +94,8 @@
     DLOGE("Failed to create hardware events interface. Error = %d", error);
   }
 
+  current_refresh_rate_ = hw_panel_info_.max_fps;
+
   return error;
 }
 
@@ -135,18 +137,21 @@
   return error;
 }
 
-DisplayError DisplayHDMI::SetRefreshRate(uint32_t refresh_rate) {
+DisplayError DisplayHDMI::SetRefreshRate(uint32_t refresh_rate, bool final_rate) {
   lock_guard<recursive_mutex> obj(recursive_mutex_);
 
   if (!active_) {
     return kErrorPermission;
   }
 
-  DisplayError error = hw_intf_->SetRefreshRate(refresh_rate);
-  if (error != kErrorNone) {
-    return error;
+  if (current_refresh_rate_ != refresh_rate) {
+    DisplayError error = hw_intf_->SetRefreshRate(refresh_rate);
+    if (error != kErrorNone) {
+      return error;
+    }
   }
 
+  current_refresh_rate_ = refresh_rate;
   return DisplayBase::ReconfigureDisplay();
 }
 
diff --git a/sdm/libs/core/display_hdmi.h b/sdm/libs/core/display_hdmi.h
index a6c1f51..ca09ce3 100644
--- a/sdm/libs/core/display_hdmi.h
+++ b/sdm/libs/core/display_hdmi.h
@@ -44,7 +44,7 @@
   virtual DisplayError Init();
   virtual DisplayError Prepare(LayerStack *layer_stack);
   virtual DisplayError GetRefreshRateRange(uint32_t *min_refresh_rate, uint32_t *max_refresh_rate);
-  virtual DisplayError SetRefreshRate(uint32_t refresh_rate);
+  virtual DisplayError SetRefreshRate(uint32_t refresh_rate, bool final_rate);
   virtual bool IsUnderscanSupported();
   virtual DisplayError OnMinHdcpEncryptionLevelChange(uint32_t min_enc_level);
 
@@ -66,6 +66,7 @@
   std::map<LayerBufferS3DFormat, HWS3DMode> s3d_format_to_mode_;
   std::vector<HWEvent> event_list_ = { HWEvent::VSYNC, HWEvent::IDLE_NOTIFY, HWEvent::EXIT,
     HWEvent::CEC_READ_MESSAGE };
+  uint32_t current_refresh_rate_ = 0;
 };
 
 }  // namespace sdm
diff --git a/sdm/libs/core/display_primary.cpp b/sdm/libs/core/display_primary.cpp
index d89e9db..53a4fd9 100644
--- a/sdm/libs/core/display_primary.cpp
+++ b/sdm/libs/core/display_primary.cpp
@@ -77,6 +77,8 @@
     HWInterface::Destroy(hw_intf_);
   }
 
+  current_refresh_rate_ = hw_panel_info_.max_fps;
+
   return error;
 }
 
@@ -262,7 +264,7 @@
   return error;
 }
 
-DisplayError DisplayPrimary::SetRefreshRate(uint32_t refresh_rate) {
+DisplayError DisplayPrimary::SetRefreshRate(uint32_t refresh_rate, bool final_rate) {
   lock_guard<recursive_mutex> obj(recursive_mutex_);
 
   if (!active_ || !hw_panel_info_.dynamic_fps) {
@@ -274,11 +276,21 @@
     return kErrorParameters;
   }
 
-  DisplayError error = hw_intf_->SetRefreshRate(refresh_rate);
-  if (error != kErrorNone) {
-    return error;
+  if (handle_idle_timeout_ && !final_rate) {
+    refresh_rate = hw_panel_info_.min_fps;
   }
 
+  if ((current_refresh_rate_ != refresh_rate) || handle_idle_timeout_) {
+    DisplayError error = hw_intf_->SetRefreshRate(refresh_rate);
+    if (error != kErrorNone) {
+      return error;
+    }
+  }
+
+  // On success, set current refresh rate to new refresh rate
+  current_refresh_rate_ = refresh_rate;
+  handle_idle_timeout_ = false;
+
   return DisplayBase::ReconfigureDisplay();
 }
 
@@ -293,6 +305,7 @@
 }
 
 void DisplayPrimary::IdleTimeout() {
+  handle_idle_timeout_ = true;
   event_handler_->Refresh();
   comp_manager_->ProcessIdleTimeout(display_comp_ctx_);
 }
diff --git a/sdm/libs/core/display_primary.h b/sdm/libs/core/display_primary.h
index 5578f36..314964a 100644
--- a/sdm/libs/core/display_primary.h
+++ b/sdm/libs/core/display_primary.h
@@ -49,7 +49,7 @@
   virtual void SetIdleTimeoutMs(uint32_t active_ms);
   virtual DisplayError SetDisplayMode(uint32_t mode);
   virtual DisplayError GetRefreshRateRange(uint32_t *min_refresh_rate, uint32_t *max_refresh_rate);
-  virtual DisplayError SetRefreshRate(uint32_t refresh_rate);
+  virtual DisplayError SetRefreshRate(uint32_t refresh_rate, bool final_rate);
   virtual DisplayError SetPanelBrightness(int level);
   virtual DisplayError GetPanelBrightness(int *level);
   virtual DisplayError CachePanelBrightness(int level);
@@ -69,6 +69,8 @@
       HWEvent::SHOW_BLANK_EVENT, HWEvent::THERMAL_LEVEL, HWEvent::IDLE_POWER_COLLAPSE };
   bool avr_prop_disabled_ = false;
   bool switch_to_cmd_ = false;
+  bool handle_idle_timeout_ = false;
+  uint32_t current_refresh_rate_ = 0;
 };
 
 }  // namespace sdm
diff --git a/sdm/libs/core/display_virtual.h b/sdm/libs/core/display_virtual.h
index aaebf46..185366c 100644
--- a/sdm/libs/core/display_virtual.h
+++ b/sdm/libs/core/display_virtual.h
@@ -53,7 +53,7 @@
   virtual DisplayError SetVSyncState(bool enable) {
     return kErrorNotSupported;
   }
-  virtual DisplayError SetRefreshRate(uint32_t refresh_rate) {
+  virtual DisplayError SetRefreshRate(uint32_t refresh_rate, bool final_rate) {
     return kErrorNotSupported;
   }
   virtual DisplayError GetMixerResolution(uint32_t *width, uint32_t *height) {
diff --git a/sdm/libs/core/drm/hw_device_drm.cpp b/sdm/libs/core/drm/hw_device_drm.cpp
index 8052613..6bc4434 100644
--- a/sdm/libs/core/drm/hw_device_drm.cpp
+++ b/sdm/libs/core/drm/hw_device_drm.cpp
@@ -429,24 +429,22 @@
         display_attributes_.x_pixels / 2;
   }
 
-  hw_panel_info_.partial_update = 0;
-  hw_panel_info_.left_align = 0;
-  hw_panel_info_.width_align = 0;
-  hw_panel_info_.top_align = 0;
-  hw_panel_info_.height_align = 0;
-  hw_panel_info_.min_roi_width = 0;
-  hw_panel_info_.min_roi_height = 0;
-  hw_panel_info_.needs_roi_merge = 0;
+  hw_panel_info_.partial_update = connector_info_.num_roi;
+  hw_panel_info_.left_roi_count = UINT32(connector_info_.num_roi);
+  hw_panel_info_.right_roi_count = UINT32(connector_info_.num_roi);
+  hw_panel_info_.left_align = connector_info_.xstart;
+  hw_panel_info_.top_align = connector_info_.ystart;
+  hw_panel_info_.width_align = connector_info_.walign;
+  hw_panel_info_.height_align = connector_info_.halign;
+  hw_panel_info_.min_roi_width = connector_info_.wmin;
+  hw_panel_info_.min_roi_height = connector_info_.hmin;
+  hw_panel_info_.needs_roi_merge = connector_info_.roi_merge;
   hw_panel_info_.dynamic_fps = connector_info_.dynamic_fps;
   hw_panel_info_.min_fps = 60;
   hw_panel_info_.max_fps = 60;
   hw_panel_info_.is_primary_panel = connector_info_.is_primary;
   hw_panel_info_.is_pluggable = 0;
 
-  if (!default_mode_) {
-    hw_panel_info_.needs_roi_merge = (connector_info_.topology == DRMTopology::DUAL_LM_MERGE);
-  }
-
   GetHWDisplayPortAndMode();
   GetHWPanelMaxBrightness();
 
@@ -562,14 +560,18 @@
 
 DisplayError HWDeviceDRM::PowerOn() {
   DTRACE_SCOPED();
+/*
   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);
+*/
   return kErrorNone;
 }
 
 DisplayError HWDeviceDRM::PowerOff() {
+/*
   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 */);
   if (ret) {
     DLOGE("%s failed with error %d", __FUNCTION__, ret);
@@ -601,6 +603,34 @@
   HWLayersInfo &hw_layer_info = hw_layers->info;
   uint32_t hw_layer_count = UINT32(hw_layer_info.hw_layers.size());
 
+  // TODO(user): Once destination scalar is enabled we can always send ROIs if driver allows
+  if (hw_panel_info_.partial_update) {
+    const int kNumMaxROIs = 4;
+    DRMRect crtc_rects[kNumMaxROIs] = {{0, 0, mixer_attributes_.width, mixer_attributes_.height}};
+    DRMRect conn_rects[kNumMaxROIs] = {{0, 0, display_attributes_.x_pixels,
+                                        display_attributes_.y_pixels}};
+
+    for (uint32_t i = 0; i < hw_layer_info.left_frame_roi.size(); i++) {
+      auto &roi = hw_layer_info.left_frame_roi.at(i);
+      // TODO(user): In multi PU, stitch ROIs vertically adjacent and upate plane destination
+      crtc_rects[i].left = UINT32(roi.left);
+      crtc_rects[i].right = UINT32(roi.right);
+      crtc_rects[i].top = UINT32(roi.top);
+      crtc_rects[i].bottom = UINT32(roi.bottom);
+      // TODO(user): In Dest scaler + PU, populate from HWDestScaleInfo->panel_roi
+      conn_rects[i].left = UINT32(roi.left);
+      conn_rects[i].right = UINT32(roi.right);
+      conn_rects[i].top = UINT32(roi.top);
+      conn_rects[i].bottom = UINT32(roi.bottom);
+    }
+
+    uint32_t num_rects = std::max(1u, static_cast<uint32_t>(hw_layer_info.left_frame_roi.size()));
+    drm_atomic_intf_->Perform(DRMOps::CRTC_SET_ROI, token_.crtc_id,
+                              num_rects, crtc_rects);
+    drm_atomic_intf_->Perform(DRMOps::CONNECTOR_SET_ROI, token_.conn_id,
+                              num_rects, conn_rects);
+  }
+
   for (uint32_t i = 0; i < hw_layer_count; i++) {
     Layer &layer = hw_layer_info.hw_layers.at(i);
     LayerBuffer *input_buffer = &layer.input_buffer;
@@ -669,6 +699,13 @@
         }
       }
     }
+
+    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);
+
+    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);
   }
 }
 
@@ -878,7 +915,7 @@
 }
 
 DisplayError HWDeviceDRM::SetVSyncState(bool enable) {
-  return kErrorNone;
+  return kErrorNotSupported;
 }
 
 void HWDeviceDRM::SetIdleTimeoutMs(uint32_t timeout_ms) {}
diff --git a/sdm/libs/core/drm/hw_device_drm.h b/sdm/libs/core/drm/hw_device_drm.h
index cc2ae7b..16954af 100644
--- a/sdm/libs/core/drm/hw_device_drm.h
+++ b/sdm/libs/core/drm/hw_device_drm.h
@@ -75,6 +75,7 @@
   virtual DisplayError Flush();
   virtual DisplayError GetPPFeaturesVersion(PPFeatureVersion *vers);
   virtual DisplayError SetPPFeatures(PPFeaturesConfig *feature_list);
+  // This API is no longer supported, expectation is to call the correct API on HWEvents
   virtual DisplayError SetVSyncState(bool enable);
   virtual void SetIdleTimeoutMs(uint32_t timeout_ms);
   virtual DisplayError SetDisplayMode(const HWDisplayMode hw_display_mode);
@@ -135,7 +136,7 @@
     uint32_t GetFbId(int fd);
 
    private:
-    static const int kCycleDelay = 1;  // N cycle delay before destroy
+    static const int kCycleDelay = 3;  // N cycle delay before destroy
     // fd to fb_id map. fd is used as key only for a single draw cycle between
     // prepare and commit. It should not be used for caching in future due to fd recycling
     std::unordered_map<int, uint32_t> hashmap_[kCycleDelay] {};
diff --git a/sdm/libs/core/drm/hw_events_drm.cpp b/sdm/libs/core/drm/hw_events_drm.cpp
index 09293a9..cea76fc 100644
--- a/sdm/libs/core/drm/hw_events_drm.cpp
+++ b/sdm/libs/core/drm/hw_events_drm.cpp
@@ -160,7 +160,30 @@
 DisplayError HWEventsDRM::Deinit() {
   exit_threads_ = true;
   Sys::pthread_cancel_(event_thread_);
+  WakeUpEventThread();
+  pthread_join(event_thread_, NULL);
+  CloseFds();
 
+  return kErrorNone;
+}
+
+DisplayError HWEventsDRM::SetEventState(HWEvent event, bool enable, void *arg) {
+  switch (event) {
+    case HWEvent::VSYNC:
+      vsync_enabled_ = enable;
+      if (enable) {
+        WakeUpEventThread();
+      }
+      break;
+    default:
+      DLOGE("Event not supported");
+      return kErrorNotSupported;
+  }
+
+  return kErrorNone;
+}
+
+void HWEventsDRM::WakeUpEventThread() {
   for (uint32_t i = 0; i < event_data_list_.size(); i++) {
     if (event_data_list_[i].event_type == HWEvent::EXIT) {
       uint64_t exit_value = 1;
@@ -169,13 +192,9 @@
         DLOGW("Error triggering exit fd (%d). write size = %d, error = %s", poll_fds_[i].fd,
               write_size, strerror(errno));
       }
+      break;
     }
   }
-
-  pthread_join(event_thread_, NULL);
-  CloseFds();
-
-  return kErrorNone;
 }
 
 DisplayError HWEventsDRM::CloseFds() {
@@ -217,7 +236,7 @@
   setpriority(PRIO_PROCESS, 0, kThreadPriorityUrgent);
 
   while (!exit_threads_) {
-    if (RegisterVSync() != kErrorNone) {
+    if (vsync_enabled_ && RegisterVSync() != kErrorNone) {
       pthread_exit(0);
       return nullptr;
     }
diff --git a/sdm/libs/core/drm/hw_events_drm.h b/sdm/libs/core/drm/hw_events_drm.h
index 8703321..41050c7 100644
--- a/sdm/libs/core/drm/hw_events_drm.h
+++ b/sdm/libs/core/drm/hw_events_drm.h
@@ -48,6 +48,7 @@
   virtual DisplayError Init(int display_type, HWEventHandler *event_handler,
                             const vector<HWEvent> &event_list);
   virtual DisplayError Deinit();
+  virtual DisplayError SetEventState(HWEvent event, bool enable, void *aux = nullptr);
 
  private:
   static const int kMaxStringLength = 1024;
@@ -72,6 +73,7 @@
   void HandleBlank(char *data) {}
   void HandleIdlePowerCollapse(char *data);
   void PopulateHWEventData(const vector<HWEvent> &event_list);
+  void WakeUpEventThread();
   DisplayError SetEventParser();
   DisplayError InitializePollFd();
   DisplayError CloseFds();
@@ -84,6 +86,7 @@
   std::string event_thread_name_ = "SDM_EventThread";
   bool exit_threads_ = false;
   uint32_t vsync_index_ = 0;
+  bool vsync_enabled_ = true;
 };
 
 }  // namespace sdm
diff --git a/sdm/libs/core/drm/hw_info_drm.cpp b/sdm/libs/core/drm/hw_info_drm.cpp
index a2ba960..6258d73 100644
--- a/sdm/libs/core/drm/hw_info_drm.cpp
+++ b/sdm/libs/core/drm/hw_info_drm.cpp
@@ -135,7 +135,7 @@
 DisplayError HWInfoDRM::GetDynamicBWLimits(HWResourceInfo *hw_resource) {
   HWDynBwLimitInfo* bw_info = &hw_resource->dyn_bw_info;
   for (int index = 0; index < kBwModeMax; index++) {
-    bw_info->total_bw_limit[index] = UINT32(hw_resource->max_bandwidth_low);
+    bw_info->total_bw_limit[index] = hw_resource->max_bandwidth_low;
     bw_info->pipe_bw_limit[index] = hw_resource->max_pipe_bw;
   }
 
@@ -164,14 +164,13 @@
   hw_resource->linear_factor = 1;
   hw_resource->scale_factor = 1;
   hw_resource->extra_fudge_factor = 2;
-  hw_resource->amortizable_threshold = 0;
+  hw_resource->amortizable_threshold = 25;
   hw_resource->system_overhead_lines = 0;
   hw_resource->hw_dest_scalar_info.count = 0;
   hw_resource->hw_dest_scalar_info.max_scale_up = 0;
   hw_resource->hw_dest_scalar_info.max_input_width = 0;
   hw_resource->hw_dest_scalar_info.max_output_width = 0;
   hw_resource->is_src_split = true;
-  hw_resource->perf_calc = false;
   hw_resource->has_dyn_bw_support = false;
   hw_resource->has_qseed3 = false;
   hw_resource->has_concurrent_writeback = false;
@@ -254,6 +253,33 @@
   hw_resource->num_blending_stages = info.max_blend_stages;
   hw_resource->smart_dma_rev = (info.smart_dma_rev == sde_drm::SmartDMARevision::V2) ?
     SmartDMARevision::V2 : SmartDMARevision::V1;
+  hw_resource->ib_fudge_factor = info.ib_fudge_factor;
+  hw_resource->hw_dest_scalar_info.prefill_lines = info.dest_scale_prefill_lines;
+  hw_resource->undersized_prefill_lines = info.undersized_prefill_lines;
+  hw_resource->macrotile_factor = info.macrotile_prefill_lines;
+  hw_resource->macrotile_nv12_factor = info.nv12_prefill_lines;
+  hw_resource->linear_factor = info.linear_prefill_lines;
+  hw_resource->scale_factor = info.downscale_prefill_lines;
+  hw_resource->extra_fudge_factor = info.extra_prefill_lines;
+  hw_resource->amortizable_threshold = info.amortized_threshold;
+  hw_resource->max_bandwidth_low = info.max_bandwidth_low / kKiloUnit;
+  hw_resource->max_bandwidth_high = info.max_bandwidth_high / kKiloUnit;
+  hw_resource->max_sde_clk = info.max_sde_clk;
+
+  std::vector<LayerBufferFormat> sdm_format;
+  for (auto &it : info.comp_ratio_rt_map) {
+    std::pair<uint32_t, uint64_t> drm_format = it.first;
+    GetSDMFormat(drm_format.first, drm_format.second, &sdm_format);
+    hw_resource->comp_ratio_rt_map.insert(std::make_pair(sdm_format[0], it.second));
+    sdm_format.clear();
+  }
+
+  for (auto &it : info.comp_ratio_nrt_map) {
+    std::pair<uint32_t, uint64_t> drm_format = it.first;
+    GetSDMFormat(drm_format.first, drm_format.second, &sdm_format);
+    hw_resource->comp_ratio_rt_map.insert(std::make_pair(sdm_format[0], it.second));
+    sdm_format.clear();
+  }
 }
 
 void HWInfoDRM::GetHWPlanesInfo(HWResourceInfo *hw_resource) {
@@ -305,6 +331,7 @@
   hw_resource->max_scale_down = info.max_downscale;
   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;
 }
 
 void HWInfoDRM::PopulateSupportedFmts(HWSubBlockType sub_blk_type,
diff --git a/sdm/libs/core/drm/hw_info_drm.h b/sdm/libs/core/drm/hw_info_drm.h
index 91829cb..5d92c41 100644
--- a/sdm/libs/core/drm/hw_info_drm.h
+++ b/sdm/libs/core/drm/hw_info_drm.h
@@ -71,6 +71,8 @@
   // TODO(user): Read Mdss version from the driver
   static const int kHWMdssVersion5 = 500;  // MDSS_V5
   static const int kMaxStringLength = 1024;
+  static const int kKiloUnit = 1000;
+
   static HWResourceInfo *hw_resource_;
 };
 
diff --git a/sdm/libs/core/fb/hw_device.cpp b/sdm/libs/core/fb/hw_device.cpp
index e1920b2..773845b 100644
--- a/sdm/libs/core/fb/hw_device.cpp
+++ b/sdm/libs/core/fb/hw_device.cpp
@@ -208,7 +208,6 @@
     HWPipeInfo *right_pipe = &hw_layers->config[i].right_pipe;
     HWRotatorSession *hw_rotator_session = &hw_layers->config[i].hw_rotator_session;
     bool is_rotator_used = (hw_rotator_session->hw_block_count != 0);
-    bool is_cursor_pipe_used = (hw_layer_info.use_hw_cursor & layer.flags.cursor);
 
     for (uint32_t count = 0; count < 2; count++) {
       HWPipeInfo *pipe_info = (count == 0) ? left_pipe : right_pipe;
@@ -242,10 +241,12 @@
         mdp_layer.pipe_ndx = pipe_info->pipe_id;
         mdp_layer.horz_deci = pipe_info->horizontal_decimation;
         mdp_layer.vert_deci = pipe_info->vertical_decimation;
-
+#ifdef MDP_COMMIT_RECT_NUM
+        mdp_layer.rect_num = pipe_info->rect;
+#endif
         SetRect(pipe_info->src_roi, &mdp_layer.src_rect);
         SetRect(pipe_info->dst_roi, &mdp_layer.dst_rect);
-        SetMDPFlags(&layer, is_rotator_used, is_cursor_pipe_used, &mdp_layer.flags);
+        SetMDPFlags(&layer, is_rotator_used, hw_layer_info.async_cursor_updates, &mdp_layer.flags);
         SetCSC(layer.input_buffer.color_metadata, &mdp_layer.color_space);
         if (pipe_info->flags & kIGC) {
           SetIGC(&layer.input_buffer, mdp_layer_count);
@@ -350,6 +351,9 @@
   mdp_commit.dest_scaler_cnt = UINT32(hw_layer_info.dest_scale_info_map.size());
 
   mdp_commit.flags |= MDP_VALIDATE_LAYER;
+#ifdef MDP_COMMIT_RECT_NUM
+  mdp_commit.flags |= MDP_COMMIT_RECT_NUM;
+#endif
   if (Sys::ioctl_(device_fd_, INT(MSMFB_ATOMIC_COMMIT), &mdp_disp_commit_) < 0) {
     if (errno == ESHUTDOWN) {
       DLOGI_IF(kTagDriverConfig, "Driver is processing shutdown sequence");
@@ -705,7 +709,7 @@
 }
 
 void HWDevice::SetMDPFlags(const Layer *layer, const bool &is_rotator_used,
-                           bool is_cursor_pipe_used, uint32_t *mdp_flags) {
+                           bool async_cursor_updates, uint32_t *mdp_flags) {
   const LayerBuffer &input_buffer = layer->input_buffer;
 
   // Flips will be taken care by rotator, if layer uses rotator for downscale/rotation. So ignore
@@ -738,7 +742,7 @@
     *mdp_flags |= MDP_LAYER_SOLID_FILL;
   }
 
-  if (hw_panel_info_.mode != kModeCommand && layer->flags.cursor && is_cursor_pipe_used) {
+  if (layer->flags.cursor && async_cursor_updates) {
     // command mode panels does not support async position update
     *mdp_flags |= MDP_LAYER_ASYNC;
   }
diff --git a/sdm/libs/core/fb/hw_device.h b/sdm/libs/core/fb/hw_device.h
index b94a5f3..2eea87b 100644
--- a/sdm/libs/core/fb/hw_device.h
+++ b/sdm/libs/core/fb/hw_device.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:
@@ -116,7 +116,7 @@
   void SetBlending(const LayerBlending &source, mdss_mdp_blend_op *target);
   void SetRect(const LayerRect &source, mdp_rect *target);
   void SetMDPFlags(const Layer *layer, const bool &is_rotator_used,
-                   bool is_cursor_pipe_used, uint32_t *mdp_flags);
+                   bool async_cursor_updates, uint32_t *mdp_flags);
   // Retrieves HW FrameBuffer Node Index
   int GetFBNodeIndex(HWDeviceType device_type);
   // Populates HWPanelInfo based on node index
@@ -143,7 +143,7 @@
   int fb_node_index_;
   const char *fb_path_;
   BufferSyncHandler *buffer_sync_handler_;
-  int device_fd_;
+  int device_fd_ = -1;
   int stored_retire_fence = -1;
   HWDeviceType device_type_;
   mdp_layer_commit mdp_disp_commit_;
diff --git a/sdm/libs/core/fb/hw_events.h b/sdm/libs/core/fb/hw_events.h
index 347495f..3d9cec8 100644
--- a/sdm/libs/core/fb/hw_events.h
+++ b/sdm/libs/core/fb/hw_events.h
@@ -44,6 +44,9 @@
   virtual DisplayError Init(int fb_num, HWEventHandler *event_handler,
                             const vector<HWEvent> &event_list);
   virtual DisplayError Deinit();
+  virtual DisplayError SetEventState(HWEvent event, bool enable, void *aux = nullptr) {
+    return kErrorNotSupported;
+  }
 
  private:
   static const int kMaxStringLength = 1024;
diff --git a/sdm/libs/core/fb/hw_info.cpp b/sdm/libs/core/fb/hw_info.cpp
index d898cd2..f2a13e3 100644
--- a/sdm/libs/core/fb/hw_info.cpp
+++ b/sdm/libs/core/fb/hw_info.cpp
@@ -95,7 +95,7 @@
 
   HWDynBwLimitInfo* bw_info = &hw_resource->dyn_bw_info;
   for (int index = 0; index < kBwModeMax; index++) {
-    bw_info->total_bw_limit[index] = UINT32(hw_resource->max_bandwidth_low);
+    bw_info->total_bw_limit[index] = hw_resource->max_bandwidth_low;
     bw_info->pipe_bw_limit[index] = hw_resource->max_pipe_bw;
   }
 
@@ -169,9 +169,9 @@
       } else if (!strncmp(tokens[0], "max_upscale_ratio", strlen("max_upscale_ratio"))) {
         hw_resource_->max_scale_up = UINT32(atoi(tokens[1]));
       } else if (!strncmp(tokens[0], "max_bandwidth_low", strlen("max_bandwidth_low"))) {
-        hw_resource_->max_bandwidth_low = UINT64(atol(tokens[1]));
+        hw_resource_->max_bandwidth_low = std::stoull(tokens[1]);
       } else if (!strncmp(tokens[0], "max_bandwidth_high", strlen("max_bandwidth_high"))) {
-        hw_resource_->max_bandwidth_high = UINT64(atol(tokens[1]));
+        hw_resource_->max_bandwidth_high = std::stoull(tokens[1]);
       } else if (!strncmp(tokens[0], "max_mixer_width", strlen("max_mixer_width"))) {
         hw_resource_->max_mixer_width = UINT32(atoi(tokens[1]));
       } else if (!strncmp(tokens[0], "max_pipe_width", strlen("max_pipe_width"))) {
@@ -179,7 +179,7 @@
       } else if (!strncmp(tokens[0], "max_cursor_size", strlen("max_cursor_size"))) {
         hw_resource_->max_cursor_size = UINT32(atoi(tokens[1]));
       } else if (!strncmp(tokens[0], "max_pipe_bw", strlen("max_pipe_bw"))) {
-        hw_resource_->max_pipe_bw = UINT32(atoi(tokens[1]));
+        hw_resource_->max_pipe_bw = std::stoull(tokens[1]);
       } else if (!strncmp(tokens[0], "max_mdp_clk", strlen("max_mdp_clk"))) {
         hw_resource_->max_sde_clk = UINT32(atoi(tokens[1]));
       } else if (!strncmp(tokens[0], "clk_fudge_factor", strlen("clk_fudge_factor"))) {
@@ -224,8 +224,6 @@
             hw_resource_->is_src_split = true;
           } else if (!strncmp(tokens[i], "non_scalar_rgb", strlen("non_scalar_rgb"))) {
             hw_resource_->has_non_scalar_rgb = true;
-          } else if (!strncmp(tokens[i], "perf_calc", strlen("perf_calc"))) {
-            hw_resource_->perf_calc = true;
           } else if (!strncmp(tokens[i], "dynamic_bw_limit", strlen("dynamic_bw_limit"))) {
             hw_resource_->has_dyn_bw_support = true;
           } else if (!strncmp(tokens[i], "separate_rotator", strlen("separate_rotator"))) {
diff --git a/sdm/libs/core/hw_events_interface.h b/sdm/libs/core/hw_events_interface.h
index e6a714c..482e077 100644
--- a/sdm/libs/core/hw_events_interface.h
+++ b/sdm/libs/core/hw_events_interface.h
@@ -49,6 +49,7 @@
   virtual DisplayError Init(int display_type, HWEventHandler *event_handler,
                             const std::vector<HWEvent> &event_list) = 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);
diff --git a/sdm/libs/core/resource_default.cpp b/sdm/libs/core/resource_default.cpp
index 31d8704..2d74941 100644
--- a/sdm/libs/core/resource_default.cpp
+++ b/sdm/libs/core/resource_default.cpp
@@ -923,11 +923,6 @@
   return kErrorNone;
 }
 
-DisplayError ResourceDefault::ValidateCursorConfig(Handle display_ctx, const Layer *layer,
-                                                   bool is_top) {
-  return kErrorNotSupported;
-}
-
 DisplayError ResourceDefault::ValidateCursorPosition(Handle display_ctx, HWLayers *hw_layers,
                                                      int x, int y) {
   return kErrorNotSupported;
diff --git a/sdm/libs/hwc/Android.mk b/sdm/libs/hwc/Android.mk
index c3d906f..a2142e3 100644
--- a/sdm/libs/hwc/Android.mk
+++ b/sdm/libs/hwc/Android.mk
@@ -4,12 +4,7 @@
 ifeq ($(use_hwc2),false)
 
 LOCAL_MODULE                  := hwcomposer.$(TARGET_BOARD_PLATFORM)
-
-ifneq ($(TARGET_IS_HEADLESS), true)
-LOCAL_MODULE_PATH_32          := $(TARGET_OUT_VENDOR)/lib
-LOCAL_MODULE_PATH_64          := $(TARGET_OUT_VENDOR)/lib64
-endif
-
+LOCAL_VENDOR_MODULE           := true
 LOCAL_MODULE_RELATIVE_PATH    := hw
 LOCAL_MODULE_TAGS             := optional
 LOCAL_C_INCLUDES              := $(common_includes)
diff --git a/sdm/libs/hwc/hwc_display.cpp b/sdm/libs/hwc/hwc_display.cpp
index 6cba7f0..07ec2ce 100644
--- a/sdm/libs/hwc/hwc_display.cpp
+++ b/sdm/libs/hwc/hwc_display.cpp
@@ -953,7 +953,7 @@
   case kCompositionGPUTarget:   *target = HWC_FRAMEBUFFER_TARGET; break;
   case kCompositionGPU:         *target = HWC_FRAMEBUFFER;        break;
   case kCompositionGPUS3D:      *target = HWC_FRAMEBUFFER;        break;
-  case kCompositionHWCursor:    *target = HWC_CURSOR_OVERLAY;     break;
+  case kCompositionCursor:      *target = HWC_CURSOR_OVERLAY;     break;
   default:                      *target = HWC_OVERLAY;            break;
   }
 }
diff --git a/sdm/libs/hwc/hwc_display_external.cpp b/sdm/libs/hwc/hwc_display_external.cpp
index a535819..da216f7 100644
--- a/sdm/libs/hwc/hwc_display_external.cpp
+++ b/sdm/libs/hwc/hwc_display_external.cpp
@@ -137,12 +137,11 @@
   bool one_video_updating_layer = SingleVideoLayerUpdating(UINT32(content_list->numHwLayers - 1));
 
   uint32_t refresh_rate = GetOptimalRefreshRate(one_video_updating_layer);
-  if (current_refresh_rate_ != refresh_rate) {
-    error = display_intf_->SetRefreshRate(refresh_rate);
-    if (error == kErrorNone) {
-      // On success, set current refresh rate to new refresh rate
-      current_refresh_rate_ = refresh_rate;
-    }
+  bool final_rate = force_refresh_rate_ ? true : false;
+  error = display_intf_->SetRefreshRate(refresh_rate, final_rate);
+  if (error == kErrorNone) {
+    // On success, set current refresh rate to new refresh rate
+    current_refresh_rate_ = refresh_rate;
   }
 
   status = PrepareLayerStack(content_list);
diff --git a/sdm/libs/hwc/hwc_display_primary.cpp b/sdm/libs/hwc/hwc_display_primary.cpp
index ba351b5..8d6f31b 100644
--- a/sdm/libs/hwc/hwc_display_primary.cpp
+++ b/sdm/libs/hwc/hwc_display_primary.cpp
@@ -192,21 +192,13 @@
   }
 
   uint32_t refresh_rate = GetOptimalRefreshRate(one_updating_layer);
-  // TODO(user): Need to read current refresh rate to avoid
-  // redundant calls to set refresh rate during idle fall back.
-  if ((current_refresh_rate_ != refresh_rate) || (handle_idle_timeout_)) {
-    error = display_intf_->SetRefreshRate(refresh_rate);
-  }
-
+  bool final_rate = force_refresh_rate_ ? true : false;
+  error = display_intf_->SetRefreshRate(refresh_rate, final_rate);
   if (error == kErrorNone) {
     // On success, set current refresh rate to new refresh rate
     current_refresh_rate_ = refresh_rate;
   }
 
-  if (handle_idle_timeout_) {
-    handle_idle_timeout_ = false;
-  }
-
   if (content_list->numHwLayers <= 1) {
     flush_ = true;
   }
@@ -370,8 +362,6 @@
 uint32_t HWCDisplayPrimary::GetOptimalRefreshRate(bool one_updating_layer) {
   if (force_refresh_rate_) {
     return force_refresh_rate_;
-  } else if (handle_idle_timeout_) {
-    return min_refresh_rate_;
   } else if (use_metadata_refresh_rate_ && one_updating_layer && metadata_refresh_rate_) {
     return metadata_refresh_rate_;
   }
@@ -388,7 +378,6 @@
   }
 
   hwc_procs->invalidate(hwc_procs);
-  handle_idle_timeout_ = true;
 
   return error;
 }
diff --git a/sdm/libs/hwc/hwc_display_primary.h b/sdm/libs/hwc/hwc_display_primary.h
index 8a2ff87..e937980 100644
--- a/sdm/libs/hwc/hwc_display_primary.h
+++ b/sdm/libs/hwc/hwc_display_primary.h
@@ -69,7 +69,6 @@
 
   BufferAllocator *buffer_allocator_ = nullptr;
   CPUHint cpu_hint_;
-  bool handle_idle_timeout_ = false;
 
   // Primary output buffer configuration
   LayerBuffer output_buffer_ = {};
diff --git a/sdm/libs/hwc2/Android.mk b/sdm/libs/hwc2/Android.mk
index 64f930e..557b55f 100644
--- a/sdm/libs/hwc2/Android.mk
+++ b/sdm/libs/hwc2/Android.mk
@@ -5,12 +5,7 @@
 ifeq ($(use_hwc2),true)
 
 LOCAL_MODULE                  := hwcomposer.$(TARGET_BOARD_PLATFORM)
-
-ifneq ($(TARGET_IS_HEADLESS), true)
-LOCAL_MODULE_PATH_32          := $(TARGET_OUT_VENDOR)/lib
-LOCAL_MODULE_PATH_64          := $(TARGET_OUT_VENDOR)/lib64
-endif
-
+LOCAL_VENDOR_MODULE           := true
 LOCAL_MODULE_RELATIVE_PATH    := hw
 LOCAL_MODULE_TAGS             := optional
 LOCAL_C_INCLUDES              := $(common_includes)
@@ -24,7 +19,8 @@
 
 LOCAL_SHARED_LIBRARIES        := libsdmcore libqservice libbinder libhardware libhardware_legacy \
                                  libutils libcutils libsync libqdutils libqdMetaData libdl \
-                                 libpowermanager libsdmutils libc++ liblog libgrallocutils
+                                 libpowermanager libsdmutils libc++ liblog libgrallocutils \
+                                 libui libgpu_tonemapper
 
 ifneq ($(TARGET_USES_GRALLOC1), true)
     LOCAL_SHARED_LIBRARIES += libmemalloc
@@ -41,7 +37,8 @@
                                  hwc_layers.cpp \
                                  hwc_callbacks.cpp \
                                  ../hwc/cpuhint.cpp \
-                                 ../hwc/hwc_socket_handler.cpp
+                                 ../hwc/hwc_socket_handler.cpp \
+                                 hwc_tonemapper.cpp
 
 ifneq ($(TARGET_USES_GRALLOC1), true)
     LOCAL_SRC_FILES += ../hwc/hwc_buffer_allocator.cpp
diff --git a/sdm/libs/hwc2/hwc_buffer_allocator.cpp b/sdm/libs/hwc2/hwc_buffer_allocator.cpp
index bdebc22..da40a34 100644
--- a/sdm/libs/hwc2/hwc_buffer_allocator.cpp
+++ b/sdm/libs/hwc2/hwc_buffer_allocator.cpp
@@ -80,6 +80,11 @@
     // Allocate uncached buffers
     alloc_flags |= GRALLOC_USAGE_PRIVATE_UNCACHED;
   }
+
+  if (buffer_config.gfx_client) {
+    alloc_flags |= GRALLOC1_CONSUMER_USAGE_GPU_TEXTURE;
+  }
+
   uint64_t producer_usage = alloc_flags;
   uint64_t consumer_usage = alloc_flags;
   // CreateBuffer
@@ -186,6 +191,9 @@
     case kFormatBGR565:
       *target = HAL_PIXEL_FORMAT_BGR_565;
       break;
+    case kFormatBGR888:
+      *target = HAL_PIXEL_FORMAT_BGR_888;
+      break;
     case kFormatBGRA8888:
       *target = HAL_PIXEL_FORMAT_BGRA_8888;
       break;
@@ -201,6 +209,9 @@
     case kFormatYCbCr422H2V1Packed:
       *target = HAL_PIXEL_FORMAT_YCbCr_422_I;
       break;
+    case kFormatCbYCrY422H2V1Packed:
+      *target = HAL_PIXEL_FORMAT_CbYCrY_422_I;
+      break;
     case kFormatYCbCr422H2V1SemiPlanar:
       *target = HAL_PIXEL_FORMAT_YCbCr_422_SP;
       break;
diff --git a/sdm/libs/hwc2/hwc_display.cpp b/sdm/libs/hwc2/hwc_display.cpp
index a899c0e..464bf1a 100644
--- a/sdm/libs/hwc2/hwc_display.cpp
+++ b/sdm/libs/hwc2/hwc_display.cpp
@@ -40,6 +40,8 @@
 #include "hwc_display.h"
 #include "hwc_debugger.h"
 #include "blit_engine_c2d.h"
+#include "hwc_tonemapper.h"
+
 #ifndef USE_GRALLOC1
 #include <gr.h>
 #endif
@@ -52,12 +54,23 @@
 
 namespace sdm {
 
-static void ApplyDeInterlaceAdjustment(Layer *layer) {
+static void ApplyDeInterlaceAdjustment(HWCLayer *hwc_layer, Layer *sdm_layer) {
   // De-interlacing adjustment
-  if (layer->input_buffer.flags.interlace) {
-    float height = (layer->src_rect.bottom - layer->src_rect.top) / 2.0f;
-    layer->src_rect.top = ROUND_UP_ALIGN_DOWN(layer->src_rect.top / 2.0f, 2);
-    layer->src_rect.bottom = layer->src_rect.top + floorf(height);
+  if (sdm_layer->input_buffer.flags.interlace) {
+    // Adjust src_rect only if new source crop was set
+    if (hwc_layer->GetGeometryChanges() & kSourceCrop) {
+      float height = (sdm_layer->src_rect.bottom - sdm_layer->src_rect.top) / 2.0f;
+      sdm_layer->src_rect.top = ROUND_UP_ALIGN_DOWN(sdm_layer->src_rect.top / 2.0f, 2);
+      sdm_layer->src_rect.bottom = sdm_layer->src_rect.top + floorf(height);
+    }
+
+    // Handle deinterlacing for UBWC Interlaced format.
+    if (IsUBWCFormat(sdm_layer->input_buffer.format)) {
+      sdm_layer->input_buffer.height /= 2;
+      sdm_layer->input_buffer.unaligned_height /= 2;
+      // After adjustments layer needs to be treated as UBWC progressive. Reset interlace flag.
+      sdm_layer->input_buffer.flags.interlace = 0;
+    }
   }
 }
 
@@ -156,10 +169,11 @@
   bool use_matrix = false;
   if (hint != HAL_COLOR_TRANSFORM_ARBITRARY_MATRIX) {
     // if the mode + transfrom request from HWC matches one mode in SDM, set that
-    color_mode_transform = color_mode_transform_map_[mode][hint];
     if (color_mode_transform.empty()) {
       transform_hint = HAL_COLOR_TRANSFORM_IDENTITY;
       use_matrix = true;
+    } else {
+      color_mode_transform = color_mode_transform_map_[mode][hint];
     }
   } else {
     use_matrix = true;
@@ -351,6 +365,11 @@
     return -EINVAL;
   }
 
+  HWCDebugHandler::Get()->GetProperty("sys.hwc_disable_hdr", &disable_hdr_handling_);
+  if (disable_hdr_handling_) {
+    DLOGI("HDR Handling disabled");
+  }
+
   int property_swap_interval = 1;
   HWCDebugHandler::Get()->GetProperty("debug.egl.swapinterval", &property_swap_interval);
   if (property_swap_interval == 0) {
@@ -365,6 +384,8 @@
     // TODO(user): Add blit engine when needed
   }
 
+  tone_mapper_ = new HWCToneMapper(buffer_allocator_);
+
   display_intf_->GetRefreshRateRange(&min_refresh_rate_, &max_refresh_rate_);
   current_refresh_rate_ = max_refresh_rate_;
   DLOGI("Display created with id: %d", id_);
@@ -385,6 +406,9 @@
     delete color_mode_;
   }
 
+  delete tone_mapper_;
+  tone_mapper_ = nullptr;
+
   return 0;
 }
 
@@ -498,12 +522,21 @@
       }
     }
 
+    bool hdr_layer = layer->input_buffer.color_metadata.colorPrimaries == ColorPrimaries_BT2020 &&
+                     (layer->input_buffer.color_metadata.transfer == Transfer_SMPTE_ST2084 ||
+                     layer->input_buffer.color_metadata.transfer == Transfer_HLG);
+    if (hdr_layer && !disable_hdr_handling_) {
+      // dont honor HDR when its handling is disabled
+      layer->input_buffer.flags.hdr = true;
+      layer_stack_.flags.hdr_present = true;
+    }
+
     // TODO(user): Move to a getter if this is needed at other places
     hwc_rect_t scaled_display_frame = {INT(layer->dst_rect.left), INT(layer->dst_rect.top),
                                        INT(layer->dst_rect.right), INT(layer->dst_rect.bottom)};
     ApplyScanAdjustment(&scaled_display_frame);
     hwc_layer->SetLayerDisplayFrame(scaled_display_frame);
-    ApplyDeInterlaceAdjustment(layer);
+    ApplyDeInterlaceAdjustment(hwc_layer, layer);
     // SDM requires these details even for solid fill
     if (layer->flags.solid_fill) {
       LayerBuffer *layer_buffer = &layer->input_buffer;
@@ -642,6 +675,9 @@
       // Do not flush until a buffer is successfully submitted again.
       flush_on_error = false;
       state = kStateOff;
+      if (tone_mapper_) {
+        tone_mapper_->Terminate();
+      }
       break;
     case HWC2::PowerMode::On:
       state = kStateOn;
@@ -833,6 +869,10 @@
   dump_frame_index_ = 0;
   dump_input_layers_ = ((bit_mask_layer_type & (1 << INPUT_LAYER_DUMP)) != 0);
 
+  if (tone_mapper_) {
+    tone_mapper_->SetFrameDumpConfig(count);
+  }
+
   DLOGI("num_frame_dump %d, input_layer_dump_enable %d", dump_frame_count_, dump_input_layers_);
 }
 
@@ -999,6 +1039,12 @@
       i++;
     }
   }
+
+  auto client_target_layer = client_target_->GetSDMLayer();
+  if (client_target_layer->request.flags.flip_buffer) {
+    *out_display_requests = INT32(HWC2::DisplayRequest::FlipClientTarget);
+  }
+
   return HWC2::Error::None;
 }
 
@@ -1043,6 +1089,17 @@
 
   if (!flush_) {
     DisplayError error = kErrorUndefined;
+    int status = 0;
+    if (tone_mapper_) {
+      if (layer_stack_.flags.hdr_present) {
+        status = tone_mapper_->HandleToneMap(&layer_stack_);
+        if (status != 0) {
+          DLOGE("Error handling HDR in ToneMapper");
+        }
+      } else {
+        tone_mapper_->Terminate();
+      }
+    }
     error = display_intf_->Commit(&layer_stack_);
     validated_ = false;
 
@@ -1073,6 +1130,10 @@
     display_intf_->Flush();
   }
 
+  if (tone_mapper_ && tone_mapper_->IsActive()) {
+     tone_mapper_->PostCommit(&layer_stack_);
+  }
+
   // TODO(user): No way to set the client target release fence on SF
   int32_t &client_target_release_fence =
       client_target_->GetSDMLayer()->input_buffer.release_fence_fd;
@@ -1124,6 +1185,8 @@
   geometry_changes_ = GeometryChanges::kNone;
   flush_ = false;
 
+  ClearRequestFlags();
+
   return status;
 }
 
@@ -1206,6 +1269,9 @@
     case HAL_PIXEL_FORMAT_BGR_565:
       format = kFormatBGR565;
       break;
+    case HAL_PIXEL_FORMAT_BGR_888:
+      format = kFormatBGR888;
+      break;
     case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:
     case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS:
       format = kFormatYCbCr420SemiPlanarVenus;
@@ -1231,6 +1297,9 @@
     case HAL_PIXEL_FORMAT_YCbCr_422_I:
       format = kFormatYCbCr422H2V1Packed;
       break;
+    case HAL_PIXEL_FORMAT_CbYCrY_422_I:
+      format = kFormatCbYCrY422H2V1Packed;
+      break;
     case HAL_PIXEL_FORMAT_RGBA_1010102:
       format = kFormatRGBA1010102;
       break;
@@ -1754,6 +1823,12 @@
   }
 }
 
+void HWCDisplay::ClearRequestFlags() {
+  for (Layer *layer : layer_stack_.layers) {
+    layer->request.flags = {};
+  }
+}
+
 std::string HWCDisplay::Dump() {
   std::ostringstream os;
   os << "-------------------------------" << std::endl;
diff --git a/sdm/libs/hwc2/hwc_display.h b/sdm/libs/hwc2/hwc_display.h
index 276bee8..a375831 100644
--- a/sdm/libs/hwc2/hwc_display.h
+++ b/sdm/libs/hwc2/hwc_display.h
@@ -39,6 +39,7 @@
 namespace sdm {
 
 class BlitEngine;
+class HWCToneMapper;
 
 // Subclasses set this to their type. This has to be different from DisplayType.
 // This is to avoid RTTI and dynamic_cast
@@ -83,7 +84,10 @@
   android_color_transform_t current_color_transform_ = HAL_COLOR_TRANSFORM_IDENTITY;
   typedef std::map<android_color_transform_t, std::string> TransformMap;
   std::map<android_color_mode_t, TransformMap> color_mode_transform_map_ = {};
-  double color_matrix_[kColorTransformMatrixCount] = {0};
+  double color_matrix_[kColorTransformMatrixCount] = { 1.0, 0.0, 0.0, 0.0, \
+                                                       0.0, 1.0, 0.0, 0.0, \
+                                                       0.0, 0.0, 1.0, 0.0, \
+                                                       0.0, 0.0, 0.0, 1.0 };
 };
 
 class HWCDisplay : public DisplayEventHandler {
@@ -230,6 +234,7 @@
   bool IsLayerUpdating(const Layer *layer);
   uint32_t SanitizeRefreshRate(uint32_t req_refresh_rate);
   virtual void CloseAcquireFds();
+  virtual void ClearRequestFlags();
 
   enum {
     INPUT_LAYER_DUMP,
@@ -276,6 +281,8 @@
   bool validated_ = false;
   bool color_tranform_failed_ = false;
   HWCColorMode *color_mode_ = NULL;
+  HWCToneMapper *tone_mapper_ = nullptr;
+  int disable_hdr_handling_ = 0;  // disables HDR handling.
 
  private:
   void DumpInputBuffers(void);
diff --git a/sdm/libs/hwc2/hwc_display_external.cpp b/sdm/libs/hwc2/hwc_display_external.cpp
index 39d4671..a8f8480 100644
--- a/sdm/libs/hwc2/hwc_display_external.cpp
+++ b/sdm/libs/hwc2/hwc_display_external.cpp
@@ -121,6 +121,8 @@
     return status;
   }
 
+  // TODO(user): SetRefreshRate need to follow new interface when added.
+
   status = PrepareLayerStack(out_num_types, out_num_requests);
   return status;
 }
diff --git a/sdm/libs/hwc2/hwc_display_primary.cpp b/sdm/libs/hwc2/hwc_display_primary.cpp
index f3404a3..2fcf2a9 100644
--- a/sdm/libs/hwc2/hwc_display_primary.cpp
+++ b/sdm/libs/hwc2/hwc_display_primary.cpp
@@ -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
@@ -112,8 +112,9 @@
     return status;
   }
   color_mode_ = new HWCColorMode(display_intf_);
+  color_mode_->Init();
 
-  return INT(color_mode_->Init());
+  return status;
 }
 
 void HWCDisplayPrimary::ProcessBootAnimCompleted() {
@@ -187,19 +188,13 @@
   ToggleCPUHint(one_updating_layer);
 
   uint32_t refresh_rate = GetOptimalRefreshRate(one_updating_layer);
-  if (current_refresh_rate_ != refresh_rate) {
-    error = display_intf_->SetRefreshRate(refresh_rate);
-  }
-
+  bool final_rate = force_refresh_rate_ ? true : false;
+  error = display_intf_->SetRefreshRate(refresh_rate, final_rate);
   if (error == kErrorNone) {
     // On success, set current refresh rate to new refresh rate
     current_refresh_rate_ = refresh_rate;
   }
 
-  if (handle_idle_timeout_) {
-    handle_idle_timeout_ = false;
-  }
-
   if (layer_set_.empty()) {
     flush_ = true;
     return status;
@@ -392,8 +387,6 @@
 uint32_t HWCDisplayPrimary::GetOptimalRefreshRate(bool one_updating_layer) {
   if (force_refresh_rate_) {
     return force_refresh_rate_;
-  } else if (handle_idle_timeout_) {
-    return min_refresh_rate_;
   } else if (use_metadata_refresh_rate_ && one_updating_layer && metadata_refresh_rate_) {
     return metadata_refresh_rate_;
   }
@@ -405,7 +398,6 @@
   DisplayError error = kErrorNone;
 
   callbacks_->Refresh(HWC_DISPLAY_PRIMARY);
-  handle_idle_timeout_ = true;
 
   return error;
 }
diff --git a/sdm/libs/hwc2/hwc_display_primary.h b/sdm/libs/hwc2/hwc_display_primary.h
index b98de2b..4df65b3 100644
--- a/sdm/libs/hwc2/hwc_display_primary.h
+++ b/sdm/libs/hwc2/hwc_display_primary.h
@@ -88,7 +88,6 @@
 
   BufferAllocator *buffer_allocator_ = nullptr;
   CPUHint *cpu_hint_ = nullptr;
-  bool handle_idle_timeout_ = false;
 
   // Primary output buffer configuration
   LayerBuffer output_buffer_ = {};
diff --git a/sdm/libs/hwc2/hwc_layers.cpp b/sdm/libs/hwc2/hwc_layers.cpp
index da8a1d8..30e9f83 100644
--- a/sdm/libs/hwc2/hwc_layers.cpp
+++ b/sdm/libs/hwc2/hwc_layers.cpp
@@ -426,6 +426,9 @@
     case HAL_PIXEL_FORMAT_RGB_888:
       format = kFormatRGB888;
       break;
+    case HAL_PIXEL_FORMAT_BGR_888:
+      format = kFormatBGR888;
+      break;
     case HAL_PIXEL_FORMAT_RGB_565:
       format = kFormatRGB565;
       break;
@@ -457,6 +460,9 @@
     case HAL_PIXEL_FORMAT_YCbCr_422_I:
       format = kFormatYCbCr422H2V1Packed;
       break;
+    case HAL_PIXEL_FORMAT_CbYCrY_422_I:
+      format = kFormatCbYCrY422H2V1Packed;
+      break;
     case HAL_PIXEL_FORMAT_RGBA_1010102:
       format = kFormatRGBA1010102;
       break;
@@ -690,7 +696,7 @@
     case kCompositionGPU:
       hwc_composition = HWC2::Composition::Client;
       break;
-    case kCompositionHWCursor:
+    case kCompositionCursor:
       hwc_composition = HWC2::Composition::Cursor;
       break;
     default:
diff --git a/sdm/libs/hwc2/hwc_tonemapper.cpp b/sdm/libs/hwc2/hwc_tonemapper.cpp
new file mode 100644
index 0000000..887c24b
--- /dev/null
+++ b/sdm/libs/hwc2/hwc_tonemapper.cpp
@@ -0,0 +1,340 @@
+/*
+* 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
+* met:
+*  * Redistributions of source code must retain the above copyright
+*    notice, this list of conditions and the following disclaimer.
+*  * Redistributions in binary form must reproduce the above
+*    copyright notice, this list of conditions and the following
+*    disclaimer in the documentation and/or other materials provided
+*    with the distribution.
+*  * Neither the name of The Linux Foundation nor the names of its
+*    contributors may be used to endorse or promote products derived
+*    from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+* ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <gralloc_priv.h>
+#include <sync/sync.h>
+
+#include <TonemapFactory.h>
+
+#include <core/buffer_allocator.h>
+
+#include <utils/constants.h>
+#include <utils/debug.h>
+#include <utils/formats.h>
+#include <utils/rect.h>
+#include <utils/utils.h>
+
+#include <vector>
+
+#include "hwc_debugger.h"
+#include "hwc_tonemapper.h"
+
+#define __CLASS__ "HWCToneMapper"
+
+namespace sdm {
+
+ToneMapSession::ToneMapSession(HWCBufferAllocator *buffer_allocator) :
+                buffer_allocator_(buffer_allocator) {
+  buffer_info_.resize(kNumIntermediateBuffers);
+}
+
+ToneMapSession::~ToneMapSession() {
+  delete gpu_tone_mapper_;
+  gpu_tone_mapper_ = nullptr;
+  FreeIntermediateBuffers();
+  buffer_info_.clear();
+}
+
+DisplayError ToneMapSession::AllocateIntermediateBuffers(const Layer *layer) {
+  DisplayError error = kErrorNone;
+  for (uint8_t i = 0; i < kNumIntermediateBuffers; i++) {
+    BufferInfo &buffer_info = buffer_info_[i];
+    buffer_info.buffer_config.width = layer->request.width;
+    buffer_info.buffer_config.height = layer->request.height;
+    buffer_info.buffer_config.format = layer->request.format;
+    buffer_info.buffer_config.secure = layer->request.flags.secure;
+    buffer_info.buffer_config.gfx_client = true;
+    error = buffer_allocator_->AllocateBuffer(&buffer_info);
+    if (error != kErrorNone) {
+      FreeIntermediateBuffers();
+      return error;
+    }
+  }
+
+  return kErrorNone;
+}
+
+void ToneMapSession::FreeIntermediateBuffers() {
+  for (uint8_t i = 0; i < kNumIntermediateBuffers; i++) {
+    // Free the valid fence
+    if (release_fence_fd_[i] >= 0) {
+      CloseFd(&release_fence_fd_[i]);
+    }
+    BufferInfo &buffer_info = buffer_info_[i];
+    if (buffer_info.private_data) {
+      buffer_allocator_->FreeBuffer(&buffer_info);
+    }
+  }
+}
+
+void ToneMapSession::UpdateBuffer(int acquire_fence, LayerBuffer *buffer) {
+  // Acquire fence will be closed by HWC Display.
+  // Fence returned by GPU will be closed in PostCommit.
+  buffer->acquire_fence_fd = acquire_fence;
+  buffer->size = buffer_info_[current_buffer_index_].alloc_buffer_info.size;
+  buffer->planes[0].fd = buffer_info_[current_buffer_index_].alloc_buffer_info.fd;
+}
+
+void ToneMapSession::SetReleaseFence(int fd) {
+  CloseFd(&release_fence_fd_[current_buffer_index_]);
+  // Used to give to GPU tonemapper along with input layer fd
+  release_fence_fd_[current_buffer_index_] = dup(fd);
+}
+
+void ToneMapSession::SetToneMapConfig(Layer *layer) {
+  // HDR -> SDR is FORWARD and SDR - > HDR is INVERSE
+  tone_map_config_.type = layer->input_buffer.flags.hdr ? TONEMAP_FORWARD : TONEMAP_INVERSE;
+  tone_map_config_.colorPrimaries = layer->input_buffer.color_metadata.colorPrimaries;
+  tone_map_config_.transfer = layer->input_buffer.color_metadata.transfer;
+  tone_map_config_.secure = layer->request.flags.secure;
+  tone_map_config_.format = layer->request.format;
+}
+
+bool ToneMapSession::IsSameToneMapConfig(Layer *layer) {
+  LayerBuffer& buffer = layer->input_buffer;
+  private_handle_t *handle = static_cast<private_handle_t *>(buffer_info_[0].private_data);
+  int tonemap_type = buffer.flags.hdr ? TONEMAP_FORWARD : TONEMAP_INVERSE;
+
+  return ((tonemap_type == tone_map_config_.type) &&
+          (buffer.color_metadata.colorPrimaries == tone_map_config_.colorPrimaries) &&
+          (buffer.color_metadata.transfer == tone_map_config_.transfer) &&
+          (layer->request.flags.secure == tone_map_config_.secure) &&
+          (layer->request.format == tone_map_config_.format) &&
+          (layer->request.width == UINT32(handle->unaligned_width)) &&
+          (layer->request.height == UINT32(handle->unaligned_height)));
+}
+
+int HWCToneMapper::HandleToneMap(LayerStack *layer_stack) {
+  uint32_t gpu_count = 0;
+  DisplayError error = kErrorNone;
+
+  for (uint32_t i = 0; i < layer_stack->layers.size(); i++) {
+    uint32_t session_index = 0;
+    Layer *layer = layer_stack->layers.at(i);
+    if (layer->composition == kCompositionGPU) {
+      gpu_count++;
+    }
+
+    if (layer->request.flags.tone_map) {
+      switch (layer->composition) {
+      case kCompositionGPUTarget:
+        if (!gpu_count) {
+          // When all layers are on FrameBuffer and if they do not update in the next draw cycle,
+          // then SDM marks them for SDE Composition because the cached FB layer gets displayed.
+          // GPU count will be 0 in this case. Try to use the existing tone-mapped frame buffer.
+          // No ToneMap/Blit is required. Just update the buffer & acquire fence fd of FB layer.
+          if (!tone_map_sessions_.empty()) {
+            ToneMapSession *fb_tone_map_session = tone_map_sessions_.at(fb_session_index_);
+            fb_tone_map_session->UpdateBuffer(-1 /* acquire_fence */, &layer->input_buffer);
+            fb_tone_map_session->layer_index_ = INT(i);
+            fb_tone_map_session->acquired_ = true;
+            return 0;
+          }
+        }
+        error = AcquireToneMapSession(layer, &session_index);
+        fb_session_index_ = session_index;
+        break;
+      default:
+        error = AcquireToneMapSession(layer, &session_index);
+        break;
+      }
+
+      if (error != kErrorNone) {
+        Terminate();
+        return -1;
+      }
+
+      ToneMapSession *session = tone_map_sessions_.at(session_index);
+      ToneMap(layer, session);
+      session->layer_index_ = INT(i);
+    }
+  }
+
+  return 0;
+}
+
+void HWCToneMapper::ToneMap(Layer* layer, ToneMapSession *session) {
+  int fence_fd = -1;
+  int acquire_fd = -1;
+  int merged_fd = -1;
+
+  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);
+
+  // 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);
+
+  if (acquire_fd >= 0) {
+    CloseFd(&acquire_fd);
+  }
+
+  if (session->release_fence_fd_[buffer_index] >= 0) {
+    CloseFd(&session->release_fence_fd_[buffer_index]);
+  }
+
+  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);
+  DTRACE_END();
+
+  DumpToneMapOutput(session, &fence_fd);
+  session->UpdateBuffer(fence_fd, &layer->input_buffer);
+}
+
+void HWCToneMapper::PostCommit(LayerStack *layer_stack) {
+  auto it = tone_map_sessions_.begin();
+  while (it != tone_map_sessions_.end()) {
+    uint32_t session_index = UINT32(std::distance(tone_map_sessions_.begin(), it));
+    ToneMapSession *session = tone_map_sessions_.at(session_index);
+    if (session->acquired_) {
+      Layer *layer = layer_stack->layers.at(UINT32(session->layer_index_));
+      // Close the fd returned by GPU ToneMapper and set release fence.
+      LayerBuffer &layer_buffer = layer->input_buffer;
+      CloseFd(&layer_buffer.acquire_fence_fd);
+      session->SetReleaseFence(layer_buffer.release_fence_fd);
+      session->acquired_ = false;
+      it++;
+    } else {
+      delete session;
+      it = tone_map_sessions_.erase(it);
+    }
+  }
+}
+
+void HWCToneMapper::Terminate() {
+  if (tone_map_sessions_.size()) {
+    while (!tone_map_sessions_.empty()) {
+      delete tone_map_sessions_.back();
+      tone_map_sessions_.pop_back();
+    }
+    fb_session_index_ = 0;
+  }
+}
+
+void HWCToneMapper::SetFrameDumpConfig(uint32_t count) {
+  DLOGI("Dump FrameConfig count = %d", count);
+  dump_frame_count_ = count;
+  dump_frame_index_ = 0;
+}
+
+void HWCToneMapper::DumpToneMapOutput(ToneMapSession *session, int *acquire_fd) {
+  if (!dump_frame_count_) {
+    return;
+  }
+
+  BufferInfo &buffer_info = session->buffer_info_[session->current_buffer_index_];
+  private_handle_t *target_buffer = static_cast<private_handle_t *>(buffer_info.private_data);
+
+  if (*acquire_fd >= 0) {
+    int error = sync_wait(*acquire_fd, 1000);
+    if (error < 0) {
+      DLOGW("sync_wait error errno = %d, desc = %s", errno, strerror(errno));
+      return;
+    }
+  }
+
+  size_t result = 0;
+  char dump_file_name[PATH_MAX];
+  snprintf(dump_file_name, sizeof(dump_file_name), "/data/misc/display/frame_dump_primary"
+           "/tonemap_%dx%d_frame%d.raw", target_buffer->width, target_buffer->height,
+           dump_frame_index_);
+
+  FILE* fp = fopen(dump_file_name, "w+");
+  if (fp) {
+    DLOGI("base addr = %x", target_buffer->base);
+    result = fwrite(reinterpret_cast<void *>(target_buffer->base), target_buffer->size, 1, fp);
+    fclose(fp);
+  }
+  dump_frame_count_--;
+  dump_frame_index_++;
+  CloseFd(acquire_fd);
+}
+
+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.
+  if (!layer->lut_3d.lutEntries || !layer->lut_3d.dim) {
+    // Atleast lutEntries must be valid for GPU Tonemapper.
+    DLOGE("Invalid Lut Entries or lut dimension = %d", layer->lut_3d.dim);
+    return kErrorParameters;
+  }
+
+  // Check if we can re-use an existing tone map session.
+  for (uint32_t i = 0; i < tone_map_sessions_.size(); i++) {
+    ToneMapSession *tonemap_session = tone_map_sessions_.at(i);
+    if (!tonemap_session->acquired_ && tonemap_session->IsSameToneMapConfig(layer)) {
+      tonemap_session->current_buffer_index_ = (tonemap_session->current_buffer_index_ + 1) %
+                                                ToneMapSession::kNumIntermediateBuffers;
+      tonemap_session->acquired_ = true;
+      *session_index = i;
+      return kErrorNone;
+    }
+  }
+
+  ToneMapSession *session = new ToneMapSession(buffer_allocator_);
+
+  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);
+
+  if (session->gpu_tone_mapper_ == NULL) {
+    DLOGE("Get Tonemapper failed!");
+    delete session;
+    return kErrorNotSupported;
+  }
+  DisplayError error = session->AllocateIntermediateBuffers(layer);
+  if (error != kErrorNone) {
+    DLOGE("Allocation of Intermediate Buffers failed!");
+    delete session;
+    return error;
+  }
+
+  session->acquired_ = true;
+  tone_map_sessions_.push_back(session);
+  *session_index = UINT32(tone_map_sessions_.size() - 1);
+
+  return kErrorNone;
+}
+
+}  // namespace sdm
diff --git a/sdm/libs/hwc2/hwc_tonemapper.h b/sdm/libs/hwc2/hwc_tonemapper.h
new file mode 100644
index 0000000..8367c3e
--- /dev/null
+++ b/sdm/libs/hwc2/hwc_tonemapper.h
@@ -0,0 +1,103 @@
+/*
+* 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
+* met:
+*  * Redistributions of source code must retain the above copyright
+*    notice, this list of conditions and the following disclaimer.
+*  * Redistributions in binary form must reproduce the above
+*    copyright notice, this list of conditions and the following
+*    disclaimer in the documentation and/or other materials provided
+*    with the distribution.
+*  * Neither the name of The Linux Foundation nor the names of its
+*    contributors may be used to endorse or promote products derived
+*    from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+* ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef __HWC_TONEMAPPER_H__
+#define __HWC_TONEMAPPER_H__
+
+#include <fcntl.h>
+#include <sys/mman.h>
+
+#include <hardware/hwcomposer.h>
+
+#include <core/layer_stack.h>
+#include <utils/sys.h>
+#include <vector>
+#include "hwc_buffer_sync_handler.h"
+#include "hwc_buffer_allocator.h"
+
+class Tonemapper;
+
+namespace sdm {
+
+struct ToneMapConfig {
+  int type = 0;
+  ColorPrimaries colorPrimaries = ColorPrimaries_Max;
+  GammaTransfer transfer = Transfer_Max;
+  LayerBufferFormat format = kFormatRGBA8888;
+  bool secure = false;
+};
+
+class ToneMapSession {
+ public:
+  explicit ToneMapSession(HWCBufferAllocator *buffer_allocator);
+  ~ToneMapSession();
+  DisplayError AllocateIntermediateBuffers(const Layer *layer);
+  void FreeIntermediateBuffers();
+  void UpdateBuffer(int acquire_fence, LayerBuffer *buffer);
+  void SetReleaseFence(int fd);
+  void SetToneMapConfig(Layer *layer);
+  bool IsSameToneMapConfig(Layer *layer);
+
+  static const uint8_t kNumIntermediateBuffers = 2;
+  Tonemapper *gpu_tone_mapper_ = nullptr;
+  HWCBufferAllocator *buffer_allocator_ = nullptr;
+  ToneMapConfig tone_map_config_ = {};
+  uint8_t current_buffer_index_ = 0;
+  std::vector<BufferInfo> buffer_info_ = {};
+  int release_fence_fd_[kNumIntermediateBuffers] = {-1, -1};
+  bool acquired_ = false;
+  int layer_index_ = -1;
+};
+
+class HWCToneMapper {
+ public:
+  explicit HWCToneMapper(HWCBufferAllocator *allocator) : buffer_allocator_(allocator) {}
+  ~HWCToneMapper() {}
+
+  int HandleToneMap(LayerStack *layer_stack);
+  bool IsActive() { return !tone_map_sessions_.empty(); }
+  void PostCommit(LayerStack *layer_stack);
+  void SetFrameDumpConfig(uint32_t count);
+  void Terminate();
+
+ private:
+  void ToneMap(Layer *layer, ToneMapSession *session);
+  DisplayError AcquireToneMapSession(Layer *layer, uint32_t *session_index);
+  void DumpToneMapOutput(ToneMapSession *session, int *acquire_fence);
+
+  std::vector<ToneMapSession*> tone_map_sessions_;
+  HWCBufferSyncHandler buffer_sync_handler_ = {};
+  HWCBufferAllocator *buffer_allocator_ = nullptr;
+  uint32_t dump_frame_count_ = 0;
+  uint32_t dump_frame_index_ = 0;
+  uint32_t fb_session_index_ = 0;
+};
+
+}  // namespace sdm
+#endif  // __HWC_TONEMAPPER_H__
diff --git a/sdm/libs/utils/Android.mk b/sdm/libs/utils/Android.mk
index 36d1148..fe89104 100644
--- a/sdm/libs/utils/Android.mk
+++ b/sdm/libs/utils/Android.mk
@@ -3,12 +3,7 @@
 include $(LOCAL_PATH)/../../../common.mk
 
 LOCAL_MODULE                  := libsdmutils
-
-ifneq ($(TARGET_IS_HEADLESS), true)
-LOCAL_MODULE_PATH_32          := $(TARGET_OUT_VENDOR)/lib
-LOCAL_MODULE_PATH_64          := $(TARGET_OUT_VENDOR)/lib64
-endif
-
+LOCAL_VENDOR_MODULE           := true
 LOCAL_MODULE_TAGS             := optional
 LOCAL_C_INCLUDES              := $(common_includes)
 LOCAL_HEADER_LIBRARIES        := display_headers
@@ -30,5 +25,7 @@
                                  $(SDM_HEADER_PATH)/utils/locker.h \
                                  $(SDM_HEADER_PATH)/utils/rect.h \
                                  $(SDM_HEADER_PATH)/utils/sys.h \
-                                 $(SDM_HEADER_PATH)/utils/utils.h
+                                 $(SDM_HEADER_PATH)/utils/utils.h \
+                                 $(SDM_HEADER_PATH)/utils/factory.h
+
 include $(BUILD_COPY_HEADERS)