display: Update to AU199 proprietary drop

Update to AU_LINUX_ANDROID_LA.HB.1.3.9.06.00.01.213.199

These display HAL changes are necessary for getting HWC2 fixed.

display_hal:
a46b76b Promotion of display.lnx.3.0-00025.
353beaa Promotion of display.lnx.3.0-00024.
5f57d11 sdm: Add support to override detail enhancer settings
fc09cc2 sdm: Modify partial update interface for destination scalar.
6884047 sdm: Add support for dynamic layer mixer resolution change.
2e9ea8d sdm: Move display state and input validation in appropriate place
b29788d Merge "hwc2: Use floating value refresh rate"
89ff452 hwc2: Use floating value refresh rate
29cd658 sdm: Add support for color mode & color transform
1626488 sdm: color-manager: New color management feature.
a216262 Merge "sdm: Add interface to disable PU for one frame"
8ce93e9 Promotion of display.lnx.3.0-00022.
3abfa78 Merge "qdutils: Query MDP caps for UBWC feature"
149b8bc libmemtrack: Update parsing of kgsl mem file
8011276 sdm: Add interface to disable PU for one frame
e7e9d0f Promotion of display.lnx.3.0-00021.
0136141 qdutils: Query MDP caps for UBWC feature
cad386a Promotion of display.lnx.3.0-00019.
4625171 Promotion of display.lnx.3.0-00018.
0a006ac Promotion of display.lnx.3.0-00017.
1204328 Promotion of display.lnx.3.0-00016.

Bug: 29463310
Change-Id: Ifc0d2a81503a7d8b91f08b7fcd2c5346f79e8c8b
diff --git a/msm8996/libgralloc/alloc_controller.cpp b/msm8996/libgralloc/alloc_controller.cpp
index 2a5d099..e9cdc73 100644
--- a/msm8996/libgralloc/alloc_controller.cpp
+++ b/msm8996/libgralloc/alloc_controller.cpp
@@ -99,14 +99,10 @@
 
 //------------- MDPCapabilityInfo-----------------------//
 MDPCapabilityInfo :: MDPCapabilityInfo() {
-  isMacroTileSupported = false;
   qdutils::querySDEInfo(HAS_MACRO_TILE, &isMacroTileSupported);
+  qdutils::querySDEInfo(HAS_UBWC, &isUBwcSupported);
 }
 
-int MDPCapabilityInfo :: isMacroTilingSupportedByMDP(){
-    return isMacroTileSupported;
- }
-
 //------------- AdrenoMemInfo-----------------------//
 AdrenoMemInfo::AdrenoMemInfo()
 {
@@ -932,20 +928,23 @@
 
 static bool isUBwcSupported(int format)
 {
-    // Existing HAL formats with UBWC support
-    switch(format)
-    {
-        case HAL_PIXEL_FORMAT_BGR_565:
-        case HAL_PIXEL_FORMAT_RGBA_8888:
-        case HAL_PIXEL_FORMAT_RGBX_8888:
-        case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:
-        case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS:
-        case HAL_PIXEL_FORMAT_RGBA_1010102:
-        case HAL_PIXEL_FORMAT_RGBX_1010102:
-            return true;
-        default:
-            return false;
+    if (MDPCapabilityInfo::getInstance().isUBwcSupportedByMDP()) {
+        // Existing HAL formats with UBWC support
+        switch(format)
+        {
+            case HAL_PIXEL_FORMAT_BGR_565:
+            case HAL_PIXEL_FORMAT_RGBA_8888:
+            case HAL_PIXEL_FORMAT_RGBX_8888:
+            case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:
+            case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS:
+            case HAL_PIXEL_FORMAT_RGBA_1010102:
+            case HAL_PIXEL_FORMAT_RGBX_1010102:
+                return true;
+            default:
+                break;
+        }
     }
+    return false;
 }
 
 bool isUBwcEnabled(int format, int usage)
diff --git a/msm8996/libgralloc/gr.h b/msm8996/libgralloc/gr.h
index e7d449e..5fe1bdb 100644
--- a/msm8996/libgralloc/gr.h
+++ b/msm8996/libgralloc/gr.h
@@ -201,7 +201,9 @@
 
 class MDPCapabilityInfo : public android::Singleton <MDPCapabilityInfo>
 {
-    int isMacroTileSupported;
+    int isMacroTileSupported = 0;
+    int isUBwcSupported = 0;
+
     public:
         MDPCapabilityInfo();
         /*
@@ -210,8 +212,14 @@
         * @return  1 : supported
         *          0 : not supported
         */
-        int isMacroTilingSupportedByMDP();
-
+        int isMacroTilingSupportedByMDP() { return isMacroTileSupported; }
+        /*
+        * Function to return whether MDP supports UBWC feature
+        *
+        * @return  1 : supported
+        *          0 : not supported
+        */
+        int isUBwcSupportedByMDP() { return isUBwcSupported; }
 };
 
 #endif /* GR_H_ */
diff --git a/msm8996/libmemtrack/kgsl.c b/msm8996/libmemtrack/kgsl.c
index 4ad94ce..5a6b075 100644
--- a/msm8996/libmemtrack/kgsl.c
+++ b/msm8996/libmemtrack/kgsl.c
@@ -83,7 +83,7 @@
      * count the entry as accounted else count the entry as unaccounted.
      */
     while (1) {
-        unsigned long size;
+        unsigned long size, mapsize;
         char line_type[7];
         char flags[8];
         char line_usage[19];
@@ -94,20 +94,21 @@
         }
 
         /* Format:
-         *  gpuaddr useraddr     size    id flags       type            usage sglen
-         * 545ba000 545ba000     4096     1 -----pY     gpumem      arraybuffer     1
+         *  gpuaddr useraddr     size    id flags       type            usage sglen mapsize
+         * 545ba000 545ba000     4096     1 -----pY     gpumem      arraybuffer     1  4096
          */
-        ret = sscanf(line, "%*x %*x %lu %*d %7s %6s %18s %*d\n",
-                     &size, flags, line_type, line_usage);
-        if (ret != 4) {
+        ret = sscanf(line, "%*x %*x %lu %*d %7s %6s %18s %*d %lu\n",
+                     &size, flags, line_type, line_usage, &mapsize);
+        if (ret != 5) {
             continue;
         }
 
         if (type == MEMTRACK_TYPE_GL && strcmp(line_type, "gpumem") == 0) {
 
-            if (flags[6] == 'Y')
-                accounted_size += size;
-            else
+            if (flags[6] == 'Y') {
+                accounted_size += mapsize;
+		unaccounted_size += size - mapsize;
+	    } else
                 unaccounted_size += size;
 
         } else if (type == MEMTRACK_TYPE_GRAPHICS && strcmp(line_type, "ion") == 0) {
diff --git a/msm8996/libqdutils/qd_utils.cpp b/msm8996/libqdutils/qd_utils.cpp
index 254df30..6453b58 100644
--- a/msm8996/libqdutils/qd_utils.cpp
+++ b/msm8996/libqdutils/qd_utils.cpp
@@ -62,6 +62,10 @@
         featureName = "tile_format";
         break;
 
+    case HAS_UBWC:
+        featureName = "ubwc";
+        break;
+
     default:
         ALOGE("Invalid query type %d", type);
         return -EINVAL;
diff --git a/msm8996/libqdutils/qd_utils.h b/msm8996/libqdutils/qd_utils.h
index 2b9ca74..0392e05 100644
--- a/msm8996/libqdutils/qd_utils.h
+++ b/msm8996/libqdutils/qd_utils.h
@@ -48,6 +48,7 @@
 
 enum HWQueryType {
     HAS_MACRO_TILE = 0,
+    HAS_UBWC = 1,
 };
 
 enum {
diff --git a/msm8996/libqservice/IQService.h b/msm8996/libqservice/IQService.h
index 2d7dddc..49467db 100644
--- a/msm8996/libqservice/IQService.h
+++ b/msm8996/libqservice/IQService.h
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2010 The Android Open Source Project
- * Copyright (C) 2012-2014, The Linux Foundation. All rights reserved.
+ * Copyright (C) 2012-2014, 2016 The Linux Foundation. All rights reserved.
  *
  * Not a Contribution, Apache license notifications and license are
  * retained for attribution purposes only.
@@ -72,6 +72,7 @@
         SET_CAMERA_STATUS = 30, // To notify display when camera is on and off
         MIN_HDCP_ENCRYPTION_LEVEL_CHANGED = 31,
         GET_BW_TRANSACTION_STATUS = 32, //Client can query BW transaction status.
+        SET_LAYER_MIXER_RESOLUTION = 33, // Enables client to set layer mixer resolution.
         COMMAND_LIST_END = 400,
     };
 
diff --git a/msm8996/sdm/include/core/display_interface.h b/msm8996/sdm/include/core/display_interface.h
index 951cd54..bb89d1d 100644
--- a/msm8996/sdm/include/core/display_interface.h
+++ b/msm8996/sdm/include/core/display_interface.h
@@ -76,6 +76,48 @@
                     //!< if VSync is enabled. Contents are not rendered in this state.
 };
 
+/*! @brief This enum represents flags to override detail enhancer parameters.
+
+  @sa DisplayInterface::SetDetailEnhancerData
+*/
+enum DetailEnhancerOverrideFlags {
+  kOverrideDEEnable            = 0x1,     // Specifies to enable detail enhancer
+  kOverrideDESharpen1          = 0x2,     // Specifies user defined Sharpening/smooth for noise
+  kOverrideDESharpen2          = 0x4,     // Specifies user defined Sharpening/smooth for signal
+  kOverrideDEClip              = 0x8,     // Specifies user defined DE clip shift
+  kOverrideDELimit             = 0x10,    // Specifies user defined DE limit value
+  kOverrideDEThrQuiet          = 0x20,    // Specifies user defined DE quiet threshold
+  kOverrideDEThrDieout         = 0x40,    // Specifies user defined DE dieout threshold
+  kOverrideDEThrLow            = 0x80,    // Specifies user defined DE low threshold
+  kOverrideDEThrHigh           = 0x100,   // Specifies user defined DE high threshold
+  kOverrideDEFilterConfig      = 0x200,   // Specifies user defined scaling filter config
+  kOverrideDEMax               = 0xFFFFFFFF,
+};
+
+/*! @brief This enum represents Y/RGB scaling filter configuration.
+
+  @sa DisplayInterface::SetDetailEnhancerData
+*/
+enum ScalingFilterConfig {
+  kFilterEdgeDirected,
+  kFilterCircular,
+  kFilterSeparable,
+  kFilterBilinear,
+  kFilterMax,
+};
+
+/*! @brief This enum represents the quality level of the content.
+
+  @sa DisplayInterface::SetDetailEnhancerData
+*/
+enum ContentQuality {
+  kContentQualityUnknown,  // Default: high artifact and noise
+  kContentQualityLow,      // Low quality content, high artifact and noise,
+  kContentQualityMedium,   // Medium quality, medium artifact and noise,
+  kContentQualityHigh,     // High quality content, low artifact and noise
+  kContentQualityMax,
+};
+
 /*! @brief This structure defines configuration for fixed properties of a display device.
 
   @sa DisplayInterface::GetConfig
@@ -109,6 +151,30 @@
   int64_t timestamp = 0;    //!< System monotonic clock timestamp in nanoseconds.
 };
 
+/*! @brief The structure defines the user input for detail enhancer module.
+
+  @sa DisplayInterface::SetDetailEnhancerData
+*/
+struct DisplayDetailEnhancerData {
+  uint32_t override_flags = 0;        // flags to specify which data to be set.
+  uint16_t enable = 0;                // Detail enchancer enable
+  int16_t sharpen_level1 = 0;         // Sharpening/smooth strenght for noise
+  int16_t sharpen_level2 = 0;         // Sharpening/smooth strenght for signal
+  uint16_t clip = 0;                  // DE clip shift
+  uint16_t limit = 0;                 // DE limit value
+  uint16_t thr_quiet = 0;             // DE quiet threshold
+  uint16_t thr_dieout = 0;            // DE dieout threshold
+  uint16_t thr_low = 0;               // DE low threshold
+  uint16_t thr_high = 0;              // DE high threshold
+  int32_t sharp_factor = 50;          // sharp_factor specifies sharpness/smoothness level,
+                                      // range -100..100 positive for sharpness and negative for
+                                      // smoothness
+  ContentQuality quality_level = kContentQualityUnknown;
+                                      // Specifies context quality level
+  ScalingFilterConfig filter_config = kFilterEdgeDirected;
+                                      // Y/RGB filter configuration
+};
+
 /*! @brief Display device event handler implemented by the client.
 
   @details This class declares prototype for display device event handler methods which must be
@@ -343,6 +409,11 @@
   */
   virtual DisplayError ControlPartialUpdate(bool enable, uint32_t *pending) = 0;
 
+  /*! @brief Method to disable partial update for at least 1 frame.
+    @return \link DisplayError \endlink
+  */
+  virtual DisplayError DisablePartialUpdateOneFrame() = 0;
+
   /*! @brief Method to set the mode of the primary display.
 
     @param[in] mode the new display mode.
@@ -351,13 +422,6 @@
   */
   virtual DisplayError SetDisplayMode(uint32_t mode) = 0;
 
-  /*! @brief Method to determine whether scaling for a custom resolution is valid.
-
-    @return \link DisplayError \endlink
-  */
-  virtual DisplayError IsScalingValid(const LayerRect &crop, const LayerRect &dst,
-                                      bool rotate90) = 0;
-
   /*! @brief Method to get the min and max refresh rate of a display.
 
     @param[out] min and max refresh rate.
@@ -467,6 +531,48 @@
   */
   virtual DisplayError GetPanelBrightness(int *level) = 0;
 
+  /*! @brief Method to set layer mixer resolution.
+
+    @param[in] width layer mixer width
+    @param[in] height layer mixer height
+
+    @return \link DisplayError \endlink
+  */
+  virtual DisplayError SetMixerResolution(uint32_t width, uint32_t height) = 0;
+
+  /*! @brief Method to get layer mixer resolution.
+
+    @param[out] width layer mixer width
+    @param[out] height layer mixer height
+
+    @return \link DisplayError \endlink
+  */
+  virtual DisplayError GetMixerResolution(uint32_t *width, uint32_t *height) = 0;
+
+  /*! @brief Method to set  frame buffer configuration.
+
+    @param[in] variable_info \link DisplayConfigVariableInfo \endlink
+
+    @return \link DisplayError \endlink
+  */
+  virtual DisplayError SetFrameBufferConfig(const DisplayConfigVariableInfo &variable_info) = 0;
+
+  /*! @brief Method to get frame buffer configuration.
+
+    @param[out] variable_info \link DisplayConfigVariableInfo \endlink
+
+    @return \link DisplayError \endlink
+  */
+  virtual DisplayError GetFrameBufferConfig(DisplayConfigVariableInfo *variable_info) = 0;
+
+  /*! @brief Method to set detail enhancement data.
+
+    @param[in] de_data \link DisplayDetailEnhancerData \endlink
+
+    @return \link DisplayError \endlink
+  */
+  virtual DisplayError SetDetailEnhancerData(const DisplayDetailEnhancerData &de_data) = 0;
+
  protected:
   virtual ~DisplayInterface() { }
 };
diff --git a/msm8996/sdm/include/core/layer_buffer.h b/msm8996/sdm/include/core/layer_buffer.h
index 7eba4e3..7713394 100644
--- a/msm8996/sdm/include/core/layer_buffer.h
+++ b/msm8996/sdm/include/core/layer_buffer.h
@@ -68,6 +68,7 @@
   kFormatXBGR2101010,   //!< 10-bits Padding, Blue, Green, Red interleaved in XBGR order. No Alpha.
   kFormatRGBA1010102Ubwc,  //!< UBWC aligned RGBA1010102 format
   kFormatRGBX1010102Ubwc,  //!< UBWC aligned RGBX1010102 format
+  kFormatRGB101010,     // 10-bits Red, Green, Blue, interleaved in RGB order. No Alpha.
 
   /* All YUV-Planar formats, Any new format will be added towards end of this group to maintain
      backward compatibility.
diff --git a/msm8996/sdm/include/private/extension_interface.h b/msm8996/sdm/include/private/extension_interface.h
index 4283b53..dea127e 100644
--- a/msm8996/sdm/include/private/extension_interface.h
+++ b/msm8996/sdm/include/private/extension_interface.h
@@ -54,11 +54,16 @@
  public:
   virtual DisplayError CreatePartialUpdate(DisplayType type, const HWResourceInfo &hw_resource_info,
                                            const HWPanelInfo &hw_panel_info,
+                                           const HWMixerAttributes &mixer_attributes,
+                                           const HWDisplayAttributes &display_attributes,
                                            PartialUpdateInterface **interface) = 0;
   virtual DisplayError DestroyPartialUpdate(PartialUpdateInterface *interface) = 0;
 
   virtual DisplayError CreateStrategyExtn(DisplayType type, HWDisplayMode mode,
-                                          HWS3DMode s3d_mode, StrategyInterface **interface) = 0;
+                                          HWS3DMode s3d_mode,
+                                          const HWMixerAttributes &mixer_attributes,
+                                          const DisplayConfigVariableInfo &fb_config,
+                                          StrategyInterface **interface) = 0;
   virtual DisplayError DestroyStrategyExtn(StrategyInterface *interface) = 0;
 
   virtual DisplayError CreateResourceExtn(const HWResourceInfo &hw_resource_info,
diff --git a/msm8996/sdm/include/private/hw_info_types.h b/msm8996/sdm/include/private/hw_info_types.h
index 70d5b96..0f40e17 100644
--- a/msm8996/sdm/include/private/hw_info_types.h
+++ b/msm8996/sdm/include/private/hw_info_types.h
@@ -91,15 +91,6 @@
   kHWSubBlockMax,
 };
 
-// y/RGB & UV Scaling Filters
-enum HWScalingFilter {
-  kScalingFilterEdgeDirected,
-  kScalingFilterCircular,
-  kScalingFilterSeparable,
-  kScalingFilterBilinear,
-  kScalingFilterMax,
-};
-
 enum HWAlphaInterpolation {
   kInterpolationPixelRepeat,
   kInterpolationBilinear,
@@ -142,6 +133,13 @@
   void Reset() { *this = HWRotatorInfo(); }
 };
 
+struct HWDestScalarInfo {
+  uint32_t count = 0;
+  uint32_t max_input_width = 0;
+  uint32_t max_output_width = 0;
+  uint32_t max_scale_up = 1;
+};
+
 struct HWResourceInfo {
   uint32_t hw_version = 0;
   uint32_t hw_revision = 0;
@@ -188,6 +186,7 @@
   std::vector<HWPipeCaps> hw_pipes;
   FormatsMap supported_formats_map;
   HWRotatorInfo hw_rot_info;
+  HWDestScalarInfo hw_dest_scalar_info;
 
   void Reset() { *this = HWResourceInfo(); }
 };
@@ -308,16 +307,7 @@
   uint64_t sep_lut = 0;
 };
 
-struct HWDetailEnhanceData {
-  uint32_t enable = 0;
-  int16_t sharpen_level1 = 0;
-  int16_t sharpen_level2 = 0;
-  uint16_t clip = 0;
-  uint16_t limit = 0;
-  uint16_t thr_quiet = 0;
-  uint16_t thr_dieout = 0;
-  uint16_t thr_low = 0;
-  uint16_t thr_high = 0;
+struct HWDetailEnhanceData : DisplayDetailEnhancerData {
   uint16_t prec_shift = 0;
   int16_t adjust_a[MAX_DETAIL_ENHANCE_CURVE] = {0};
   int16_t adjust_b[MAX_DETAIL_ENHANCE_CURVE] = {0};
@@ -362,8 +352,8 @@
   uint32_t dst_height = 0;
   HWPlane plane[MAX_PLANES];
   // scale_v2_data fields
-  HWScalingFilter y_rgb_filter_cfg = kScalingFilterEdgeDirected;
-  HWScalingFilter uv_filter_cfg = kScalingFilterEdgeDirected;
+  ScalingFilterConfig y_rgb_filter_cfg = kFilterEdgeDirected;
+  ScalingFilterConfig uv_filter_cfg = kFilterEdgeDirected;
   HWAlphaInterpolation alpha_filter_cfg = kInterpolationPixelRepeat;
   HWBlendingFilter blend_cfg = kBlendFilterCircular;
 
@@ -386,6 +376,15 @@
   HWDetailEnhanceData detail_enhance;
 };
 
+struct HWDestScaleInfo {
+  uint32_t mixer_width = 0;
+  uint32_t mixer_height = 0;
+  bool scale_update = false;
+  HWScaleData scale_data = {};
+};
+
+typedef std::map<uint32_t, HWDestScaleInfo *> DestScaleInfoMap;
+
 struct HWPipeInfo {
   uint32_t pipe_id = 0;
   HWSubBlockType sub_block_type = kHWSubBlockMax;
@@ -427,6 +426,7 @@
   LayerRect right_partial_update;  // Right ROI.
 
   bool use_hw_cursor = false;      // Indicates that HWCursor pipe needs to be used for cursor layer
+  DestScaleInfoMap dest_scale_info_map = {};
 };
 
 struct HWLayers {
@@ -439,7 +439,6 @@
 
 struct HWDisplayAttributes : DisplayConfigVariableInfo {
   bool is_device_split = false;
-  uint32_t split_left = 0;
   uint32_t v_front_porch = 0;  //!< Vertical front porch of panel
   uint32_t v_back_porch = 0;   //!< Vertical back porch of panel
   uint32_t v_pulse_width = 0;  //!< Vertical pulse width of panel
@@ -448,20 +447,44 @@
 
   void Reset() { *this = HWDisplayAttributes(); }
 
-  bool operator !=(const HWDisplayAttributes &attributes) {
-    return ((is_device_split != attributes.is_device_split) ||
-            (split_left != attributes.split_left) ||
-            (x_pixels != attributes.x_pixels) || (y_pixels != attributes.y_pixels) ||
-            (x_dpi != attributes.x_dpi) || (y_dpi != attributes.y_dpi) || (fps != attributes.fps) ||
-            (vsync_period_ns != attributes.vsync_period_ns) ||
-            (v_front_porch != attributes.v_front_porch) ||
-            (v_back_porch != attributes.v_back_porch) ||
-            (v_pulse_width != attributes.v_pulse_width) ||
-            (is_yuv != attributes.is_yuv));
+  bool operator !=(const HWDisplayAttributes &display_attributes) {
+    return ((is_device_split != display_attributes.is_device_split) ||
+            (x_pixels != display_attributes.x_pixels) ||
+            (y_pixels != display_attributes.y_pixels) ||
+            (x_dpi != display_attributes.x_dpi) ||
+            (y_dpi != display_attributes.y_dpi) ||
+            (fps != display_attributes.fps) ||
+            (vsync_period_ns != display_attributes.vsync_period_ns) ||
+            (v_front_porch != display_attributes.v_front_porch) ||
+            (v_back_porch != display_attributes.v_back_porch) ||
+            (v_pulse_width != display_attributes.v_pulse_width) ||
+            (is_yuv != display_attributes.is_yuv));
   }
 
-  bool operator ==(const HWDisplayAttributes &attributes) {
-    return !(operator !=(attributes));
+  bool operator ==(const HWDisplayAttributes &display_attributes) {
+    return !(operator !=(display_attributes));
+  }
+};
+
+struct HWMixerAttributes {
+  uint32_t width = 0;                                  // Layer mixer width
+  uint32_t height = 0;                                 // Layer mixer height
+  uint32_t split_left = 0;
+  LayerBufferFormat output_format = kFormatRGB101010;  // Layer mixer output format
+
+  bool operator !=(const HWMixerAttributes &mixer_attributes) {
+    return ((width != mixer_attributes.width) ||
+            (height != mixer_attributes.height) ||
+            (output_format != mixer_attributes.output_format) ||
+            (split_left != mixer_attributes.split_left));
+  }
+
+  bool operator ==(const HWMixerAttributes &mixer_attributes) {
+    return !(operator !=(mixer_attributes));
+  }
+
+  bool IsValid() {
+    return (width > 0 && height > 0);
   }
 };
 
diff --git a/msm8996/sdm/include/private/resource_interface.h b/msm8996/sdm/include/private/resource_interface.h
index 21652f5..6115112 100644
--- a/msm8996/sdm/include/private/resource_interface.h
+++ b/msm8996/sdm/include/private/resource_interface.h
@@ -32,11 +32,16 @@
 
 class ResourceInterface {
  public:
-  virtual DisplayError RegisterDisplay(DisplayType type, const HWDisplayAttributes &attributes,
-                                       const HWPanelInfo &hw_panel_info, Handle *display_ctx) = 0;
+  virtual DisplayError RegisterDisplay(DisplayType type,
+                                       const HWDisplayAttributes &display_attributes,
+                                       const HWPanelInfo &hw_panel_info,
+                                       const HWMixerAttributes &mixer_attributes,
+                                       Handle *display_ctx) = 0;
   virtual DisplayError UnregisterDisplay(Handle display_ctx) = 0;
-  virtual void ReconfigureDisplay(Handle display_ctx, const HWDisplayAttributes &attributes,
-                                  const HWPanelInfo &hw_panel_info) = 0;
+  virtual DisplayError ReconfigureDisplay(Handle display_ctx,
+                                          const HWDisplayAttributes &display_attributes,
+                                          const HWPanelInfo &hw_panel_info,
+                                          const HWMixerAttributes &mixer_attributes) = 0;
   virtual DisplayError Start(Handle display_ctx) = 0;
   virtual DisplayError Stop(Handle display_ctx) = 0;
   virtual DisplayError Acquire(Handle display_ctx, HWLayers *hw_layers) = 0;
@@ -53,6 +58,8 @@
                                               int x, int y) = 0;
   virtual DisplayError SetMaxBandwidthMode(HWBwModes mode) = 0;
   virtual DisplayError GetScaleLutConfig(HWScaleLutInfo *lut_info) = 0;
+  virtual DisplayError SetDetailEnhancerData(Handle display_ctx,
+                                             const DisplayDetailEnhancerData &de_data) = 0;
 
  protected:
   virtual ~ResourceInterface() { }
diff --git a/msm8996/sdm/include/private/strategy_interface.h b/msm8996/sdm/include/private/strategy_interface.h
index 17acfed..f2bfe23 100644
--- a/msm8996/sdm/include/private/strategy_interface.h
+++ b/msm8996/sdm/include/private/strategy_interface.h
@@ -48,7 +48,9 @@
   virtual DisplayError Start(HWLayersInfo *hw_layers_info, uint32_t *max_attempts) = 0;
   virtual DisplayError GetNextStrategy(StrategyConstraints *constraints) = 0;
   virtual DisplayError Stop() = 0;
-  virtual DisplayError Reconfigure(HWDisplayMode mode, HWS3DMode s3d_mode) = 0;
+  virtual DisplayError Reconfigure(HWDisplayMode mode, HWS3DMode s3d_mode,
+                                   const HWMixerAttributes &mixer_attributes,
+                                   const DisplayConfigVariableInfo &fb_config) = 0;
 
  protected:
   virtual ~StrategyInterface() { }
diff --git a/msm8996/sdm/include/utils/rect.h b/msm8996/sdm/include/utils/rect.h
index c198645..d084556 100644
--- a/msm8996/sdm/include/utils/rect.h
+++ b/msm8996/sdm/include/utils/rect.h
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2015, The Linux Foundation. All rights reserved.
+* Copyright (c) 2015-2016, 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
@@ -37,6 +37,12 @@
 
 namespace sdm {
 
+  enum RectOrientation {
+    kOrientationPortrait,
+    kOrientationLandscape,
+    kOrientationUnknown,
+  };
+
   bool IsValid(const LayerRect &rect);
   bool IsCongruent(const LayerRect &rect1, const LayerRect &rect2);
   void Log(DebugTag debug_tag, const char *prefix, const LayerRect &roi);
@@ -49,6 +55,9 @@
                       bool flip_horizontal, LayerRect *out_rects);
   void SplitTopBottom(const LayerRect &in_rect, uint32_t split_count, uint32_t align_y,
                       bool flip_horizontal, LayerRect *out_rects);
+  void ScaleRect(const LayerRect &src_domain, const LayerRect &dst_domain, const LayerRect &in_rect,
+                 LayerRect *out_rect);
+  RectOrientation GetOrientation(const LayerRect &in_rect);
 }  // namespace sdm
 
 #endif  // __RECT_H__
diff --git a/msm8996/sdm/libs/core/comp_manager.cpp b/msm8996/sdm/libs/core/comp_manager.cpp
index 562186c..6fa7e5f 100644
--- a/msm8996/sdm/libs/core/comp_manager.cpp
+++ b/msm8996/sdm/libs/core/comp_manager.cpp
@@ -69,8 +69,12 @@
   return kErrorNone;
 }
 
-DisplayError CompManager::RegisterDisplay(DisplayType type, const HWDisplayAttributes &attributes,
-                                          const HWPanelInfo &hw_panel_info, Handle *display_ctx) {
+DisplayError CompManager::RegisterDisplay(DisplayType type,
+                                          const HWDisplayAttributes &display_attributes,
+                                          const HWPanelInfo &hw_panel_info,
+                                          const HWMixerAttributes &mixer_attributes,
+                                          const DisplayConfigVariableInfo &fb_config,
+                                          Handle *display_ctx) {
   SCOPE_LOCK(locker_);
 
   DisplayError error = kErrorNone;
@@ -81,7 +85,8 @@
   }
 
   Strategy *&strategy = display_comp_ctx->strategy;
-  strategy = new Strategy(extension_intf_, type, hw_res_info_, hw_panel_info, attributes);
+  strategy = new Strategy(extension_intf_, type, hw_res_info_, hw_panel_info, mixer_attributes,
+                          display_attributes, fb_config);
   if (!strategy) {
     DLOGE("Unable to create strategy");
     delete display_comp_ctx;
@@ -95,7 +100,7 @@
     return error;
   }
 
-  error = resource_intf_->RegisterDisplay(type, attributes, hw_panel_info,
+  error = resource_intf_->RegisterDisplay(type, display_attributes, hw_panel_info, mixer_attributes,
                                           &display_comp_ctx->display_resource_ctx);
   if (error != kErrorNone) {
     strategy->Deinit();
@@ -154,17 +159,25 @@
 }
 
 DisplayError CompManager::ReconfigureDisplay(Handle comp_handle,
-                                             const HWDisplayAttributes &attributes,
-                                             const HWPanelInfo &hw_panel_info) {
+                                             const HWDisplayAttributes &display_attributes,
+                                             const HWPanelInfo &hw_panel_info,
+                                             const HWMixerAttributes &mixer_attributes,
+                                             const DisplayConfigVariableInfo &fb_config) {
+  SCOPE_LOCK(locker_);
+
+  DisplayError error = kErrorNone;
   DisplayCompositionContext *display_comp_ctx =
                              reinterpret_cast<DisplayCompositionContext *>(comp_handle);
 
-  resource_intf_->ReconfigureDisplay(display_comp_ctx->display_resource_ctx, attributes,
-                                     hw_panel_info);
+  error = resource_intf_->ReconfigureDisplay(display_comp_ctx->display_resource_ctx,
+                                             display_attributes, hw_panel_info, mixer_attributes);
+  if (error != kErrorNone) {
+    return error;
+  }
 
-  DisplayError error = kErrorNone;
   if (display_comp_ctx->strategy) {
-    error = display_comp_ctx->strategy->Reconfigure(hw_panel_info, attributes);
+    error = display_comp_ctx->strategy->Reconfigure(hw_panel_info, display_attributes,
+                                                    mixer_attributes, fb_config);
     if (error != kErrorNone) {
       DLOGE("Unable to Reconfigure strategy.");
       display_comp_ctx->strategy->Deinit();
@@ -468,5 +481,15 @@
   return resource_intf_->GetScaleLutConfig(lut_info);
 }
 
+DisplayError CompManager::SetDetailEnhancerData(Handle display_ctx,
+                                                const DisplayDetailEnhancerData &de_data) {
+  SCOPE_LOCK(locker_);
+
+  DisplayCompositionContext *display_comp_ctx =
+                             reinterpret_cast<DisplayCompositionContext *>(display_ctx);
+
+  return resource_intf_->SetDetailEnhancerData(display_comp_ctx->display_resource_ctx, de_data);
+}
+
 }  // namespace sdm
 
diff --git a/msm8996/sdm/libs/core/comp_manager.h b/msm8996/sdm/libs/core/comp_manager.h
index d6d45c1..a77eed0 100644
--- a/msm8996/sdm/libs/core/comp_manager.h
+++ b/msm8996/sdm/libs/core/comp_manager.h
@@ -41,11 +41,15 @@
   DisplayError Init(const HWResourceInfo &hw_res_info_, ExtensionInterface *extension_intf,
                   BufferSyncHandler *buffer_sync_handler);
   DisplayError Deinit();
-  DisplayError RegisterDisplay(DisplayType type, const HWDisplayAttributes &attributes,
-                               const HWPanelInfo &hw_panel_info, Handle *res_mgr_hnd);
+  DisplayError RegisterDisplay(DisplayType type, const HWDisplayAttributes &display_attributes,
+                               const HWPanelInfo &hw_panel_info,
+                               const HWMixerAttributes &mixer_attributes,
+                               const DisplayConfigVariableInfo &fb_config, Handle *res_mgr_hnd);
   DisplayError UnregisterDisplay(Handle res_mgr_hnd);
-  DisplayError ReconfigureDisplay(Handle display_ctx, const HWDisplayAttributes &attributes,
-                                  const HWPanelInfo &hw_panel_info);
+  DisplayError ReconfigureDisplay(Handle display_ctx, const HWDisplayAttributes &display_attributes,
+                                  const HWPanelInfo &hw_panel_info,
+                                  const HWMixerAttributes &mixer_attributes,
+                                  const DisplayConfigVariableInfo &fb_config);
   void PrePrepare(Handle display_ctx, HWLayers *hw_layers);
   DisplayError Prepare(Handle display_ctx, HWLayers *hw_layers);
   DisplayError PostPrepare(Handle display_ctx, HWLayers *hw_layers);
@@ -62,6 +66,7 @@
   bool CanSetIdleTimeout(Handle display_ctx);
   DisplayError SetMaxBandwidthMode(HWBwModes mode);
   DisplayError GetScaleLutConfig(HWScaleLutInfo *lut_info);
+  DisplayError SetDetailEnhancerData(Handle display_ctx, const DisplayDetailEnhancerData &de_data);
 
   // DumpImpl method
   virtual void AppendDump(char *buffer, uint32_t length);
diff --git a/msm8996/sdm/libs/core/display_base.cpp b/msm8996/sdm/libs/core/display_base.cpp
index 8cbdeb2..d9583b7 100644
--- a/msm8996/sdm/libs/core/display_base.cpp
+++ b/msm8996/sdm/libs/core/display_base.cpp
@@ -56,6 +56,18 @@
   uint32_t active_index = 0;
   hw_intf_->GetActiveConfig(&active_index);
   hw_intf_->GetDisplayAttributes(active_index, &display_attributes_);
+  fb_config_ = display_attributes_;
+
+  HWMixerAttributes mixer_attributes;
+  error = hw_intf_->GetMixerAttributes(&mixer_attributes);
+  if (error != kErrorNone) {
+    return error;
+  }
+  mixer_attributes_ = mixer_attributes;
+
+  // Override x_pixels and y_pixels of frame buffer with mixer width and height
+  fb_config_.x_pixels = mixer_attributes.width;
+  fb_config_.y_pixels = mixer_attributes.height;
 
   HWScaleLutInfo lut_info = {};
   error = comp_manager_->GetScaleLutConfig(&lut_info);
@@ -67,8 +79,8 @@
     goto CleanupOnError;
   }
 
-  error = comp_manager_->RegisterDisplay(display_type_, display_attributes_,
-                                         hw_panel_info_, &display_comp_ctx_);
+  error = comp_manager_->RegisterDisplay(display_type_, display_attributes_, hw_panel_info_,
+                                         mixer_attributes, fb_config_, &display_comp_ctx_);
   if (error != kErrorNone) {
     goto CleanupOnError;
   }
@@ -161,17 +173,24 @@
     return kErrorParameters;
   }
 
-  auto gpu_target_layer_dst_xpixels = gpu_target_layer->dst_rect.right;
-  auto gpu_target_layer_dst_ypixels = gpu_target_layer->dst_rect.bottom;
+  float layer_mixer_width = FLOAT(mixer_attributes_.width);
+  float layer_mixer_height = FLOAT(mixer_attributes_.height);
+  float fb_width = FLOAT(fb_config_.x_pixels);
+  float fb_height = FLOAT(fb_config_.y_pixels);
+  LayerRect src_domain = (LayerRect){0.0f, 0.0f, fb_width, fb_height};
+  LayerRect dst_domain = (LayerRect){0.0f, 0.0f, layer_mixer_width, layer_mixer_height};
+  LayerRect out_rect = gpu_target_layer->dst_rect;
 
-  HWDisplayAttributes display_attrib;
-  uint32_t active_index = 0;
-  hw_intf_->GetActiveConfig(&active_index);
-  hw_intf_->GetDisplayAttributes(active_index, &display_attrib);
+  ScaleRect(src_domain, dst_domain, gpu_target_layer->dst_rect, &out_rect);
 
-  if (gpu_target_layer_dst_xpixels > display_attrib.x_pixels ||
-    gpu_target_layer_dst_ypixels > display_attrib.y_pixels) {
-    DLOGE("GPU target layer dst rect is not with in limits");
+  auto gpu_target_layer_dst_xpixels = out_rect.right - out_rect.left;
+  auto gpu_target_layer_dst_ypixels = out_rect.bottom - out_rect.top;
+
+  if (gpu_target_layer_dst_xpixels > mixer_attributes_.width ||
+    gpu_target_layer_dst_ypixels > mixer_attributes_.height) {
+    DLOGE("GPU target layer dst rect is not with in limits gpu wxh %fx%f mixer wxh %dx%d",
+    gpu_target_layer_dst_xpixels, gpu_target_layer_dst_ypixels, mixer_attributes_.width,
+    mixer_attributes_.height);
     return kErrorParameters;
   }
 
@@ -179,35 +198,34 @@
 }
 
 DisplayError DisplayBase::Prepare(LayerStack *layer_stack) {
-  DisplayError error = kErrorNone;
-  bool disable_partial_update = false;
-  uint32_t pending = 0;
+  SCOPE_LOCK(locker_);
+
+  if (!active_) {
+    return kErrorPermission;
+  }
 
   if (!layer_stack) {
     return kErrorParameters;
   }
 
-  pending_commit_ = false;
+  return PrepareLocked(layer_stack);
+}
+
+DisplayError DisplayBase::PrepareLocked(LayerStack *layer_stack) {
+  DisplayError error = kErrorNone;
 
   error = ValidateGPUTarget(layer_stack);
   if (error != kErrorNone) {
     return error;
   }
 
-  if (!active_) {
-    return kErrorPermission;
+  if (color_mgr_ && color_mgr_->NeedsPartialUpdateDisable()) {
+    DisablePartialUpdateOneFrameLocked();
   }
 
-  // Request to disable partial update only if it is currently enabled.
-  if (color_mgr_ && partial_update_control_) {
-    disable_partial_update = color_mgr_->NeedsPartialUpdateDisable();
-    if (disable_partial_update) {
-      ControlPartialUpdate(false, &pending);
-    }
-  }
-
-  if (one_frame_full_roi_) {
-    ControlPartialUpdate(false, &pending);
+  if (partial_update_control_ == false || disable_pu_one_frame_) {
+    comp_manager_->ControlPartialUpdate(display_comp_ctx_, false /* enable */);
+    disable_pu_one_frame_ = false;
   }
 
   // Clean hw layers for reuse.
@@ -249,29 +267,22 @@
   }
 
   comp_manager_->PostPrepare(display_comp_ctx_, &hw_layers_);
-  if (disable_partial_update) {
-    ControlPartialUpdate(true, &pending);
-  }
-
-  if (one_frame_full_roi_) {
-    ControlPartialUpdate(true, &pending);
-    one_frame_full_roi_ = false;
-  }
 
   return error;
 }
 
 DisplayError DisplayBase::Commit(LayerStack *layer_stack) {
-  DisplayError error = kErrorNone;
+  SCOPE_LOCK(locker_);
+
+  if (!active_) {
+    pending_commit_ = false;
+    return kErrorPermission;
+  }
 
   if (!layer_stack) {
     return kErrorParameters;
   }
 
-  if (!active_) {
-    return kErrorPermission;
-  }
-
   if (!pending_commit_) {
     DLOGE("Commit: Corresponding Prepare() is not called for display = %d", display_type_);
     return kErrorUndefined;
@@ -279,6 +290,12 @@
 
   pending_commit_ = false;
 
+  return CommitLocked(layer_stack);
+}
+
+DisplayError DisplayBase::CommitLocked(LayerStack *layer_stack) {
+  DisplayError error = kErrorNone;
+
   // Layer stack attributes has changed, need to Reconfigure, currently in use for Hybrid Comp
   if (layer_stack->flags.attributes_changed) {
     error = comp_manager_->ReConfigure(display_comp_ctx_, &hw_layers_);
@@ -319,6 +336,10 @@
     }
   }
 
+  if (partial_update_control_) {
+    comp_manager_->ControlPartialUpdate(display_comp_ctx_, true /* enable */);
+  }
+
   error = comp_manager_->PostCommit(display_comp_ctx_, &hw_layers_);
   if (error != kErrorNone) {
     return error;
@@ -460,6 +481,11 @@
 }
 
 DisplayError DisplayBase::SetActiveConfig(uint32_t index) {
+  SCOPE_LOCK(locker_);
+  return SetActiveConfigLocked(index);
+}
+
+DisplayError DisplayBase::SetActiveConfigLocked(uint32_t index) {
   DisplayError error = kErrorNone;
   uint32_t active_index = 0;
 
@@ -474,26 +500,12 @@
     return error;
   }
 
-  HWDisplayAttributes attrib;
-  error = hw_intf_->GetDisplayAttributes(index, &attrib);
-  if (error != kErrorNone) {
-    return error;
-  }
+  return ReconfigureDisplay();
+}
 
-  hw_intf_->GetHWPanelInfo(&hw_panel_info_);
-
-  if (display_comp_ctx_) {
-    comp_manager_->UnregisterDisplay(display_comp_ctx_);
-  }
-
-  error = comp_manager_->RegisterDisplay(display_type_, attrib, hw_panel_info_,
-                                         &display_comp_ctx_);
-
-  if (error == kErrorNone && partial_update_control_) {
-    one_frame_full_roi_ = true;
-  }
-
-  return error;
+DisplayError DisplayBase::SetActiveConfig(DisplayConfigVariableInfo *variable_info) {
+  SCOPE_LOCK(locker_);
+  return SetActiveConfigLocked(variable_info);
 }
 
 DisplayError DisplayBase::SetMaxMixerStages(uint32_t max_mixer_stages) {
@@ -509,43 +521,19 @@
 }
 
 DisplayError DisplayBase::ControlPartialUpdate(bool enable, uint32_t *pending) {
-  if (!pending) {
-    return kErrorParameters;
-  }
+  SCOPE_LOCK(locker_);
+  return ControlPartialUpdateLocked(enable, pending);
+}
 
-  if (!hw_panel_info_.partial_update) {
-    // Nothing to be done.
-    DLOGI("partial update is not applicable for display=%d", display_type_);
-    return kErrorNotSupported;
-  }
-
-  *pending = 0;
-  if (enable == partial_update_control_) {
-    DLOGI("Same state transition is requested.");
-    return kErrorNone;
-  }
-
-  partial_update_control_ = enable;
-  comp_manager_->ControlPartialUpdate(display_comp_ctx_, enable);
-
-  if (!enable) {
-    // If the request is to turn off feature, new draw call is required to have
-    // the new setting into effect.
-    *pending = 1;
-  }
-
-  return kErrorNone;
+DisplayError DisplayBase::DisablePartialUpdateOneFrame() {
+  SCOPE_LOCK(locker_);
+  return DisablePartialUpdateOneFrameLocked();
 }
 
 DisplayError DisplayBase::SetDisplayMode(uint32_t mode) {
   return kErrorNotSupported;
 }
 
-DisplayError DisplayBase::IsScalingValid(const LayerRect &crop, const LayerRect &dst,
-                                         bool rotate90) {
-  return comp_manager_->ValidateScaling(crop, dst, rotate90);
-}
-
 DisplayError DisplayBase::SetPanelBrightness(int level) {
   return kErrorNotSupported;
 }
@@ -878,4 +866,135 @@
   return error;
 }
 
+DisplayError DisplayBase::ReconfigureDisplay() {
+  DisplayError error = kErrorNone;
+  HWDisplayAttributes display_attributes;
+  HWMixerAttributes mixer_attributes;
+  HWPanelInfo hw_panel_info;
+  uint32_t active_index = 0;
+
+  error = hw_intf_->GetActiveConfig(&active_index);
+  if (error != kErrorNone) {
+    return error;
+  }
+
+  error = hw_intf_->GetDisplayAttributes(active_index, &display_attributes);
+  if (error != kErrorNone) {
+    return error;
+  }
+
+  error = hw_intf_->GetMixerAttributes(&mixer_attributes);
+  if (error != kErrorNone) {
+    return error;
+  }
+
+  error = hw_intf_->GetHWPanelInfo(&hw_panel_info);
+  if (error != kErrorNone) {
+    return error;
+  }
+
+  if (display_attributes == display_attributes_ && mixer_attributes == mixer_attributes_ &&
+      hw_panel_info == hw_panel_info_) {
+    return kErrorNone;
+  }
+
+  error = comp_manager_->ReconfigureDisplay(display_comp_ctx_, display_attributes, hw_panel_info,
+                                            mixer_attributes, fb_config_);
+  if (error != kErrorNone) {
+    return error;
+  }
+
+  if (mixer_attributes != mixer_attributes_) {
+    DisablePartialUpdateOneFrameLocked();
+  }
+
+  display_attributes_ = display_attributes;
+  mixer_attributes_ = mixer_attributes;
+  hw_panel_info_ = hw_panel_info;
+
+  return kErrorNone;
+}
+
+DisplayError DisplayBase::SetMixerResolution(uint32_t width, uint32_t height) {
+  SCOPE_LOCK(locker_);
+  return SetMixerResolutionLocked(width, height);
+}
+
+DisplayError DisplayBase::GetMixerResolution(uint32_t *width, uint32_t *height) {
+  SCOPE_LOCK(locker_);
+  return GetMixerResolutionLocked(width, height);
+}
+
+DisplayError DisplayBase::GetMixerResolutionLocked(uint32_t *width, uint32_t *height) {
+  if (!width || !height) {
+    return kErrorParameters;
+  }
+
+  *width = mixer_attributes_.width;
+  *height = mixer_attributes_.height;
+
+  return kErrorNone;
+}
+
+DisplayError DisplayBase::SetFrameBufferConfig(const DisplayConfigVariableInfo &variable_info) {
+  SCOPE_LOCK(locker_);
+  return SetFrameBufferConfigLocked(variable_info);
+}
+
+DisplayError DisplayBase::SetFrameBufferConfigLocked(
+                                   const DisplayConfigVariableInfo &variable_info) {
+  uint32_t width = variable_info.x_pixels;
+  uint32_t height = variable_info.y_pixels;
+
+  if (width == 0 || height == 0) {
+    DLOGE("Unsupported resolution: (%dx%d)", width, height);
+    return kErrorParameters;
+  }
+
+  // Create rects to represent the new source and destination crops
+  LayerRect crop = LayerRect(0, 0, FLOAT(width), FLOAT(height));
+  LayerRect dst = LayerRect(0, 0, FLOAT(mixer_attributes_.width), FLOAT(mixer_attributes_.height));
+  // Set rotate90 to false since this is taken care of during regular composition.
+  bool rotate90 = false;
+
+  DisplayError error = comp_manager_->ValidateScaling(crop, dst, rotate90);
+  if (error != kErrorNone) {
+    DLOGE("Unsupported resolution: (%dx%d)", width, height);
+    return kErrorParameters;
+  }
+
+  error =  comp_manager_->ReconfigureDisplay(display_comp_ctx_, display_attributes_, hw_panel_info_,
+                                             mixer_attributes_, variable_info);
+  if (error != kErrorNone) {
+    return error;
+  }
+
+  fb_config_.x_pixels = width;
+  fb_config_.y_pixels = height;
+
+  DLOGI("New framebuffer resolution (%dx%d)", fb_config_.x_pixels, fb_config_.y_pixels);
+
+  return kErrorNone;
+}
+
+DisplayError DisplayBase::GetFrameBufferConfig(DisplayConfigVariableInfo *variable_info) {
+  SCOPE_LOCK(locker_);
+  return GetFrameBufferConfigLocked(variable_info);
+}
+
+DisplayError DisplayBase::GetFrameBufferConfigLocked(DisplayConfigVariableInfo *variable_info) {
+  if (!variable_info) {
+    return kErrorParameters;
+  }
+
+  *variable_info = fb_config_;
+
+  return kErrorNone;
+}
+
+DisplayError DisplayBase::SetDetailEnhancerData(const DisplayDetailEnhancerData &de_data) {
+  SCOPE_LOCK(locker_);
+  return SetDetailEnhancerDataLocked(de_data);
+}
+
 }  // namespace sdm
diff --git a/msm8996/sdm/libs/core/display_base.h b/msm8996/sdm/libs/core/display_base.h
index 3d58ed6..1672351 100644
--- a/msm8996/sdm/libs/core/display_base.h
+++ b/msm8996/sdm/libs/core/display_base.h
@@ -54,8 +54,8 @@
   virtual ~DisplayBase() { }
   virtual DisplayError Init();
   virtual DisplayError Deinit();
-  virtual DisplayError Prepare(LayerStack *layer_stack);
-  virtual DisplayError Commit(LayerStack *layer_stack);
+  DisplayError Prepare(LayerStack *layer_stack) final;
+  DisplayError Commit(LayerStack *layer_stack) final;
   virtual DisplayError Flush();
   virtual DisplayError GetDisplayState(DisplayState *state);
   virtual DisplayError GetNumVariableInfoConfigs(uint32_t *count);
@@ -63,11 +63,12 @@
   virtual DisplayError GetActiveConfig(uint32_t *index);
   virtual DisplayError GetVSyncState(bool *enabled);
   virtual DisplayError SetDisplayState(DisplayState state);
-  virtual DisplayError SetActiveConfig(uint32_t index);
+  DisplayError SetActiveConfig(uint32_t index) final;
+  DisplayError SetActiveConfig(DisplayConfigVariableInfo *variable_info) final;
   virtual DisplayError SetMaxMixerStages(uint32_t max_mixer_stages);
-  virtual DisplayError ControlPartialUpdate(bool enable, uint32_t *pending);
+  DisplayError ControlPartialUpdate(bool enable, uint32_t *pending) final;
+  DisplayError DisablePartialUpdateOneFrame() final;
   virtual DisplayError SetDisplayMode(uint32_t mode);
-  virtual DisplayError IsScalingValid(const LayerRect &crop, const LayerRect &dst, bool rotate90);
   virtual bool IsUnderscanSupported();
   virtual DisplayError SetPanelBrightness(int level);
   virtual DisplayError OnMinHdcpEncryptionLevelChange(uint32_t min_enc_level);
@@ -83,21 +84,49 @@
   virtual DisplayError GetRefreshRateRange(uint32_t *min_refresh_rate, uint32_t *max_refresh_rate);
   virtual DisplayError GetPanelBrightness(int *level);
   virtual DisplayError SetVSyncState(bool enable);
+  DisplayError SetMixerResolution(uint32_t width, uint32_t height) final;
+  DisplayError GetMixerResolution(uint32_t *width, uint32_t *height) final;
+  DisplayError SetFrameBufferConfig(const DisplayConfigVariableInfo &variable_info) final;
+  DisplayError GetFrameBufferConfig(DisplayConfigVariableInfo *variable_info) final;
+  DisplayError SetDetailEnhancerData(const DisplayDetailEnhancerData &de_data) final;
 
  protected:
+  virtual DisplayError PrepareLocked(LayerStack *layer_stack);
+  virtual DisplayError CommitLocked(LayerStack *layer_stack);
+  virtual DisplayError SetActiveConfigLocked(uint32_t index);
+  virtual DisplayError SetActiveConfigLocked(DisplayConfigVariableInfo *variable_info) {
+    return kErrorNotSupported;
+  }
+  virtual DisplayError ControlPartialUpdateLocked(bool enable, uint32_t *pending) {
+    return kErrorNotSupported;
+  }
+  virtual DisplayError DisablePartialUpdateOneFrameLocked() {
+    return kErrorNotSupported;
+  }
+  virtual DisplayError SetMixerResolutionLocked(uint32_t width, uint32_t height) {
+    return kErrorNotSupported;
+  }
+  virtual DisplayError GetMixerResolutionLocked(uint32_t *width, uint32_t *height);
+  virtual DisplayError SetFrameBufferConfigLocked(const DisplayConfigVariableInfo &variable_info);
+  virtual DisplayError GetFrameBufferConfigLocked(DisplayConfigVariableInfo *variable_info);
+  virtual DisplayError SetDetailEnhancerDataLocked(const DisplayDetailEnhancerData &de_data) {
+    return kErrorNotSupported;
+  }
+
   // DumpImpl method
   void AppendDump(char *buffer, uint32_t length);
 
   bool IsRotationRequired(HWLayers *hw_layers);
   const char *GetName(const LayerComposition &composition);
   DisplayError ValidateGPUTarget(LayerStack *layer_stack);
+  DisplayError ReconfigureDisplay();
 
+  Locker locker_;
   DisplayType display_type_;
   DisplayEventHandler *event_handler_ = NULL;
   HWDeviceType hw_device_type_;
   HWInterface *hw_intf_ = NULL;
   HWPanelInfo hw_panel_info_;
-  HWDisplayAttributes display_attributes_;
   BufferSyncHandler *buffer_sync_handler_ = NULL;
   CompManager *comp_manager_ = NULL;
   RotatorInterface *rotator_intf_ = NULL;
@@ -115,14 +144,17 @@
   ColorManagerProxy *color_mgr_ = NULL;  // each display object owns its ColorManagerProxy
   bool partial_update_control_ = true;
   HWEventsInterface *hw_events_intf_ = NULL;
+  bool disable_pu_one_frame_ = false;
   uint32_t num_color_modes_ = 0;
   SDEDisplayMode *color_modes_ = NULL;
   int32_t color_mode_ = 0;
   typedef std::map<std::string, SDEDisplayMode *> ColorModeMap;
   ColorModeMap color_mode_map_ = {};
+  HWDisplayAttributes display_attributes_ = {};
+  HWMixerAttributes mixer_attributes_ = {};
+  DisplayConfigVariableInfo fb_config_ = {};
 
  private:
-  bool one_frame_full_roi_ = false;
   // Unused
   virtual DisplayError GetConfig(DisplayConfigFixedInfo *variable_info) {
     return kErrorNone;
diff --git a/msm8996/sdm/libs/core/display_hdmi.cpp b/msm8996/sdm/libs/core/display_hdmi.cpp
index 9a9628a..11c268a 100644
--- a/msm8996/sdm/libs/core/display_hdmi.cpp
+++ b/msm8996/sdm/libs/core/display_hdmi.cpp
@@ -106,17 +106,10 @@
   return error;
 }
 
-DisplayError DisplayHDMI::Prepare(LayerStack *layer_stack) {
-  SCOPE_LOCK(locker_);
-
+DisplayError DisplayHDMI::PrepareLocked(LayerStack *layer_stack) {
   SetS3DMode(layer_stack);
 
-  return DisplayBase::Prepare(layer_stack);
-}
-
-DisplayError DisplayHDMI::Commit(LayerStack *layer_stack) {
-  SCOPE_LOCK(locker_);
-  return DisplayBase::Commit(layer_stack);
+  return DisplayBase::PrepareLocked(layer_stack);
 }
 
 DisplayError DisplayHDMI::Flush() {
@@ -154,16 +147,6 @@
   return DisplayBase::SetDisplayState(state);
 }
 
-DisplayError DisplayHDMI::SetActiveConfig(DisplayConfigVariableInfo *variable_info) {
-  SCOPE_LOCK(locker_);
-  return kErrorNotSupported;
-}
-
-DisplayError DisplayHDMI::SetActiveConfig(uint32_t index) {
-  SCOPE_LOCK(locker_);
-  return DisplayBase::SetActiveConfig(index);
-}
-
 DisplayError DisplayHDMI::SetVSyncState(bool enable) {
   SCOPE_LOCK(locker_);
   return DisplayBase::SetVSyncState(enable);
@@ -181,12 +164,6 @@
   return DisplayBase::SetDisplayMode(mode);
 }
 
-DisplayError DisplayHDMI::IsScalingValid(const LayerRect &crop, const LayerRect &dst,
-                                         bool rotate90) {
-  SCOPE_LOCK(locker_);
-  return DisplayBase::IsScalingValid(crop, dst, rotate90);
-}
-
 DisplayError DisplayHDMI::GetRefreshRateRange(uint32_t *min_refresh_rate,
                                               uint32_t *max_refresh_rate) {
   SCOPE_LOCK(locker_);
@@ -336,9 +313,6 @@
 void DisplayHDMI::SetS3DMode(LayerStack *layer_stack) {
   uint32_t s3d_layer_count = 0;
   HWS3DMode s3d_mode = kS3DModeNone;
-  HWPanelInfo panel_info;
-  HWDisplayAttributes display_attributes;
-  uint32_t active_index = 0;
   uint32_t layer_count = UINT32(layer_stack->layers.size());
 
   // S3D mode is supported for the following scenarios:
@@ -373,15 +347,7 @@
     layer_stack->flags.s3d_mode_present = true;
   }
 
-  hw_intf_->GetHWPanelInfo(&panel_info);
-  hw_intf_->GetActiveConfig(&active_index);
-  hw_intf_->GetDisplayAttributes(active_index, &display_attributes);
-
-  if (panel_info != hw_panel_info_ || display_attributes != display_attributes_) {
-    comp_manager_->ReconfigureDisplay(display_comp_ctx_, display_attributes, panel_info);
-    hw_panel_info_ = panel_info;
-    display_attributes_ = display_attributes;
-  }
+  DisplayBase::ReconfigureDisplay();
 }
 
 void DisplayHDMI::CECMessage(char *message) {
diff --git a/msm8996/sdm/libs/core/display_hdmi.h b/msm8996/sdm/libs/core/display_hdmi.h
index 88e553d..b3ec9af 100644
--- a/msm8996/sdm/libs/core/display_hdmi.h
+++ b/msm8996/sdm/libs/core/display_hdmi.h
@@ -42,8 +42,6 @@
               RotatorInterface *rotator_intf);
   virtual DisplayError Init();
   virtual DisplayError Deinit();
-  virtual DisplayError Prepare(LayerStack *layer_stack);
-  virtual DisplayError Commit(LayerStack *layer_stack);
   virtual DisplayError Flush();
   virtual DisplayError GetDisplayState(DisplayState *state);
   virtual DisplayError GetNumVariableInfoConfigs(uint32_t *count);
@@ -51,13 +49,10 @@
   virtual DisplayError GetActiveConfig(uint32_t *index);
   virtual DisplayError GetVSyncState(bool *enabled);
   virtual DisplayError SetDisplayState(DisplayState state);
-  virtual DisplayError SetActiveConfig(DisplayConfigVariableInfo *variable_info);
-  virtual DisplayError SetActiveConfig(uint32_t index);
   virtual DisplayError SetVSyncState(bool enable);
   virtual void SetIdleTimeoutMs(uint32_t timeout_ms);
   virtual DisplayError SetMaxMixerStages(uint32_t max_mixer_stages);
   virtual DisplayError SetDisplayMode(uint32_t mode);
-  virtual DisplayError IsScalingValid(const LayerRect &crop, const LayerRect &dst, bool rotate90);
   virtual DisplayError GetRefreshRateRange(uint32_t *min_refresh_rate, uint32_t *max_refresh_rate);
   virtual DisplayError SetRefreshRate(uint32_t refresh_rate);
   virtual bool IsUnderscanSupported();
@@ -74,11 +69,11 @@
   virtual void CECMessage(char *message);
 
  private:
+  virtual DisplayError PrepareLocked(LayerStack *layer_stack);
   virtual uint32_t GetBestConfig(HWS3DMode s3d_mode);
   virtual void GetScanSupport();
   virtual void SetS3DMode(LayerStack *layer_stack);
 
-  Locker locker_;
   HWScanSupport scan_support_;
   std::map<LayerBufferS3DFormat, HWS3DMode> s3d_format_to_mode_;
   std::vector<const char *> event_list_ = {"vsync_event", "idle_notify", "cec/rd_msg",
diff --git a/msm8996/sdm/libs/core/display_primary.cpp b/msm8996/sdm/libs/core/display_primary.cpp
index e5751df..70b96fe 100644
--- a/msm8996/sdm/libs/core/display_primary.cpp
+++ b/msm8996/sdm/libs/core/display_primary.cpp
@@ -24,6 +24,11 @@
 
 #include <utils/constants.h>
 #include <utils/debug.h>
+#include <utils/rect.h>
+#include <map>
+#include <algorithm>
+#include <functional>
+#include <vector>
 
 #include "display_primary.h"
 #include "hw_interface.h"
@@ -86,17 +91,25 @@
   return error;
 }
 
-DisplayError DisplayPrimary::Prepare(LayerStack *layer_stack) {
-  SCOPE_LOCK(locker_);
-  return DisplayBase::Prepare(layer_stack);
+DisplayError DisplayPrimary::PrepareLocked(LayerStack *layer_stack) {
+  DisplayError error = kErrorNone;
+  uint32_t new_mixer_width = 0;
+  uint32_t new_mixer_height = 0;
+  uint32_t display_width = display_attributes_.x_pixels;
+  uint32_t display_height = display_attributes_.y_pixels;
+
+  if (NeedsMixerReconfiguration(layer_stack, &new_mixer_width, &new_mixer_height)) {
+    error = ReconfigureMixer(new_mixer_width, new_mixer_height);
+    if (error != kErrorNone) {
+      ReconfigureMixer(display_width, display_height);
+    }
+  }
+
+  return DisplayBase::PrepareLocked(layer_stack);
 }
 
-DisplayError DisplayPrimary::Commit(LayerStack *layer_stack) {
-  SCOPE_LOCK(locker_);
+DisplayError DisplayPrimary::CommitLocked(LayerStack *layer_stack) {
   DisplayError error = kErrorNone;
-  HWPanelInfo panel_info;
-  HWDisplayAttributes display_attributes;
-  uint32_t active_index = 0;
 
   // Enabling auto refresh is async and needs to happen before commit ioctl
   if (hw_panel_info_.mode == kModeCommand) {
@@ -105,19 +118,12 @@
 
   bool set_idle_timeout = comp_manager_->CanSetIdleTimeout(display_comp_ctx_);
 
-  error = DisplayBase::Commit(layer_stack);
+  error = DisplayBase::CommitLocked(layer_stack);
   if (error != kErrorNone) {
     return error;
   }
 
-  hw_intf_->GetHWPanelInfo(&panel_info);
-  hw_intf_->GetActiveConfig(&active_index);
-  hw_intf_->GetDisplayAttributes(active_index, &display_attributes);
-
-  if (panel_info != hw_panel_info_) {
-    error = comp_manager_->ReconfigureDisplay(display_comp_ctx_, display_attributes, panel_info);
-    hw_panel_info_ = panel_info;
-  }
+  DisplayBase::ReconfigureDisplay();
 
   if (hw_panel_info_.mode == kModeVideo) {
     if (set_idle_timeout && !layer_stack->flags.single_buffered_layer_present) {
@@ -181,16 +187,6 @@
   return kErrorNone;
 }
 
-DisplayError DisplayPrimary::SetActiveConfig(DisplayConfigVariableInfo *variable_info) {
-  SCOPE_LOCK(locker_);
-  return kErrorNotSupported;
-}
-
-DisplayError DisplayPrimary::SetActiveConfig(uint32_t index) {
-  SCOPE_LOCK(locker_);
-  return DisplayBase::SetActiveConfig(index);
-}
-
 DisplayError DisplayPrimary::SetVSyncState(bool enable) {
   SCOPE_LOCK(locker_);
   return DisplayBase::SetVSyncState(enable);
@@ -214,22 +210,16 @@
 DisplayError DisplayPrimary::SetDisplayMode(uint32_t mode) {
   SCOPE_LOCK(locker_);
   DisplayError error = kErrorNone;
-  HWDisplayMode hw_display_mode = kModeDefault;
+  HWDisplayMode hw_display_mode = static_cast<HWDisplayMode>(mode);
+  uint32_t pending = 0;
 
   if (!active_) {
     DLOGW("Invalid display state = %d. Panel must be on.", state_);
     return kErrorNotSupported;
   }
 
-  switch (mode) {
-  case kModeVideo:
-    hw_display_mode = kModeVideo;
-    break;
-  case kModeCommand:
-    hw_display_mode = kModeCommand;
-    break;
-  default:
-    DLOGW("Invalid panel mode parameters. Requested = %d", mode);
+  if (hw_display_mode != kModeCommand && hw_display_mode != kModeVideo) {
+    DLOGW("Invalid panel mode parameters. Requested = %d", hw_display_mode);
     return kErrorParameters;
   }
 
@@ -246,16 +236,11 @@
     return error;
   }
 
-  // Disable PU if the previous PU state is on when switching to video mode, and re-enable PU when
-  // switching back to command mode.
-  bool toggle_partial_update = !(hw_display_mode == kModeVideo);
-  if (partial_update_control_) {
-    comp_manager_->ControlPartialUpdate(display_comp_ctx_, toggle_partial_update);
-  }
-
-  if (hw_display_mode == kModeVideo) {
+  if (mode == kModeVideo) {
+    ControlPartialUpdateLocked(false /* enable */, &pending);
     hw_intf_->SetIdleTimeoutMs(idle_timeout_ms_);
-  } else if (hw_display_mode == kModeCommand) {
+  } else if (mode == kModeCommand) {
+    ControlPartialUpdateLocked(true /* enable */, &pending);
     hw_intf_->SetIdleTimeoutMs(0);
   }
 
@@ -267,12 +252,6 @@
   return hw_intf_->SetPanelBrightness(level);
 }
 
-DisplayError DisplayPrimary::IsScalingValid(const LayerRect &crop, const LayerRect &dst,
-                                            bool rotate90) {
-  SCOPE_LOCK(locker_);
-  return DisplayBase::IsScalingValid(crop, dst, rotate90);
-}
-
 DisplayError DisplayPrimary::GetRefreshRateRange(uint32_t *min_refresh_rate,
                                                  uint32_t *max_refresh_rate) {
   SCOPE_LOCK(locker_);
@@ -305,21 +284,7 @@
     return error;
   }
 
-  HWDisplayAttributes display_attributes;
-  uint32_t active_index = 0;
-  error = hw_intf_->GetActiveConfig(&active_index);
-  if (error != kErrorNone) {
-    return error;
-  }
-
-  error = hw_intf_->GetDisplayAttributes(active_index, &display_attributes);
-  if (error != kErrorNone) {
-    return error;
-  }
-
-  comp_manager_->ReconfigureDisplay(display_comp_ctx_, display_attributes, hw_panel_info_);
-
-  return kErrorNone;
+  return DisplayBase::ReconfigureDisplay();
 }
 
 void DisplayPrimary::AppendDump(char *buffer, uint32_t length) {
@@ -362,5 +327,137 @@
   return hw_intf_->GetPanelBrightness(level);
 }
 
+DisplayError DisplayPrimary::ControlPartialUpdateLocked(bool enable, uint32_t *pending) {
+  if (!pending) {
+    return kErrorParameters;
+  }
+
+  if (!hw_panel_info_.partial_update) {
+    // Nothing to be done.
+    DLOGI("partial update is not applicable for display=%d", display_type_);
+    return kErrorNotSupported;
+  }
+
+  *pending = 0;
+  if (enable == partial_update_control_) {
+    DLOGI("Same state transition is requested.");
+    return kErrorNone;
+  }
+
+  partial_update_control_ = enable;
+
+  if (!enable) {
+    // If the request is to turn off feature, new draw call is required to have
+    // the new setting into effect.
+    *pending = 1;
+  }
+
+  return kErrorNone;
+}
+
+DisplayError DisplayPrimary::DisablePartialUpdateOneFrameLocked() {
+  disable_pu_one_frame_ = true;
+
+  return kErrorNone;
+}
+
+DisplayError DisplayPrimary::SetMixerResolutionLocked(uint32_t width, uint32_t height) {
+  return ReconfigureMixer(width, height);
+}
+
+DisplayError DisplayPrimary::ReconfigureMixer(uint32_t width, uint32_t height) {
+  DisplayError error = kErrorNone;
+
+  HWMixerAttributes mixer_attributes;
+  mixer_attributes.width = width;
+  mixer_attributes.height = height;
+
+  error = hw_intf_->SetMixerAttributes(mixer_attributes);
+  if (error != kErrorNone) {
+    return error;
+  }
+
+  return DisplayBase::ReconfigureDisplay();
+}
+
+bool DisplayPrimary::NeedsMixerReconfiguration(LayerStack *layer_stack, uint32_t *new_mixer_width,
+                                               uint32_t *new_mixer_height) {
+  uint32_t layer_count = UINT32(layer_stack->layers.size());
+
+  uint32_t fb_width  = fb_config_.x_pixels;
+  uint32_t fb_height  = fb_config_.y_pixels;
+  uint32_t fb_area = fb_width * fb_height;
+  LayerRect fb_rect = (LayerRect) {0.0f, 0.0f, FLOAT(fb_width), FLOAT(fb_height)};
+  uint32_t mixer_width = mixer_attributes_.width;
+  uint32_t mixer_height = mixer_attributes_.height;
+
+  RectOrientation fb_orientation = GetOrientation(fb_rect);
+  uint32_t max_layer_area = 0;
+  uint32_t max_area_layer_index = 0;
+  std::vector<Layer *> layers = layer_stack->layers;
+
+  for (uint32_t i = 0; i < layer_count; i++) {
+    Layer *layer = layers.at(i);
+    LayerBuffer *layer_buffer = layer->input_buffer;
+
+    if (!layer_buffer->flags.video) {
+      continue;
+    }
+
+    uint32_t layer_width = UINT32(layer->src_rect.right - layer->src_rect.left);
+    uint32_t layer_height = UINT32(layer->src_rect.bottom - layer->src_rect.top);
+    uint32_t layer_area = layer_width * layer_height;
+
+    if (layer_area > max_layer_area) {
+      max_layer_area = layer_area;
+      max_area_layer_index = i;
+    }
+  }
+
+  if (max_layer_area > fb_area) {
+    Layer *layer = layers.at(max_area_layer_index);
+
+    uint32_t layer_width = UINT32(layer->src_rect.right - layer->src_rect.left);
+    uint32_t layer_height = UINT32(layer->src_rect.bottom - layer->src_rect.top);
+    LayerRect layer_rect = (LayerRect){0.0f, 0.0f, FLOAT(layer_width), FLOAT(layer_height)};
+
+    RectOrientation layer_orientation = GetOrientation(layer_rect);
+    if (layer_orientation != kOrientationUnknown &&
+        fb_orientation != kOrientationUnknown) {
+      if (layer_orientation != fb_orientation) {
+        Swap(layer_width, layer_height);
+      }
+    }
+
+    // Align the width and height according to fb's aspect ratio
+    layer_width = UINT32((FLOAT(fb_width) / FLOAT(fb_height)) * layer_height);
+
+    *new_mixer_width = layer_width;
+    *new_mixer_height = layer_height;
+
+    return true;
+  } else {
+    if (fb_width != mixer_width || fb_height != mixer_height) {
+      *new_mixer_width = fb_width;
+      *new_mixer_height = fb_height;
+
+      return true;
+    }
+  }
+
+  return false;
+}
+
+DisplayError DisplayPrimary::SetDetailEnhancerDataLocked(const DisplayDetailEnhancerData &de_data) {
+  DisplayError error = comp_manager_->SetDetailEnhancerData(display_comp_ctx_, de_data);
+  if (error != kErrorNone) {
+    return error;
+  }
+
+  DisablePartialUpdateOneFrameLocked();
+
+  return kErrorNone;
+}
+
 }  // namespace sdm
 
diff --git a/msm8996/sdm/libs/core/display_primary.h b/msm8996/sdm/libs/core/display_primary.h
index d3a37cd..f029961 100644
--- a/msm8996/sdm/libs/core/display_primary.h
+++ b/msm8996/sdm/libs/core/display_primary.h
@@ -41,8 +41,6 @@
                  RotatorInterface *rotator_intf);
   virtual DisplayError Init();
   virtual DisplayError Deinit();
-  virtual DisplayError Prepare(LayerStack *layer_stack);
-  virtual DisplayError Commit(LayerStack *layer_stack);
   virtual DisplayError Flush();
   virtual DisplayError GetDisplayState(DisplayState *state);
   virtual DisplayError GetNumVariableInfoConfigs(uint32_t *count);
@@ -50,13 +48,10 @@
   virtual DisplayError GetActiveConfig(uint32_t *index);
   virtual DisplayError GetVSyncState(bool *enabled);
   virtual DisplayError SetDisplayState(DisplayState state);
-  virtual DisplayError SetActiveConfig(DisplayConfigVariableInfo *variable_info);
-  virtual DisplayError SetActiveConfig(uint32_t index);
   virtual DisplayError SetVSyncState(bool enable);
   virtual void SetIdleTimeoutMs(uint32_t timeout_ms);
   virtual DisplayError SetMaxMixerStages(uint32_t max_mixer_stages);
   virtual DisplayError SetDisplayMode(uint32_t mode);
-  virtual DisplayError IsScalingValid(const LayerRect &crop, const LayerRect &dst, bool rotate90);
   virtual DisplayError GetRefreshRateRange(uint32_t *min_refresh_rate, uint32_t *max_refresh_rate);
   virtual DisplayError SetRefreshRate(uint32_t refresh_rate);
   virtual bool IsUnderscanSupported();
@@ -73,7 +68,17 @@
   virtual void CECMessage(char *message) { }
 
  private:
-  Locker locker_;
+  virtual DisplayError PrepareLocked(LayerStack *layer_stack);
+  virtual DisplayError CommitLocked(LayerStack *layer_stack);
+  virtual DisplayError ControlPartialUpdateLocked(bool enable, uint32_t *pending);
+  virtual DisplayError DisablePartialUpdateOneFrameLocked();
+  virtual DisplayError SetMixerResolutionLocked(uint32_t width, uint32_t height);
+  virtual DisplayError SetDetailEnhancerDataLocked(const DisplayDetailEnhancerData &de_data);
+
+  bool NeedsMixerReconfiguration(LayerStack *layer_stack, uint32_t *new_mixer_width,
+                                 uint32_t *new_mixer_height);
+  DisplayError ReconfigureMixer(uint32_t width, uint32_t height);
+
   uint32_t idle_timeout_ms_ = 0;
   std::vector<const char *> event_list_ = {"vsync_event", "show_blank_event", "idle_notify",
                                            "msm_fb_thermal_level", "thread_exit"};
diff --git a/msm8996/sdm/libs/core/display_virtual.cpp b/msm8996/sdm/libs/core/display_virtual.cpp
index ff8da68..cafb986 100644
--- a/msm8996/sdm/libs/core/display_virtual.cpp
+++ b/msm8996/sdm/libs/core/display_virtual.cpp
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2014 - 2015, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014 - 2016, 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:
@@ -69,16 +69,6 @@
   return error;
 }
 
-DisplayError DisplayVirtual::Prepare(LayerStack *layer_stack) {
-  SCOPE_LOCK(locker_);
-  return DisplayBase::Prepare(layer_stack);
-}
-
-DisplayError DisplayVirtual::Commit(LayerStack *layer_stack) {
-  SCOPE_LOCK(locker_);
-  return DisplayBase::Commit(layer_stack);
-}
-
 DisplayError DisplayVirtual::Flush() {
   SCOPE_LOCK(locker_);
   return DisplayBase::Flush();
@@ -122,10 +112,7 @@
   return DisplayBase::SetDisplayState(state);
 }
 
-DisplayError DisplayVirtual::SetActiveConfig(DisplayConfigVariableInfo *variable_info) {
-  SCOPE_LOCK(locker_);
-  DisplayError error = kErrorNone;
-
+DisplayError DisplayVirtual::SetActiveConfigLocked(DisplayConfigVariableInfo *variable_info) {
   if (!variable_info) {
     return kErrorParameters;
   }
@@ -134,24 +121,17 @@
   display_attributes_.y_pixels = variable_info->y_pixels;
   display_attributes_.fps = variable_info->fps;
 
+  HWMixerAttributes mixer_attributes;
+  mixer_attributes.width = variable_info->x_pixels;;
+  mixer_attributes.height = variable_info->y_pixels;
   // if display is already connected, unregister display from composition manager and register
   // the display with new configuration.
   if (display_comp_ctx_) {
     comp_manager_->UnregisterDisplay(display_comp_ctx_);
   }
 
-  error = comp_manager_->RegisterDisplay(display_type_, display_attributes_, hw_panel_info_,
-                                         &display_comp_ctx_);
-  if (error != kErrorNone) {
-    return error;
-  }
-
-  return error;
-}
-
-DisplayError DisplayVirtual::SetActiveConfig(uint32_t index) {
-  SCOPE_LOCK(locker_);
-  return kErrorNotSupported;
+  return comp_manager_->RegisterDisplay(display_type_, display_attributes_, hw_panel_info_,
+                                        mixer_attributes, fb_config_, &display_comp_ctx_);
 }
 
 DisplayError DisplayVirtual::SetVSyncState(bool enable) {
@@ -171,12 +151,6 @@
   return DisplayBase::SetDisplayMode(mode);
 }
 
-DisplayError DisplayVirtual::IsScalingValid(const LayerRect &crop, const LayerRect &dst,
-                                            bool rotate90) {
-  SCOPE_LOCK(locker_);
-  return DisplayBase::IsScalingValid(crop, dst, rotate90);
-}
-
 DisplayError DisplayVirtual::GetRefreshRateRange(uint32_t *min_refresh_rate,
                                                  uint32_t *max_refresh_rate) {
   SCOPE_LOCK(locker_);
diff --git a/msm8996/sdm/libs/core/display_virtual.h b/msm8996/sdm/libs/core/display_virtual.h
index b26be12..ba164ae 100644
--- a/msm8996/sdm/libs/core/display_virtual.h
+++ b/msm8996/sdm/libs/core/display_virtual.h
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2014 - 2015, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014 - 2016, 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:
@@ -40,8 +40,6 @@
                  RotatorInterface *rotator_intf);
   virtual DisplayError Init();
   virtual DisplayError Deinit();
-  virtual DisplayError Prepare(LayerStack *layer_stack);
-  virtual DisplayError Commit(LayerStack *layer_stack);
   virtual DisplayError Flush();
   virtual DisplayError GetDisplayState(DisplayState *state);
   virtual DisplayError GetNumVariableInfoConfigs(uint32_t *count);
@@ -49,13 +47,10 @@
   virtual DisplayError GetActiveConfig(uint32_t *index);
   virtual DisplayError GetVSyncState(bool *enabled);
   virtual DisplayError SetDisplayState(DisplayState state);
-  virtual DisplayError SetActiveConfig(DisplayConfigVariableInfo *variable_info);
-  virtual DisplayError SetActiveConfig(uint32_t index);
   virtual DisplayError SetVSyncState(bool enable);
   virtual void SetIdleTimeoutMs(uint32_t timeout_ms);
   virtual DisplayError SetMaxMixerStages(uint32_t max_mixer_stages);
   virtual DisplayError SetDisplayMode(uint32_t mode);
-  virtual DisplayError IsScalingValid(const LayerRect &crop, const LayerRect &dst, bool rotate90);
   virtual DisplayError GetRefreshRateRange(uint32_t *min_refresh_rate, uint32_t *max_refresh_rate);
   virtual DisplayError SetRefreshRate(uint32_t refresh_rate);
   virtual bool IsUnderscanSupported();
@@ -64,8 +59,10 @@
   virtual DisplayError SetCursorPosition(int x, int y);
 
  private:
-  Locker locker_;
-  HWDisplayAttributes display_attributes_;
+  virtual DisplayError SetActiveConfigLocked(uint32_t index) {
+    return kErrorNotSupported;
+  }
+  virtual DisplayError SetActiveConfigLocked(DisplayConfigVariableInfo *variable_info);
 };
 
 }  // namespace sdm
diff --git a/msm8996/sdm/libs/core/fb/hw_device.cpp b/msm8996/sdm/libs/core/fb/hw_device.cpp
index 546490a..6b7dd2e 100644
--- a/msm8996/sdm/libs/core/fb/hw_device.cpp
+++ b/msm8996/sdm/libs/core/fb/hw_device.cpp
@@ -238,8 +238,10 @@
         mdp_layer.bg_color = layer->solid_fill_color;
 
         // HWScaleData to MDP driver
-        hw_scale_->SetHWScaleData(pipe_info->scale_data, mdp_layer_count, &mdp_layer);
-        mdp_layer.scale = hw_scale_->GetScaleDataRef(mdp_layer_count);
+        hw_scale_->SetHWScaleData(pipe_info->scale_data, mdp_layer_count, &mdp_commit,
+                                  pipe_info->sub_block_type);
+        mdp_layer.scale = hw_scale_->GetScaleDataRef(mdp_layer_count, pipe_info->sub_block_type);
+
         mdp_layer_count++;
 
         DLOGV_IF(kTagDriverConfig, "******************* Layer[%d] %s pipe Input ******************",
diff --git a/msm8996/sdm/libs/core/fb/hw_device.h b/msm8996/sdm/libs/core/fb/hw_device.h
index 7311271..d5b18de 100644
--- a/msm8996/sdm/libs/core/fb/hw_device.h
+++ b/msm8996/sdm/libs/core/fb/hw_device.h
@@ -84,6 +84,12 @@
   virtual DisplayError SetAutoRefresh(bool enable) { return kErrorNone; }
   virtual DisplayError SetS3DMode(HWS3DMode s3d_mode);
   virtual DisplayError SetScaleLutConfig(HWScaleLutInfo *lut_info);
+  virtual DisplayError SetMixerAttributes(const HWMixerAttributes &mixer_attributes) {
+    return kErrorNotSupported;
+  }
+  virtual DisplayError GetMixerAttributes(HWMixerAttributes *mixer_attributes) {
+    return kErrorNotSupported;
+  }
 
   // For HWDevice derivatives
   virtual DisplayError Init();
diff --git a/msm8996/sdm/libs/core/fb/hw_hdmi.cpp b/msm8996/sdm/libs/core/fb/hw_hdmi.cpp
index db7a2d9..3dfac8a 100644
--- a/msm8996/sdm/libs/core/fb/hw_hdmi.cpp
+++ b/msm8996/sdm/libs/core/fb/hw_hdmi.cpp
@@ -252,10 +252,8 @@
   display_attributes->y_dpi = 0;
   display_attributes->fps = timing_mode->refresh_rate / 1000;
   display_attributes->vsync_period_ns = UINT32(1000000000L / display_attributes->fps);
-  display_attributes->split_left = display_attributes->x_pixels;
   if (display_attributes->x_pixels > hw_resource_.max_mixer_width) {
     display_attributes->is_device_split = true;
-    display_attributes->split_left = display_attributes->x_pixels / 2;
     display_attributes->h_total += h_blanking;
   }
 
@@ -755,5 +753,21 @@
   return kErrorNone;
 }
 
+DisplayError HWHDMI::GetMixerAttributes(HWMixerAttributes *mixer_attributes) {
+  if (!mixer_attributes) {
+    return kErrorParameters;
+  }
+
+  HWDisplayAttributes display_attributes;
+  GetDisplayAttributes(active_config_index_, &display_attributes);
+
+  mixer_attributes->width = display_attributes.x_pixels;
+  mixer_attributes->height = display_attributes.y_pixels;
+  mixer_attributes->split_left = display_attributes.is_device_split ?
+      (display_attributes.x_pixels / 2) : mixer_attributes->width;
+
+  return kErrorNone;
+}
+
 }  // namespace sdm
 
diff --git a/msm8996/sdm/libs/core/fb/hw_hdmi.h b/msm8996/sdm/libs/core/fb/hw_hdmi.h
index aa5e2a0..833b3d3 100644
--- a/msm8996/sdm/libs/core/fb/hw_hdmi.h
+++ b/msm8996/sdm/libs/core/fb/hw_hdmi.h
@@ -69,6 +69,7 @@
   virtual DisplayError Validate(HWLayers *hw_layers);
   virtual DisplayError SetS3DMode(HWS3DMode s3d_mode);
   virtual DisplayError SetRefreshRate(uint32_t refresh_rate);
+  virtual DisplayError GetMixerAttributes(HWMixerAttributes *mixer_attributes);
 
  private:
   DisplayError ReadEDIDInfo();
diff --git a/msm8996/sdm/libs/core/fb/hw_info.cpp b/msm8996/sdm/libs/core/fb/hw_info.cpp
index f6f664a..25bb01c 100644
--- a/msm8996/sdm/libs/core/fb/hw_info.cpp
+++ b/msm8996/sdm/libs/core/fb/hw_info.cpp
@@ -31,6 +31,7 @@
 #include <utils/constants.h>
 #include <utils/debug.h>
 #include <utils/sys.h>
+#include <dlfcn.h>
 
 #include <algorithm>
 #include <iostream>
@@ -241,6 +242,16 @@
         hw_resource->system_overhead_lines = UINT32(atoi(tokens[1]));
       } else if (!strncmp(tokens[0], "wb_intf_index", strlen("wb_intf_index"))) {
         hw_resource->writeback_index = UINT32(atoi(tokens[1]));
+      } else if (!strncmp(tokens[0], "dest_scaler_count", strlen("dest_scaler_count"))) {
+        hw_resource->hw_dest_scalar_info.count = UINT32(atoi(tokens[1]));
+      } else if (!strncmp(tokens[0], "max_dest_scale_up", strlen("max_dest_scale_up"))) {
+        hw_resource->hw_dest_scalar_info.max_scale_up = UINT32(atoi(tokens[1]));
+      } else if (!strncmp(tokens[0], "max_dest_scaler_input_width",
+                 strlen("max_dest_scaler_input_width"))) {
+        hw_resource->hw_dest_scalar_info.max_input_width = UINT32(atoi(tokens[1]));
+      } else if (!strncmp(tokens[0], "max_dest_scaler_output_width",
+                 strlen("max_dest_scaler_output_width"))) {
+        hw_resource->hw_dest_scalar_info.max_output_width = UINT32(atoi(tokens[1]));
       } else if (!strncmp(tokens[0], "features", strlen("features"))) {
         for (uint32_t i = 0; i < token_count; i++) {
           if (!strncmp(tokens[i], "bwc", strlen("bwc"))) {
@@ -316,6 +327,14 @@
     }
   }
 
+  // Disable destination scalar count to 0 if extension library is not present
+  void *extension_lib = ::dlopen("libsdmextension.so", RTLD_NOW);
+  if (!extension_lib) {
+    hw_resource->hw_dest_scalar_info.count = 0;
+  } else {
+    ::dlclose(extension_lib);
+  }
+
   Sys::fclose_(fileptr);
 
   DLOGI("SDE Version = %d, SDE Revision = %x, RGB = %d, VIG = %d, DMA = %d, Cursor = %d",
diff --git a/msm8996/sdm/libs/core/fb/hw_primary.cpp b/msm8996/sdm/libs/core/fb/hw_primary.cpp
index 84eea2a..3d0c776 100644
--- a/msm8996/sdm/libs/core/fb/hw_primary.cpp
+++ b/msm8996/sdm/libs/core/fb/hw_primary.cpp
@@ -40,6 +40,7 @@
 #include <utils/sys.h>
 #include <core/display_interface.h>
 #include <linux/msm_mdp_ext.h>
+#include <utils/rect.h>
 
 #include <string>
 
@@ -99,11 +100,18 @@
     return error;
   }
 
+  uint32_t dest_scalar_count = hw_resource_.hw_dest_scalar_info.count;
+  if (dest_scalar_count) {
+    mdp_dest_scalar_data_ = new mdp_destination_scaler_data[dest_scalar_count];
+  }
+
   error = PopulateDisplayAttributes();
   if (error != kErrorNone) {
     return error;
   }
 
+  UpdateMixerAttributes();
+
   // Disable HPD at start if HDMI is external, it will be enabled later when the display powers on
   // This helps for framework reboot or adb shell stop/start
   EnableHotPlugDetection(0);
@@ -199,6 +207,8 @@
 }
 
 DisplayError HWPrimary::Deinit() {
+  delete [] mdp_dest_scalar_data_;
+
   return HWDevice::Deinit();
 }
 
@@ -273,8 +283,6 @@
   display_attributes_.vsync_period_ns = UINT32(1000000000L / display_attributes_.fps);
   display_attributes_.is_device_split = (hw_panel_info_.split_info.left_split ||
       (var_screeninfo.xres > hw_resource_.max_mixer_width)) ? true : false;
-  display_attributes_.split_left = hw_panel_info_.split_info.left_split ?
-      hw_panel_info_.split_info.left_split : display_attributes_.x_pixels / 2;
   display_attributes_.h_total += display_attributes_.is_device_split ? h_blanking : 0;
 
   return kErrorNone;
@@ -305,6 +313,7 @@
     DLOGI("Successfully set config %u", index);
     PopulateHWPanelInfo();
     PopulateDisplayAttributes();
+    UpdateMixerAttributes();
     active_config_index_ = index;
   } else {
     DLOGE("Writing config index %u failed with error: %s", index, strerror(errno));
@@ -381,15 +390,27 @@
   return kErrorNone;
 }
 
-DisplayError HWPrimary::Validate(HWLayers *hw_layers) {
-  LayerStack *stack = hw_layers->info.stack;
+void HWPrimary::ResetDisplayParams() {
+  uint32_t dst_scalar_cnt = hw_resource_.hw_dest_scalar_info.count;
 
   HWDevice::ResetDisplayParams();
 
+  if (mdp_dest_scalar_data_) {
+    memset(mdp_dest_scalar_data_, 0, sizeof(mdp_dest_scalar_data_) * dst_scalar_cnt);
+    mdp_disp_commit_.commit_v1.dest_scaler = mdp_dest_scalar_data_;
+  }
+}
+
+DisplayError HWPrimary::Validate(HWLayers *hw_layers) {
+  HWLayersInfo &hw_layer_info = hw_layers->info;
+  LayerStack *stack = hw_layer_info.stack;
+
+  ResetDisplayParams();
+
   mdp_layer_commit_v1 &mdp_commit = mdp_disp_commit_.commit_v1;
 
-  LayerRect left_roi = hw_layers->info.left_partial_update;
-  LayerRect right_roi = hw_layers->info.right_partial_update;
+  LayerRect left_roi = hw_layer_info.left_partial_update;
+  LayerRect right_roi = hw_layer_info.right_partial_update;
   mdp_commit.left_roi.x = UINT32(left_roi.left);
   mdp_commit.left_roi.y = UINT32(left_roi.top);
   mdp_commit.left_roi.w = UINT32(left_roi.right - left_roi.left);
@@ -398,8 +419,8 @@
   // SDM treats ROI as one full coordinate system.
   // In case source split is disabled, However, Driver assumes Mixer to operate in
   // different co-ordinate system.
-  if (!hw_resource_.is_src_split) {
-    mdp_commit.right_roi.x = UINT32(right_roi.left) - hw_panel_info_.split_info.left_split;
+  if (!hw_resource_.is_src_split && IsValid(right_roi)) {
+    mdp_commit.right_roi.x = UINT32(right_roi.left) - mixer_attributes_.split_left;
     mdp_commit.right_roi.y = UINT32(right_roi.top);
     mdp_commit.right_roi.w = UINT32(right_roi.right - right_roi.left);
     mdp_commit.right_roi.h = UINT32(right_roi.bottom - right_roi.top);
@@ -424,6 +445,40 @@
     DLOGI_IF(kTagDriverConfig, "****************************************************************");
   }
 
+  uint32_t index = 0;
+  for (uint32_t i = 0; i < hw_resource_.hw_dest_scalar_info.count; i++) {
+    DestScaleInfoMap::iterator it = hw_layer_info.dest_scale_info_map.find(i);
+
+    if (it == hw_layer_info.dest_scale_info_map.end()) {
+      continue;
+    }
+
+    HWDestScaleInfo *dest_scale_info = it->second;
+
+    mdp_destination_scaler_data *dest_scalar_data = &mdp_dest_scalar_data_[index];
+    hw_scale_->SetHWScaleData(dest_scale_info->scale_data, index, &mdp_commit,
+                              kHWDestinationScalar);
+
+    if (dest_scale_info->scale_update) {
+      dest_scalar_data->flags |= MDP_DESTSCALER_SCALE_UPDATE;
+    }
+
+    dest_scalar_data->dest_scaler_ndx = i;
+    dest_scalar_data->lm_width = dest_scale_info->mixer_width;
+    dest_scalar_data->lm_height = dest_scale_info->mixer_height;
+    dest_scalar_data->scale = reinterpret_cast <uint64_t>
+      (hw_scale_->GetScaleDataRef(index, kHWDestinationScalar));
+
+    index++;
+
+    DLOGV_IF(kTagDriverConfig, "************************ DestScalar[%d] **************************",
+             dest_scalar_data->dest_scaler_ndx);
+    DLOGV_IF(kTagDriverConfig, "Mixer WxH %dx%d", dest_scalar_data->lm_width,
+             dest_scalar_data->lm_height);
+    DLOGI_IF(kTagDriverConfig, "*****************************************************************");
+  }
+  mdp_commit.dest_scaler_cnt = UINT32(hw_layer_info.dest_scale_info_map.size());
+
   return HWDevice::Validate(hw_layers);
 }
 
@@ -640,5 +695,76 @@
   return kErrorNone;
 }
 
+DisplayError HWPrimary::SetMixerAttributes(const HWMixerAttributes &mixer_attributes) {
+  if (IsResolutionSwitchEnabled() || !hw_resource_.hw_dest_scalar_info.count) {
+    return kErrorNotSupported;
+  }
+
+  if (mixer_attributes.width > display_attributes_.x_pixels ||
+      mixer_attributes.height > display_attributes_.y_pixels) {
+    DLOGW("Input resolution exceeds display resolution! input: res %dx%d display: res %dx%d",
+          mixer_attributes.width, mixer_attributes.height, display_attributes_.x_pixels,
+          display_attributes_.y_pixels);
+    return kErrorNotSupported;
+  }
+
+  uint32_t max_input_width = hw_resource_.hw_dest_scalar_info.max_input_width;
+  if (display_attributes_.is_device_split) {
+    max_input_width *= 2;
+  }
+
+  if (mixer_attributes.width > max_input_width) {
+    DLOGW("Input width exceeds width limit! input_width %d width_limit %d", mixer_attributes.width,
+          max_input_width);
+    return kErrorNotSupported;
+  }
+
+  float mixer_aspect_ratio = FLOAT(mixer_attributes.width) / FLOAT(mixer_attributes.height);
+  float display_aspect_ratio =
+    FLOAT(display_attributes_.x_pixels) / FLOAT(display_attributes_.y_pixels);
+
+  if (display_aspect_ratio != mixer_aspect_ratio) {
+    DLOGW("Aspect ratio mismatch! input: res %dx%d display: res %dx%d", mixer_attributes.width,
+          mixer_attributes.height, display_attributes_.x_pixels, display_attributes_.y_pixels);
+    return kErrorNotSupported;
+  }
+
+  float scale_x = FLOAT(display_attributes_.x_pixels) / FLOAT(mixer_attributes.width);
+  float scale_y = FLOAT(display_attributes_.y_pixels) / FLOAT(mixer_attributes.height);
+  float max_scale_up = hw_resource_.hw_dest_scalar_info.max_scale_up;
+  if (scale_x > max_scale_up || scale_y > max_scale_up) {
+    DLOGW("Up scaling ratio exceeds for destination scalar upscale limit scale_x %f scale_y %f " \
+          "max_scale_up %f", scale_x, scale_y, max_scale_up);
+    return kErrorNotSupported;
+  }
+
+  float mixer_split_ratio = FLOAT(mixer_attributes_.split_left) / FLOAT(mixer_attributes_.width);
+
+  mixer_attributes_ = mixer_attributes;
+  mixer_attributes_.split_left = mixer_attributes_.width;
+  if (display_attributes_.is_device_split) {
+    mixer_attributes_.split_left = UINT32(FLOAT(mixer_attributes.width) * mixer_split_ratio);
+  }
+
+  return kErrorNone;
+}
+
+DisplayError HWPrimary::GetMixerAttributes(HWMixerAttributes *mixer_attributes) {
+  if (!mixer_attributes) {
+    return kErrorParameters;
+  }
+
+  *mixer_attributes = mixer_attributes_;
+
+  return kErrorNone;
+}
+
+void HWPrimary::UpdateMixerAttributes() {
+  mixer_attributes_.width = display_attributes_.x_pixels;
+  mixer_attributes_.height = display_attributes_.y_pixels;
+  mixer_attributes_.split_left = display_attributes_.is_device_split ?
+      hw_panel_info_.split_info.left_split : mixer_attributes_.width;
+}
+
 }  // namespace sdm
 
diff --git a/msm8996/sdm/libs/core/fb/hw_primary.h b/msm8996/sdm/libs/core/fb/hw_primary.h
index 999c41a..36b3f63 100644
--- a/msm8996/sdm/libs/core/fb/hw_primary.h
+++ b/msm8996/sdm/libs/core/fb/hw_primary.h
@@ -65,6 +65,8 @@
   virtual DisplayError SetPPFeatures(PPFeaturesConfig *feature_list);
   virtual DisplayError GetPanelBrightness(int *level);
   virtual DisplayError SetAutoRefresh(bool enable);
+  virtual DisplayError SetMixerAttributes(const HWMixerAttributes &mixer_attributes);
+  virtual DisplayError GetMixerAttributes(HWMixerAttributes *mixer_attributes);
 
  private:
   // Panel modes for the MSMFB_LPM_ENABLE ioctl
@@ -77,6 +79,8 @@
   void InitializeConfigs();
   bool IsResolutionSwitchEnabled() { return !display_configs_.empty(); }
   bool GetCurrentModeFromSysfs(size_t *curr_x_pixels, size_t *curr_y_pixels);
+  void UpdateMixerAttributes();
+  void ResetDisplayParams();
 
   HWDisplayAttributes display_attributes_;
   std::vector<DisplayConfigVariableInfo> display_configs_;
@@ -85,6 +89,8 @@
   const char *kBrightnessNode = "/sys/class/leds/lcd-backlight/brightness";
   const char *kAutoRefreshNode = "/sys/devices/virtual/graphics/fb0/msm_cmd_autorefresh_en";
   bool auto_refresh_ = false;
+  HWMixerAttributes mixer_attributes_ = {};
+  mdp_destination_scaler_data *mdp_dest_scalar_data_ = NULL;
 };
 
 }  // namespace sdm
diff --git a/msm8996/sdm/libs/core/fb/hw_scale.cpp b/msm8996/sdm/libs/core/fb/hw_scale.cpp
index f18727f..3d175e5 100644
--- a/msm8996/sdm/libs/core/fb/hw_scale.cpp
+++ b/msm8996/sdm/libs/core/fb/hw_scale.cpp
@@ -47,11 +47,16 @@
 }
 
 void HWScaleV1::SetHWScaleData(const HWScaleData &scale_data, uint32_t index,
-                               mdp_input_layer *mdp_layer) {
+                               mdp_layer_commit_v1 *mdp_commit, HWSubBlockType sub_block_type) {
   if (!scale_data.enable.scale) {
     return;
   }
 
+  if (sub_block_type == kHWDestinationScalar) {
+    return;
+  }
+
+  mdp_input_layer *mdp_layer = &mdp_commit->input_layers[index];
   mdp_layer->flags |= MDP_LAYER_ENABLE_PIXEL_EXT;
   mdp_scale_data *mdp_scale = &scale_data_v1_.at(index);
   mdp_scale->enable_pxl_ext = scale_data.enable.scale;
@@ -84,8 +89,12 @@
   return;
 }
 
-void* HWScaleV1::GetScaleDataRef(uint32_t index) {
-  return &scale_data_v1_.at(index);
+void* HWScaleV1::GetScaleDataRef(uint32_t index, HWSubBlockType sub_block_type) {
+  if (sub_block_type != kHWDestinationScalar) {
+    return &scale_data_v1_.at(index);
+  }
+
+  return NULL;
 }
 
 void HWScaleV1::DumpScaleData(void *mdp_scale) {
@@ -112,14 +121,32 @@
 }
 
 void HWScaleV2::SetHWScaleData(const HWScaleData &scale_data, uint32_t index,
-                               mdp_input_layer *mdp_layer) {
+                               mdp_layer_commit_v1 *mdp_commit, HWSubBlockType sub_block_type) {
   if (!scale_data.enable.scale && !scale_data.enable.direction_detection &&
       !scale_data.enable.detail_enhance ) {
     return;
   }
 
-  mdp_scale_data_v2 *mdp_scale = &scale_data_v2_.at(index);
-  mdp_layer->flags |= MDP_LAYER_ENABLE_QSEED3_SCALE;
+  mdp_scale_data_v2 *mdp_scale;
+  if (sub_block_type != kHWDestinationScalar) {
+    mdp_input_layer *mdp_layer = &mdp_commit->input_layers[index];
+    mdp_layer->flags |= MDP_LAYER_ENABLE_QSEED3_SCALE;
+    mdp_scale = &scale_data_v2_.at(index);
+  } else {
+    mdp_scale_data_v2 mdp_dest_scale;
+    mdp_destination_scaler_data *dest_scalar =
+      reinterpret_cast<mdp_destination_scaler_data *>(mdp_commit->dest_scaler);
+
+    dest_scalar[index].flags = MDP_DESTSCALER_ENABLE;
+
+    if (scale_data.enable.detail_enhance) {
+      dest_scalar[index].flags |= MDP_DESTSCALER_ENHANCER_UPDATE;
+    }
+
+    dest_scale_data_v2_.insert(std::make_pair(index, mdp_dest_scale));
+    mdp_scale = &dest_scale_data_v2_[index];
+  }
+
   mdp_scale->enable = (scale_data.enable.scale ? ENABLE_SCALE : 0) |
                       (scale_data.enable.direction_detection ? ENABLE_DIRECTION_DETECTION : 0) |
                       (scale_data.enable.detail_enhance ? ENABLE_DETAIL_ENHANCE : 0);
@@ -206,23 +233,27 @@
   return;
 }
 
-void* HWScaleV2::GetScaleDataRef(uint32_t index) {
-  return &scale_data_v2_.at(index);
+void* HWScaleV2::GetScaleDataRef(uint32_t index, HWSubBlockType sub_block_type) {
+  if (sub_block_type != kHWDestinationScalar) {
+    return &scale_data_v2_.at(index);
+  } else {
+    return &dest_scale_data_v2_[index];
+  }
 }
 
-uint32_t HWScaleV2::GetMDPScalingFilter(HWScalingFilter filter_cfg) {
+uint32_t HWScaleV2::GetMDPScalingFilter(ScalingFilterConfig filter_cfg) {
   switch (filter_cfg) {
-  case kScalingFilterEdgeDirected:
+  case kFilterEdgeDirected:
     return FILTER_EDGE_DIRECTED_2D;
-  case kScalingFilterCircular:
+  case kFilterCircular:
     return FILTER_CIRCULAR_2D;
-  case kScalingFilterSeparable:
+  case kFilterSeparable:
     return FILTER_SEPARABLE_1D;
-  case kScalingFilterBilinear:
+  case kFilterBilinear:
     return FILTER_BILINEAR;
   default:
     DLOGE("Invalid Scaling Filter");
-    return kScalingFilterMax;
+    return kFilterMax;
   }
 }
 
diff --git a/msm8996/sdm/libs/core/fb/hw_scale.h b/msm8996/sdm/libs/core/fb/hw_scale.h
index 0891d42..7590833 100644
--- a/msm8996/sdm/libs/core/fb/hw_scale.h
+++ b/msm8996/sdm/libs/core/fb/hw_scale.h
@@ -30,6 +30,7 @@
 
 #include <cstring>
 #include <array>
+#include <map>
 
 namespace sdm {
 
@@ -39,8 +40,8 @@
   static DisplayError Destroy(HWScale *intf);
 
   virtual void SetHWScaleData(const HWScaleData &scale, uint32_t index,
-                              mdp_input_layer *mdp_layer) = 0;
-  virtual void* GetScaleDataRef(uint32_t index) = 0;
+                              mdp_layer_commit_v1 *mdp_commit, HWSubBlockType sub_block_type) = 0;
+  virtual void* GetScaleDataRef(uint32_t index, HWSubBlockType sub_block_type) = 0;
   virtual void DumpScaleData(void *mdp_scale) = 0;
   virtual void ResetScaleParams() = 0;
  protected:
@@ -50,8 +51,8 @@
 class HWScaleV1 : public HWScale {
  public:
   virtual void SetHWScaleData(const HWScaleData &scale, uint32_t index,
-                              mdp_input_layer *mdp_layer);
-  virtual void* GetScaleDataRef(uint32_t index);
+                              mdp_layer_commit_v1 *mdp_commit, HWSubBlockType sub_block_type);
+  virtual void* GetScaleDataRef(uint32_t index, HWSubBlockType sub_block_type);
   virtual void DumpScaleData(void *mdp_scale);
   virtual void ResetScaleParams() { scale_data_v1_ = {}; }
 
@@ -63,18 +64,19 @@
 class HWScaleV2 : public HWScale {
  public:
   virtual void SetHWScaleData(const HWScaleData &scale, uint32_t index,
-                              mdp_input_layer *mdp_layer);
-  virtual void* GetScaleDataRef(uint32_t index);
+                              mdp_layer_commit_v1 *mdp_commit, HWSubBlockType sub_block_type);
+  virtual void* GetScaleDataRef(uint32_t index, HWSubBlockType sub_block_type);
   virtual void DumpScaleData(void *mdp_scale);
-  virtual void ResetScaleParams() { scale_data_v2_ = {}; }
+  virtual void ResetScaleParams() { scale_data_v2_ = {}; dest_scale_data_v2_ = {}; }
 
  protected:
   ~HWScaleV2() {}
   std::array<mdp_scale_data_v2, (kMaxSDELayers * 2)> scale_data_v2_ = {};
+  std::map<uint32_t, mdp_scale_data_v2> dest_scale_data_v2_ = {};
 
  private:
   uint32_t GetMDPAlphaInterpolation(HWAlphaInterpolation alpha_filter_cfg);
-  uint32_t GetMDPScalingFilter(HWScalingFilter filter_cfg);
+  uint32_t GetMDPScalingFilter(ScalingFilterConfig filter_cfg);
 };
 
 }  // namespace sdm
diff --git a/msm8996/sdm/libs/core/hw_interface.h b/msm8996/sdm/libs/core/hw_interface.h
index 75d92b9..0ff5126 100644
--- a/msm8996/sdm/libs/core/hw_interface.h
+++ b/msm8996/sdm/libs/core/hw_interface.h
@@ -95,6 +95,8 @@
   virtual DisplayError SetAutoRefresh(bool enable) = 0;
   virtual DisplayError SetS3DMode(HWS3DMode s3d_mode) = 0;
   virtual DisplayError SetScaleLutConfig(HWScaleLutInfo *lut_info) = 0;
+  virtual DisplayError SetMixerAttributes(const HWMixerAttributes &mixer_attributes) = 0;
+  virtual DisplayError GetMixerAttributes(HWMixerAttributes *mixer_attributes) = 0;
 
  protected:
   virtual ~HWInterface() { }
diff --git a/msm8996/sdm/libs/core/resource_default.cpp b/msm8996/sdm/libs/core/resource_default.cpp
index e13150b..bdbd8b7 100644
--- a/msm8996/sdm/libs/core/resource_default.cpp
+++ b/msm8996/sdm/libs/core/resource_default.cpp
@@ -104,8 +104,9 @@
 }
 
 DisplayError ResourceDefault::RegisterDisplay(DisplayType type,
-                                              const HWDisplayAttributes &attributes,
+                                              const HWDisplayAttributes &display_attributes,
                                               const HWPanelInfo &hw_panel_info,
+                                              const HWMixerAttributes &mixer_attributes,
                                               Handle *display_ctx) {
   DisplayError error = kErrorNone;
 
@@ -139,12 +140,9 @@
 
   hw_block_ctx_[hw_block_id].is_in_use = true;
 
-  display_resource_ctx->display_attributes = attributes;
+  display_resource_ctx->display_attributes = display_attributes;
   display_resource_ctx->hw_block_id = hw_block_id;
-
-  if (!display_resource_ctx->display_attributes.is_device_split) {
-    display_resource_ctx->display_attributes.split_left = attributes.x_pixels;
-  }
+  display_resource_ctx->mixer_attributes = mixer_attributes;
 
   *display_ctx = display_resource_ctx;
   return error;
@@ -162,14 +160,19 @@
   return kErrorNone;
 }
 
-void ResourceDefault::ReconfigureDisplay(Handle display_ctx, const HWDisplayAttributes &attributes,
-                                    const HWPanelInfo &hw_panel_info) {
+DisplayError ResourceDefault::ReconfigureDisplay(Handle display_ctx,
+                                                 const HWDisplayAttributes &display_attributes,
+                                                 const HWPanelInfo &hw_panel_info,
+                                                 const HWMixerAttributes &mixer_attributes) {
   SCOPE_LOCK(locker_);
 
   DisplayResourceContext *display_resource_ctx =
                           reinterpret_cast<DisplayResourceContext *>(display_ctx);
 
-  display_resource_ctx->display_attributes = attributes;
+  display_resource_ctx->display_attributes = display_attributes;
+  display_resource_ctx->mixer_attributes = mixer_attributes;
+
+  return kErrorNone;
 }
 
 DisplayError ResourceDefault::Start(Handle display_ctx) {
@@ -447,20 +450,20 @@
 DisplayError ResourceDefault::DisplaySplitConfig(DisplayResourceContext *display_resource_ctx,
                                             const LayerRect &src_rect, const LayerRect &dst_rect,
                                             HWLayerConfig *layer_config) {
-  HWDisplayAttributes &display_attributes = display_resource_ctx->display_attributes;
+  HWMixerAttributes &mixer_attributes = display_resource_ctx->mixer_attributes;
 
   // for display split case
   HWPipeInfo *left_pipe = &layer_config->left_pipe;
   HWPipeInfo *right_pipe = &layer_config->right_pipe;
   LayerRect scissor_left, scissor_right, dst_left, crop_left, crop_right, dst_right;
 
-  scissor_left.right = FLOAT(display_attributes.split_left);
-  scissor_left.bottom = FLOAT(display_attributes.y_pixels);
+  scissor_left.right = FLOAT(mixer_attributes.split_left);
+  scissor_left.bottom = FLOAT(mixer_attributes.height);
 
-  scissor_right.left = FLOAT(display_attributes.split_left);
+  scissor_right.left = FLOAT(mixer_attributes.split_left);
   scissor_right.top = 0.0f;
-  scissor_right.right = FLOAT(display_attributes.x_pixels);
-  scissor_right.bottom = FLOAT(display_attributes.y_pixels);
+  scissor_right.right = FLOAT(mixer_attributes.width);
+  scissor_right.bottom = FLOAT(mixer_attributes.height);
 
   crop_left = src_rect;
   dst_left = dst_rect;
@@ -901,4 +904,9 @@
   return kErrorNone;
 }
 
+DisplayError ResourceDefault::SetDetailEnhancerData(Handle display_ctx,
+                                                    const DisplayDetailEnhancerData &de_data) {
+  return kErrorNotSupported;
+}
+
 }  // namespace sdm
diff --git a/msm8996/sdm/libs/core/resource_default.h b/msm8996/sdm/libs/core/resource_default.h
index ce6dd5f..b57ce94 100644
--- a/msm8996/sdm/libs/core/resource_default.h
+++ b/msm8996/sdm/libs/core/resource_default.h
@@ -37,11 +37,16 @@
  public:
   DisplayError Init(const HWResourceInfo &hw_resource_info);
   DisplayError Deinit();
-  virtual DisplayError RegisterDisplay(DisplayType type, const HWDisplayAttributes &attributes,
-                                       const HWPanelInfo &hw_panel_info, Handle *display_ctx);
+  virtual DisplayError RegisterDisplay(DisplayType type,
+                                       const HWDisplayAttributes &display_attributes,
+                                       const HWPanelInfo &hw_panel_info,
+                                       const HWMixerAttributes &mixer_attributes,
+                                       Handle *display_ctx);
   virtual DisplayError UnregisterDisplay(Handle display_ctx);
-  virtual void ReconfigureDisplay(Handle display_ctx, const HWDisplayAttributes &attributes,
-                                  const HWPanelInfo &hw_panel_info);
+  virtual DisplayError ReconfigureDisplay(Handle display_ctx,
+                                          const HWDisplayAttributes &display_attributes,
+                                          const HWPanelInfo &hw_panel_info,
+                                          const HWMixerAttributes &mixer_attributes);
   virtual DisplayError Start(Handle display_ctx);
   virtual DisplayError Stop(Handle display_ctx);
   virtual DisplayError Acquire(Handle display_ctx, HWLayers *hw_layers);
@@ -54,6 +59,8 @@
   DisplayError ValidateCursorConfig(Handle display_ctx, const Layer *layer, bool is_top);
   DisplayError ValidateCursorPosition(Handle display_ctx, HWLayers *hw_layers, int x, int y);
   DisplayError SetMaxBandwidthMode(HWBwModes mode);
+  virtual DisplayError SetDetailEnhancerData(Handle display_ctx,
+                                             const DisplayDetailEnhancerData &de_data);
 
  private:
   enum PipeOwner {
@@ -84,6 +91,7 @@
     HWDisplayAttributes display_attributes;
     HWBlockType hw_block_id;
     uint64_t frame_count;
+    HWMixerAttributes mixer_attributes;
 
     DisplayResourceContext() : hw_block_id(kHWBlockMax), frame_count(0) { }
   };
diff --git a/msm8996/sdm/libs/core/strategy.cpp b/msm8996/sdm/libs/core/strategy.cpp
index b8a499e..a70ac36 100644
--- a/msm8996/sdm/libs/core/strategy.cpp
+++ b/msm8996/sdm/libs/core/strategy.cpp
@@ -33,9 +33,12 @@
 
 Strategy::Strategy(ExtensionInterface *extension_intf, DisplayType type,
                    const HWResourceInfo &hw_resource_info, const HWPanelInfo &hw_panel_info,
-                   const HWDisplayAttributes &hw_display_attributes)
+                   const HWMixerAttributes &mixer_attributes,
+                   const HWDisplayAttributes &display_attributes,
+                   const DisplayConfigVariableInfo &fb_config)
   : extension_intf_(extension_intf), display_type_(type), hw_resource_info_(hw_resource_info),
-    hw_panel_info_(hw_panel_info), hw_display_attributes_(hw_display_attributes) {
+    hw_panel_info_(hw_panel_info), mixer_attributes_(mixer_attributes),
+    display_attributes_(display_attributes), fb_config_(fb_config) {
 }
 
 DisplayError Strategy::Init() {
@@ -43,14 +46,16 @@
 
   if (extension_intf_) {
     error = extension_intf_->CreateStrategyExtn(display_type_, hw_panel_info_.mode,
-                                                hw_panel_info_.s3d_mode, &strategy_intf_);
+                                                hw_panel_info_.s3d_mode, mixer_attributes_,
+                                                fb_config_, &strategy_intf_);
     if (error != kErrorNone) {
       DLOGE("Failed to create strategy");
       return error;
     }
 
-    error = extension_intf_->CreatePartialUpdate(display_type_, hw_resource_info_,
-                                                 hw_panel_info_, &partial_update_intf_);
+    error = extension_intf_->CreatePartialUpdate(display_type_, hw_resource_info_, hw_panel_info_,
+                                                 mixer_attributes_, display_attributes_,
+                                                 &partial_update_intf_);
   }
 
   return kErrorNone;
@@ -75,11 +80,9 @@
   hw_layers_info_ = hw_layers_info;
   extn_start_success_ = false;
   tried_default_ = false;
-
   uint32_t i = 0;
   LayerStack *layer_stack = hw_layers_info_->stack;
   uint32_t layer_count = UINT32(layer_stack->layers.size());
-
   for (; i < layer_count; i++) {
     if (layer_stack->layers.at(i)->composition == kCompositionGPUTarget) {
       fb_layer_index_ = i;
@@ -167,29 +170,34 @@
     return;
   }
 
-  float disp_x_res = hw_display_attributes_.x_pixels;
-  float disp_y_res = hw_display_attributes_.y_pixels;
+  float layer_mixer_width = mixer_attributes_.width;
+  float layer_mixer_height = mixer_attributes_.height;
 
   if (!hw_resource_info_.is_src_split &&
-     ((disp_x_res > hw_resource_info_.max_mixer_width) ||
+     ((layer_mixer_width > hw_resource_info_.max_mixer_width) ||
      ((display_type_ == kPrimary) && hw_panel_info_.split_info.right_split))) {
     split_display = true;
   }
 
   if (split_display) {
-    float left_split = FLOAT(hw_panel_info_.split_info.left_split);
-    hw_layers_info_->left_partial_update = (LayerRect) {0.0f, 0.0f, left_split, disp_y_res};
-    hw_layers_info_->right_partial_update = (LayerRect) {left_split, 0.0f, disp_x_res, disp_y_res};
+    float left_split = FLOAT(mixer_attributes_.split_left);
+    hw_layers_info_->left_partial_update = (LayerRect) {0.0f, 0.0f, left_split, layer_mixer_height};
+    hw_layers_info_->right_partial_update = (LayerRect) {left_split, 0.0f, layer_mixer_width,
+                                            layer_mixer_height};
   } else {
-    hw_layers_info_->left_partial_update = (LayerRect) {0.0f, 0.0f, disp_x_res, disp_y_res};
+    hw_layers_info_->left_partial_update = (LayerRect) {0.0f, 0.0f, layer_mixer_width,
+                                           layer_mixer_height};
     hw_layers_info_->right_partial_update = (LayerRect) {0.0f, 0.0f, 0.0f, 0.0f};
   }
 }
 
 DisplayError Strategy::Reconfigure(const HWPanelInfo &hw_panel_info,
-                         const HWDisplayAttributes &hw_display_attributes) {
+                         const HWDisplayAttributes &display_attributes,
+                         const HWMixerAttributes &mixer_attributes,
+                         const DisplayConfigVariableInfo &fb_config) {
   hw_panel_info_ = hw_panel_info;
-  hw_display_attributes_ = hw_display_attributes;
+  display_attributes_ = display_attributes;
+  mixer_attributes_ = mixer_attributes;
 
   if (!extension_intf_) {
     return kErrorNone;
@@ -202,10 +210,12 @@
     partial_update_intf_ = NULL;
   }
 
-  extension_intf_->CreatePartialUpdate(display_type_, hw_resource_info_,
-                                       hw_panel_info_, &partial_update_intf_);
+  extension_intf_->CreatePartialUpdate(display_type_, hw_resource_info_, hw_panel_info_,
+                                       mixer_attributes_, display_attributes_,
+                                       &partial_update_intf_);
 
-  return strategy_intf_->Reconfigure(hw_panel_info_.mode, hw_panel_info_.s3d_mode);
+  return strategy_intf_->Reconfigure(hw_panel_info_.mode, hw_panel_info_.s3d_mode, mixer_attributes,
+                                     fb_config);
 }
 
 }  // namespace sdm
diff --git a/msm8996/sdm/libs/core/strategy.h b/msm8996/sdm/libs/core/strategy.h
index 5f14d28..b284d61 100644
--- a/msm8996/sdm/libs/core/strategy.h
+++ b/msm8996/sdm/libs/core/strategy.h
@@ -34,7 +34,8 @@
  public:
   Strategy(ExtensionInterface *extension_intf, DisplayType type,
            const HWResourceInfo &hw_resource_info, const HWPanelInfo &hw_panel_info,
-           const HWDisplayAttributes &hw_display_attributes);
+           const HWMixerAttributes &mixer_attributes, const HWDisplayAttributes &display_attributes,
+           const DisplayConfigVariableInfo &fb_config);
 
   DisplayError Init();
   DisplayError Deinit();
@@ -44,7 +45,9 @@
   DisplayError GetNextStrategy(StrategyConstraints *constraints);
   DisplayError Stop();
   DisplayError Reconfigure(const HWPanelInfo &hw_panel_info,
-                           const HWDisplayAttributes &hw_display_attributes);
+                           const HWDisplayAttributes &hw_display_attributes,
+                           const HWMixerAttributes &mixer_attributes,
+                           const DisplayConfigVariableInfo &fb_config);
 
  private:
   void GenerateROI();
@@ -56,7 +59,9 @@
   HWResourceInfo hw_resource_info_;
   HWPanelInfo hw_panel_info_;
   HWLayersInfo *hw_layers_info_ = NULL;
-  HWDisplayAttributes hw_display_attributes_;
+  HWMixerAttributes mixer_attributes_ = {};
+  HWDisplayAttributes display_attributes_ = {};
+  DisplayConfigVariableInfo fb_config_ = {};
   uint32_t fb_layer_index_ = 0;
   bool extn_start_success_ = false;
   bool tried_default_ = false;
diff --git a/msm8996/sdm/libs/hwc/hwc_color_manager.cpp b/msm8996/sdm/libs/hwc/hwc_color_manager.cpp
index 27115b5..7c12ec0 100644
--- a/msm8996/sdm/libs/hwc/hwc_color_manager.cpp
+++ b/msm8996/sdm/libs/hwc/hwc_color_manager.cpp
@@ -254,7 +254,7 @@
     uint32_t primary_width = 0;
     uint32_t primary_height = 0;
 
-    hwc_display->GetPanelResolution(&primary_width, &primary_height);
+    hwc_display->GetMixerResolution(&primary_width, &primary_height);
     uint8_t *buf = new uint8_t[size]();
     // handle for solid fill layer with fd = -1.
     private_handle_t *handle =
diff --git a/msm8996/sdm/libs/hwc/hwc_display.cpp b/msm8996/sdm/libs/hwc/hwc_display.cpp
index f829f68..97e6c02 100644
--- a/msm8996/sdm/libs/hwc/hwc_display.cpp
+++ b/msm8996/sdm/libs/hwc/hwc_display.cpp
@@ -83,13 +83,6 @@
     swap_interval_zero_ = true;
   }
 
-  framebuffer_config_ = new DisplayConfigVariableInfo();
-  if (!framebuffer_config_) {
-    DLOGV("Failed to allocate memory for custom framebuffer config.");
-    core_intf_->DestroyDisplay(display_intf_);
-    return -EINVAL;
-  }
-
   int blit_enabled = 0;
   HWCDebugHandler::Get()->GetProperty("persist.hwc.blit.comp", &blit_enabled);
   if (needs_blit_ && blit_enabled) {
@@ -126,8 +119,6 @@
     return -EINVAL;
   }
 
-  delete framebuffer_config_;
-
   if (blit_engine_) {
     blit_engine_->DeInit();
     delete blit_engine_;
@@ -224,11 +215,17 @@
   return 0;
 }
 
-int HWCDisplay::GetDisplayAttributes(uint32_t config, const uint32_t *attributes, int32_t *values) {
-  DisplayConfigVariableInfo variable_config = *framebuffer_config_;
+int HWCDisplay::GetDisplayAttributes(uint32_t config, const uint32_t *display_attributes,
+                                     int32_t *values) {
+  DisplayConfigVariableInfo variable_config;
+  DisplayError error = display_intf_->GetFrameBufferConfig(&variable_config);
+  if (error != kErrorNone) {
+    DLOGV("Get variable config failed. Error = %d", error);
+    return -EINVAL;
+  }
 
-  for (int i = 0; attributes[i] != HWC_DISPLAY_NO_ATTRIBUTE; i++) {
-    switch (attributes[i]) {
+  for (int i = 0; display_attributes[i] != HWC_DISPLAY_NO_ATTRIBUTE; i++) {
+    switch (display_attributes[i]) {
     case HWC_DISPLAY_VSYNC_PERIOD:
       values[i] = INT32(variable_config.vsync_period_ns);
       break;
@@ -245,7 +242,7 @@
       values[i] = INT32(variable_config.y_dpi * 1000.0f);
       break;
     default:
-      DLOGW("Spurious attribute type = %d", attributes[i]);
+      DLOGW("Spurious attribute type = %d", display_attributes[i]);
       return -EINVAL;
     }
   }
@@ -261,6 +258,10 @@
   return -1;
 }
 
+DisplayError HWCDisplay::SetMixerResolution(uint32_t width, uint32_t height) {
+  return kErrorNotSupported;
+}
+
 void HWCDisplay::SetFrameDumpConfig(uint32_t count, uint32_t bit_mask_layer_type) {
   dump_frame_count_ = count;
   dump_frame_index_ = 0;
@@ -450,7 +451,6 @@
     }
 
     hwc_rect_t scaled_display_frame = hwc_layer.displayFrame;
-    ScaleDisplayFrame(&scaled_display_frame);
     ApplyScanAdjustment(&scaled_display_frame);
 
     SetRect(scaled_display_frame, &layer->dst_rect);
@@ -792,16 +792,6 @@
   return error;
 }
 
-DisplayError HWCDisplay::ControlPartialUpdate(bool enable, uint32_t *pending) {
-  DisplayError error = kErrorNone;
-
-  if (display_intf_) {
-    error = display_intf_->ControlPartialUpdate(enable, pending);
-  }
-
-  return error;
-}
-
 LayerBufferFormat HWCDisplay::GetSDMFormat(const int32_t &source, const int flags) {
   LayerBufferFormat format = kFormatInvalid;
   if (flags & private_handle_t::PRIV_FLAGS_UBWC_ALIGNED) {
@@ -1042,108 +1032,49 @@
 }
 
 int HWCDisplay::SetFrameBufferResolution(uint32_t x_pixels, uint32_t y_pixels) {
-  if (x_pixels <= 0 || y_pixels <= 0) {
-    DLOGV("Unsupported config: x_pixels=%d, y_pixels=%d", x_pixels, y_pixels);
-    return -EINVAL;
-  }
-
-  if (framebuffer_config_->x_pixels == x_pixels && framebuffer_config_->y_pixels == y_pixels) {
-    return 0;
-  }
-
-  DisplayConfigVariableInfo active_config;
-  uint32_t active_config_index = 0;
-  display_intf_->GetActiveConfig(&active_config_index);
-  DisplayError error = display_intf_->GetConfig(active_config_index, &active_config);
+  DisplayConfigVariableInfo fb_config;
+  DisplayError error = display_intf_->GetFrameBufferConfig(&fb_config);
   if (error != kErrorNone) {
-    DLOGV("GetConfig variable info failed. Error = %d", error);
+    DLOGV("Get frame buffer config failed. Error = %d", error);
     return -EINVAL;
   }
 
-  if (active_config.x_pixels <= 0 || active_config.y_pixels <= 0) {
-    DLOGV("Invalid panel resolution (%dx%d)", active_config.x_pixels, active_config.y_pixels);
-    return -EINVAL;
-  }
+  fb_config.x_pixels = x_pixels;
+  fb_config.y_pixels = y_pixels;
 
-  // Create rects to represent the new source and destination crops
-  LayerRect crop = LayerRect(0, 0, FLOAT(x_pixels), FLOAT(y_pixels));
-  LayerRect dst = LayerRect(0, 0, FLOAT(active_config.x_pixels), FLOAT(active_config.y_pixels));
-  // Set rotate90 to false since this is taken care of during regular composition.
-  bool rotate90 = false;
-  error = display_intf_->IsScalingValid(crop, dst, rotate90);
+  error = display_intf_->SetFrameBufferConfig(fb_config);
   if (error != kErrorNone) {
-    DLOGV("Unsupported resolution: (%dx%d)", x_pixels, y_pixels);
+    DLOGV("Set frame buffer config failed. Error = %d", error);
     return -EINVAL;
   }
 
-  framebuffer_config_->x_pixels = x_pixels;
-  framebuffer_config_->y_pixels = y_pixels;
-  framebuffer_config_->vsync_period_ns = active_config.vsync_period_ns;
-  framebuffer_config_->x_dpi = active_config.x_dpi;
-  framebuffer_config_->y_dpi = active_config.y_dpi;
-
-  DLOGI("New framebuffer resolution (%dx%d)", framebuffer_config_->x_pixels,
-        framebuffer_config_->y_pixels);
+  DLOGI("New framebuffer resolution (%dx%d)", x_pixels, y_pixels);
 
   return 0;
 }
 
 void HWCDisplay::GetFrameBufferResolution(uint32_t *x_pixels, uint32_t *y_pixels) {
-  *x_pixels = framebuffer_config_->x_pixels;
-  *y_pixels = framebuffer_config_->y_pixels;
+  DisplayConfigVariableInfo fb_config;
+  display_intf_->GetFrameBufferConfig(&fb_config);
+
+  *x_pixels = fb_config.x_pixels;
+  *y_pixels = fb_config.y_pixels;
 }
 
-void HWCDisplay::ScaleDisplayFrame(hwc_rect_t *display_frame) {
-  if (!IsFrameBufferScaled()) {
-    return;
-  }
-
-  uint32_t active_config_index = 0;
-  display_intf_->GetActiveConfig(&active_config_index);
-  DisplayConfigVariableInfo active_config;
-  DisplayError error = display_intf_->GetConfig(active_config_index, &active_config);
-  if (error != kErrorNone) {
-    DLOGE("GetConfig variable info failed. Error = %d", error);
-    return;
-  }
-
-  float custom_x_pixels = FLOAT(framebuffer_config_->x_pixels);
-  float custom_y_pixels = FLOAT(framebuffer_config_->y_pixels);
-  float active_x_pixels = FLOAT(active_config.x_pixels);
-  float active_y_pixels = FLOAT(active_config.y_pixels);
-  float x_pixels_ratio = active_x_pixels / custom_x_pixels;
-  float y_pixels_ratio = active_y_pixels / custom_y_pixels;
-  float layer_width = FLOAT(display_frame->right - display_frame->left);
-  float layer_height = FLOAT(display_frame->bottom - display_frame->top);
-
-  display_frame->left = INT(x_pixels_ratio * FLOAT(display_frame->left));
-  display_frame->top = INT(y_pixels_ratio * FLOAT(display_frame->top));
-  display_frame->right = INT(FLOAT(display_frame->left) + layer_width * x_pixels_ratio);
-  display_frame->bottom = INT(FLOAT(display_frame->top) + layer_height * y_pixels_ratio);
+DisplayError HWCDisplay::GetMixerResolution(uint32_t *x_pixels, uint32_t *y_pixels) {
+  return display_intf_->GetMixerResolution(x_pixels, y_pixels);
 }
 
-bool HWCDisplay::IsFrameBufferScaled() {
-  if (framebuffer_config_->x_pixels == 0 || framebuffer_config_->y_pixels == 0) {
-    return false;
-  }
-  uint32_t panel_x_pixels = 0;
-  uint32_t panel_y_pixels = 0;
-  GetPanelResolution(&panel_x_pixels, &panel_y_pixels);
-  return (framebuffer_config_->x_pixels != panel_x_pixels) ||
-          (framebuffer_config_->y_pixels != panel_y_pixels);
-}
 
 void HWCDisplay::GetPanelResolution(uint32_t *x_pixels, uint32_t *y_pixels) {
-  DisplayConfigVariableInfo active_config;
-  uint32_t active_config_index = 0;
-  display_intf_->GetActiveConfig(&active_config_index);
-  DisplayError error = display_intf_->GetConfig(active_config_index, &active_config);
-  if (error != kErrorNone) {
-    DLOGE("GetConfig variable info failed. Error = %d", error);
-    return;
-  }
-  *x_pixels = active_config.x_pixels;
-  *y_pixels = active_config.y_pixels;
+  DisplayConfigVariableInfo display_config;
+  uint32_t active_index = 0;
+
+  display_intf_->GetActiveConfig(&active_index);
+  display_intf_->GetConfig(active_index, &display_config);
+
+  *x_pixels = display_config.x_pixels;
+  *y_pixels = display_config.y_pixels;
 }
 
 int HWCDisplay::SetDisplayStatus(uint32_t display_status) {
@@ -1365,8 +1296,9 @@
   return display_intf_->GetNumVariableInfoConfigs(count) == kErrorNone ? 0 : -1;
 }
 
-int HWCDisplay::GetDisplayAttributesForConfig(int config, DisplayConfigVariableInfo *attributes) {
-  return display_intf_->GetConfig(UINT32(config), attributes) == kErrorNone ? 0 : -1;
+int HWCDisplay::GetDisplayAttributesForConfig(int config,
+                                            DisplayConfigVariableInfo *display_attributes) {
+  return display_intf_->GetConfig(UINT32(config), display_attributes) == kErrorNone ? 0 : -1;
 }
 
 // TODO(user): HWC needs to know updating for dyn_fps, cpu hint features,
diff --git a/msm8996/sdm/libs/hwc/hwc_display.h b/msm8996/sdm/libs/hwc/hwc_display.h
index 8bc7a91..1dfface 100644
--- a/msm8996/sdm/libs/hwc/hwc_display.h
+++ b/msm8996/sdm/libs/hwc/hwc_display.h
@@ -59,23 +59,28 @@
 
   // Framebuffer configurations
   virtual int GetDisplayConfigs(uint32_t *configs, size_t *num_configs);
-  virtual int GetDisplayAttributes(uint32_t config, const uint32_t *attributes, int32_t *values);
+  virtual int GetDisplayAttributes(uint32_t config, const uint32_t *display_attributes,
+                                   int32_t *values);
   virtual int GetActiveConfig();
   virtual int SetActiveConfig(int index);
 
   virtual void SetIdleTimeoutMs(uint32_t timeout_ms);
   virtual void SetFrameDumpConfig(uint32_t count, uint32_t bit_mask_layer_type);
   virtual DisplayError SetMaxMixerStages(uint32_t max_mixer_stages);
-  virtual DisplayError ControlPartialUpdate(bool enable, uint32_t *pending);
+  virtual DisplayError ControlPartialUpdate(bool enable, uint32_t *pending) {
+    return kErrorNotSupported;
+  }
   virtual uint32_t GetLastPowerMode();
   virtual int SetFrameBufferResolution(uint32_t x_pixels, uint32_t y_pixels);
   virtual void GetFrameBufferResolution(uint32_t *x_pixels, uint32_t *y_pixels);
-  virtual void GetPanelResolution(uint32_t *x_pixels, uint32_t *y_pixels);
   virtual int SetDisplayStatus(uint32_t display_status);
   virtual int OnMinHdcpEncryptionLevelChange(uint32_t min_enc_level);
   virtual int Perform(uint32_t operation, ...);
   virtual int SetCursorPosition(int x, int y);
   virtual void SetSecureDisplay(bool secure_display_active);
+  virtual DisplayError SetMixerResolution(uint32_t width, uint32_t height);
+  virtual DisplayError GetMixerResolution(uint32_t *width, uint32_t *height);
+  virtual void GetPanelResolution(uint32_t *width, uint32_t *height);
 
   // Captures frame output in the buffer specified by output_buffer_info. The API is
   // non-blocking and the client is expected to check operation status later on.
@@ -93,7 +98,8 @@
   virtual int SetActiveDisplayConfig(int config);
   virtual int GetActiveDisplayConfig(uint32_t *config);
   virtual int GetDisplayConfigCount(uint32_t *count);
-  virtual int GetDisplayAttributesForConfig(int config, DisplayConfigVariableInfo *attributes);
+  virtual int GetDisplayAttributesForConfig(int config,
+                                            DisplayConfigVariableInfo *display_attributes);
 
   int SetPanelBrightness(int level);
   int GetPanelBrightness(int *level);
@@ -136,6 +142,9 @@
   virtual uint32_t RoundToStandardFPS(float fps);
   virtual uint32_t SanitizeRefreshRate(uint32_t req_refresh_rate);
   virtual void PrepareDynamicRefreshRate(Layer *layer);
+  virtual DisplayError DisablePartialUpdateOneFrame() {
+    return kErrorNotSupported;
+  }
   inline void SetRect(const hwc_rect_t &source, LayerRect *target);
   inline void SetRect(const hwc_frect_t &source, LayerRect *target);
   inline void SetComposition(const int32_t &source, LayerComposition *target);
@@ -145,7 +154,6 @@
   LayerBufferFormat GetSDMFormat(const int32_t &source, const int flags);
   const char *GetHALPixelFormatString(int format);
   const char *GetDisplayString();
-  void ScaleDisplayFrame(hwc_rect_t *display_frame);
   void MarkLayersForGPUBypass(hwc_display_contents_1_t *content_list);
   virtual void ApplyScanAdjustment(hwc_rect_t *display_frame);
   DisplayError SetCSC(ColorSpace_t source, LayerCSC *target);
@@ -176,7 +184,6 @@
   bool dump_input_layers_ = false;
   uint32_t last_power_mode_;
   bool swap_interval_zero_ = false;
-  DisplayConfigVariableInfo *framebuffer_config_ = NULL;
   bool display_paused_ = false;
   uint32_t min_refresh_rate_ = 0;
   uint32_t max_refresh_rate_ = 0;
@@ -196,7 +203,6 @@
   bool animating_ = false;
 
  private:
-  bool IsFrameBufferScaled();
   void DumpInputBuffers(hwc_display_contents_1_t *content_list);
   int PrepareLayerParams(hwc_layer_1_t *hwc_layer, Layer *layer);
   void CommitLayerParams(hwc_layer_1_t *hwc_layer, Layer *layer);
diff --git a/msm8996/sdm/libs/hwc/hwc_display_external.cpp b/msm8996/sdm/libs/hwc/hwc_display_external.cpp
index a647517..ad8690c 100644
--- a/msm8996/sdm/libs/hwc/hwc_display_external.cpp
+++ b/msm8996/sdm/libs/hwc/hwc_display_external.cpp
@@ -50,6 +50,7 @@
   uint32_t external_width = 0;
   uint32_t external_height = 0;
   int drc_enabled = 0;
+  DisplayError error = kErrorNone;
 
   HWCDisplay *hwc_display_external = new HWCDisplayExternal(core_intf, hwc_procs, qservice);
   int status = hwc_display_external->Init();
@@ -58,7 +59,10 @@
     return status;
   }
 
-  hwc_display_external->GetPanelResolution(&external_width, &external_height);
+  error = hwc_display_external->GetMixerResolution(&external_width, &external_height);
+  if (error != kErrorNone) {
+    return -EINVAL;
+  }
 
   if (primary_width && primary_height) {
     // use_primary_res means HWCDisplayExternal should directly set framebuffer resolution to the
@@ -180,28 +184,28 @@
     return;
   }
 
-  uint32_t panel_width = 0;
-  uint32_t panel_height = 0;
-  GetPanelResolution(&panel_width, &panel_height);
+  uint32_t mixer_width = 0;
+  uint32_t mixer_height = 0;
+  GetMixerResolution(&mixer_width, &mixer_height);
 
-  if (panel_width == 0 || panel_height == 0) {
-    DLOGV("Invalid panel dimensions (%d, %d)", panel_width, panel_height);
+  if (mixer_width == 0 || mixer_height == 0) {
+    DLOGV("Invalid mixer dimensions (%d, %d)", mixer_width, mixer_height);
     return;
   }
 
-  uint32_t new_panel_width = UINT32(panel_width * FLOAT(1.0f - width_ratio));
-  uint32_t new_panel_height = UINT32(panel_height * FLOAT(1.0f - height_ratio));
+  uint32_t new_mixer_width = UINT32(mixer_width * FLOAT(1.0f - width_ratio));
+  uint32_t new_mixer_height = UINT32(mixer_height * FLOAT(1.0f - height_ratio));
 
-  int x_offset = INT((FLOAT(panel_width) * width_ratio) / 2.0f);
-  int y_offset = INT((FLOAT(panel_height) * height_ratio) / 2.0f);
+  int x_offset = INT((FLOAT(mixer_width) * width_ratio) / 2.0f);
+  int y_offset = INT((FLOAT(mixer_height) * height_ratio) / 2.0f);
 
-  display_frame->left = (display_frame->left * INT32(new_panel_width) / INT32(panel_width))
+  display_frame->left = (display_frame->left * INT32(new_mixer_width) / INT32(mixer_width))
                         + x_offset;
-  display_frame->top = (display_frame->top * INT32(new_panel_height) / INT32(panel_height)) +
+  display_frame->top = (display_frame->top * INT32(new_mixer_height) / INT32(mixer_height)) +
                        y_offset;
-  display_frame->right = ((display_frame->right * INT32(new_panel_width)) / INT32(panel_width)) +
+  display_frame->right = ((display_frame->right * INT32(new_mixer_width)) / INT32(mixer_width)) +
                          x_offset;
-  display_frame->bottom = ((display_frame->bottom * INT32(new_panel_height)) / INT32(panel_height))
+  display_frame->bottom = ((display_frame->bottom * INT32(new_mixer_height)) / INT32(mixer_height))
                           + y_offset;
 }
 
diff --git a/msm8996/sdm/libs/hwc/hwc_display_null.cpp b/msm8996/sdm/libs/hwc/hwc_display_null.cpp
index 11cf47a..649f40c 100644
--- a/msm8996/sdm/libs/hwc/hwc_display_null.cpp
+++ b/msm8996/sdm/libs/hwc/hwc_display_null.cpp
@@ -97,12 +97,12 @@
 
 #define NULL_DISPLAY_FPS 60
 
-int HWCDisplayNull::GetDisplayAttributes(uint32_t config, const uint32_t *attributes,
+int HWCDisplayNull::GetDisplayAttributes(uint32_t config, const uint32_t *display_attributes,
                                          int32_t *values) {
-  for (int i = 0; attributes[i] != HWC_DISPLAY_NO_ATTRIBUTE; i++) {
+  for (int i = 0; display_attributes[i] != HWC_DISPLAY_NO_ATTRIBUTE; i++) {
     // We fake display resolution as 1080P by default, though it can be overriden through a call to
     // SetResolution(), and DPI as 160, though what the DPI value does is not clear
-    switch (attributes[i]) {
+    switch (display_attributes[i]) {
     case HWC_DISPLAY_VSYNC_PERIOD:
       values[i] = INT32(1000000000L / NULL_DISPLAY_FPS);
       break;
diff --git a/msm8996/sdm/libs/hwc/hwc_display_null.h b/msm8996/sdm/libs/hwc/hwc_display_null.h
index 2f6438a..297e870 100644
--- a/msm8996/sdm/libs/hwc/hwc_display_null.h
+++ b/msm8996/sdm/libs/hwc/hwc_display_null.h
@@ -48,7 +48,8 @@
     return HWCDisplay::GetDisplayConfigs(configs, num_configs);
   }
 
-  virtual int GetDisplayAttributes(uint32_t config, const uint32_t *attributes, int32_t *values);
+  virtual int GetDisplayAttributes(uint32_t config, const uint32_t *display_attributes,
+                                   int32_t *values);
   virtual int GetActiveConfig() { return 0; }
   virtual int SetActiveConfig(int index) { return -1; }
 
@@ -79,7 +80,8 @@
   virtual int SetActiveDisplayConfig(int config) { return 0; }
   virtual int GetActiveDisplayConfig(uint32_t *config) { return -1; }
   virtual int GetDisplayConfigCount(uint32_t *count) { return -1; }
-  virtual int GetDisplayAttributesForConfig(int config, DisplayConfigVariableInfo *attributes) {
+  virtual int GetDisplayAttributesForConfig(int config,
+                                            DisplayConfigVariableInfo *display_attributes) {
     return -1;
   }
   virtual bool IsValidContentList(hwc_display_contents_1_t *content_list) {
diff --git a/msm8996/sdm/libs/hwc/hwc_display_primary.cpp b/msm8996/sdm/libs/hwc/hwc_display_primary.cpp
index 32ff73b..f92ab43 100644
--- a/msm8996/sdm/libs/hwc/hwc_display_primary.cpp
+++ b/msm8996/sdm/libs/hwc/hwc_display_primary.cpp
@@ -56,7 +56,7 @@
     return status;
   }
 
-  hwc_display_primary->GetPanelResolution(&primary_width, &primary_height);
+  hwc_display_primary->GetMixerResolution(&primary_width, &primary_height);
   int width = 0, height = 0;
   HWCDebugHandler::Get()->GetProperty("sdm.fb_size_width", &width);
   HWCDebugHandler::Get()->GetProperty("sdm.fb_size_height", &height);
@@ -382,9 +382,6 @@
   frame_capture_buffer_queued_ = false;
   post_processed_output_ = false;
   output_buffer_ = {};
-
-  uint32_t pending = 0;  // Just a temporary to satisfy the API
-  ControlPartialUpdate(true  /* enable */, &pending);
 }
 
 void HWCDisplayPrimary::HandleFrameDump() {
@@ -413,9 +410,6 @@
     output_buffer_ = {};
     output_buffer_info_ = {};
     output_buffer_base_ = nullptr;
-
-    uint32_t pending = 0;  // Just a temporary to satisfy the API
-    ControlPartialUpdate(true  /* enable */, &pending);
   }
 }
 
@@ -454,8 +448,7 @@
 
   output_buffer_base_ = buffer;
   post_processed_output_ = true;
-  uint32_t pending = 0;  // Just a temporary to satisfy the API
-  ControlPartialUpdate(false  /* enable */, &pending);
+  DisablePartialUpdateOneFrame();
 }
 
 int HWCDisplayPrimary::FrameCaptureAsync(const BufferInfo& output_buffer_info,
@@ -489,12 +482,38 @@
   frame_capture_buffer_queued_ = true;
   // Status is only cleared on a new call to dump and remains valid otherwise
   frame_capture_status_ = -EAGAIN;
-
-  uint32_t pending = 0;  // Just a temporary to satisfy the API
-  ControlPartialUpdate(false  /* enable */, &pending);
+  DisablePartialUpdateOneFrame();
 
   return 0;
 }
 
+DisplayError HWCDisplayPrimary::ControlPartialUpdate(bool enable, uint32_t *pending) {
+  DisplayError error = kErrorNone;
+
+  if (display_intf_) {
+    error = display_intf_->ControlPartialUpdate(enable, pending);
+  }
+
+  return error;
+}
+
+DisplayError HWCDisplayPrimary::DisablePartialUpdateOneFrame() {
+  DisplayError error = kErrorNone;
+
+  if (display_intf_) {
+    error = display_intf_->DisablePartialUpdateOneFrame();
+  }
+
+  return error;
+}
+
+DisplayError HWCDisplayPrimary::SetMixerResolution(uint32_t width, uint32_t height) {
+  return display_intf_->SetMixerResolution(width, height);
+}
+
+DisplayError HWCDisplayPrimary::GetMixerResolution(uint32_t *width, uint32_t *height) {
+  return display_intf_->GetMixerResolution(width, height);
+}
+
 }  // namespace sdm
 
diff --git a/msm8996/sdm/libs/hwc/hwc_display_primary.h b/msm8996/sdm/libs/hwc/hwc_display_primary.h
index 8c02731..81e510f 100644
--- a/msm8996/sdm/libs/hwc/hwc_display_primary.h
+++ b/msm8996/sdm/libs/hwc/hwc_display_primary.h
@@ -54,12 +54,14 @@
   virtual void SetFrameDumpConfig(uint32_t count, uint32_t bit_mask_layer_type);
   virtual int FrameCaptureAsync(const BufferInfo& output_buffer_info, bool post_processed);
   virtual int GetFrameCaptureStatus() { return frame_capture_status_; }
+  virtual DisplayError ControlPartialUpdate(bool enable, uint32_t *pending);
 
  private:
   HWCDisplayPrimary(CoreInterface *core_intf, BufferAllocator *buffer_allocator,
                     hwc_procs_t const **hwc_procs, qService::QService *qservice);
   void SetMetaDataRefreshRateFlag(bool enable);
   virtual DisplayError SetDisplayMode(uint32_t mode);
+  virtual DisplayError DisablePartialUpdateOneFrame();
   void ProcessBootAnimCompleted(hwc_display_contents_1_t *content_list);
   void SetQDCMSolidFillInfo(bool enable, uint32_t color);
   void ToggleCPUHint(bool set);
@@ -68,6 +70,8 @@
   void HandleFrameOutput();
   void HandleFrameCapture();
   void HandleFrameDump();
+  DisplayError SetMixerResolution(uint32_t width, uint32_t height);
+  DisplayError GetMixerResolution(uint32_t *width, uint32_t *height);
 
   BufferAllocator *buffer_allocator_ = nullptr;
   CPUHint *cpu_hint_ = nullptr;
diff --git a/msm8996/sdm/libs/hwc/hwc_display_virtual.cpp b/msm8996/sdm/libs/hwc/hwc_display_virtual.cpp
index ef7198c..1363839 100644
--- a/msm8996/sdm/libs/hwc/hwc_display_virtual.cpp
+++ b/msm8996/sdm/libs/hwc/hwc_display_virtual.cpp
@@ -67,7 +67,7 @@
     return status;
   }
 
-  hwc_display_virtual->GetPanelResolution(&virtual_width, &virtual_height);
+  hwc_display_virtual->GetMixerResolution(&virtual_width, &virtual_height);
 
   if (content_list->numHwLayers < 1) {
     Destroy(hwc_display_virtual);
diff --git a/msm8996/sdm/libs/hwc/hwc_session.cpp b/msm8996/sdm/libs/hwc/hwc_session.cpp
index 63bde5c..8d12aee 100644
--- a/msm8996/sdm/libs/hwc/hwc_session.cpp
+++ b/msm8996/sdm/libs/hwc/hwc_session.cpp
@@ -555,10 +555,10 @@
 }
 
 int HWCSession::GetDisplayAttributes(hwc_composer_device_1 *device, int disp, uint32_t config,
-                                     const uint32_t *attributes, int32_t *values) {
+                                     const uint32_t *display_attributes, int32_t *values) {
   SCOPE_LOCK(locker_);
 
-  if (!device || !attributes || !values) {
+  if (!device || !display_attributes || !values) {
     return -EINVAL;
   }
 
@@ -569,7 +569,8 @@
   HWCSession *hwc_session = static_cast<HWCSession *>(device);
   int status = -EINVAL;
   if (hwc_session->hwc_display_[disp]) {
-    status = hwc_session->hwc_display_[disp]->GetDisplayAttributes(config, attributes, values);
+    status = hwc_session->hwc_display_[disp]->GetDisplayAttributes(config, display_attributes,
+                                                                   values);
   }
 
   return status;
@@ -775,6 +776,10 @@
     status = GetBWTransactionStatus(input_parcel, output_parcel);
     break;
 
+  case qService::IQService::SET_LAYER_MIXER_RESOLUTION:
+    status = SetMixerResolution(input_parcel);
+    break;
+
   default:
     DLOGW("QService command = %d is not supported", command);
     return -EINVAL;
@@ -947,22 +952,22 @@
   int config = input_parcel->readInt32();
   int dpy = input_parcel->readInt32();
   int error = android::BAD_VALUE;
-  DisplayConfigVariableInfo attributes;
+  DisplayConfigVariableInfo display_attributes;
 
   if (dpy > HWC_DISPLAY_VIRTUAL) {
     return android::BAD_VALUE;
   }
 
   if (hwc_display_[dpy]) {
-    error = hwc_display_[dpy]->GetDisplayAttributesForConfig(config, &attributes);
+    error = hwc_display_[dpy]->GetDisplayAttributesForConfig(config, &display_attributes);
     if (error == 0) {
-      output_parcel->writeInt32(INT(attributes.vsync_period_ns));
-      output_parcel->writeInt32(INT(attributes.x_pixels));
-      output_parcel->writeInt32(INT(attributes.y_pixels));
-      output_parcel->writeFloat(attributes.x_dpi);
-      output_parcel->writeFloat(attributes.y_dpi);
+      output_parcel->writeInt32(INT(display_attributes.vsync_period_ns));
+      output_parcel->writeInt32(INT(display_attributes.x_pixels));
+      output_parcel->writeInt32(INT(display_attributes.y_pixels));
+      output_parcel->writeFloat(display_attributes.x_dpi);
+      output_parcel->writeFloat(display_attributes.y_dpi);
       output_parcel->writeInt32(0);  // Panel type, unsupported.
-      output_parcel->writeInt32(attributes.is_yuv);
+      output_parcel->writeInt32(display_attributes.is_yuv);
     }
   }
 
@@ -1116,6 +1121,31 @@
   }
 }
 
+android::status_t HWCSession::SetMixerResolution(const android::Parcel *input_parcel) {
+  DisplayError error = kErrorNone;
+  uint32_t dpy = UINT32(input_parcel->readInt32());
+
+  if (dpy != HWC_DISPLAY_PRIMARY) {
+    DLOGI("Resoulution change not supported for this display %d", dpy);
+    return -EINVAL;
+  }
+
+  if (!hwc_display_[HWC_DISPLAY_PRIMARY]) {
+    DLOGI("Primary display is not initialized");
+    return -EINVAL;
+  }
+
+  uint32_t width = UINT32(input_parcel->readInt32());
+  uint32_t height = UINT32(input_parcel->readInt32());
+
+  error = hwc_display_[HWC_DISPLAY_PRIMARY]->SetMixerResolution(width, height);
+  if (error != kErrorNone) {
+    return -EINVAL;
+  }
+
+  return 0;
+}
+
 void HWCSession::DynamicDebug(const android::Parcel *input_parcel) {
   int type = input_parcel->readInt32();
   bool enable = (input_parcel->readInt32() > 0);
diff --git a/msm8996/sdm/libs/hwc/hwc_session.h b/msm8996/sdm/libs/hwc/hwc_session.h
index efcafcf..2bdae2b 100644
--- a/msm8996/sdm/libs/hwc/hwc_session.h
+++ b/msm8996/sdm/libs/hwc/hwc_session.h
@@ -68,7 +68,7 @@
   static int GetDisplayConfigs(hwc_composer_device_1 *device, int disp, uint32_t *configs,
                                size_t *numConfigs);
   static int GetDisplayAttributes(hwc_composer_device_1 *device, int disp, uint32_t config,
-                                  const uint32_t *attributes, int32_t *values);
+                                  const uint32_t *display_attributes, int32_t *values);
   static int GetActiveConfig(hwc_composer_device_1 *device, int disp);
   static int SetActiveConfig(hwc_composer_device_1 *device, int disp, int index);
   static int SetCursorPositionAsync(hwc_composer_device_1 *device, int disp, int x, int y);
@@ -123,6 +123,8 @@
                                           android::Parcel *output_parcel);
   android::status_t GetBWTransactionStatus(const android::Parcel *input_parcel,
                                           android::Parcel *output_parcel);
+  android::status_t SetMixerResolution(const android::Parcel *input_parcel);
+
   static Locker locker_;
   CoreInterface *core_intf_ = NULL;
   hwc_procs_t hwc_procs_default_;
diff --git a/msm8996/sdm/libs/utils/rect.cpp b/msm8996/sdm/libs/utils/rect.cpp
index e756464..1872df2 100644
--- a/msm8996/sdm/libs/utils/rect.cpp
+++ b/msm8996/sdm/libs/utils/rect.cpp
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2015, The Linux Foundation. All rights reserved.
+* Copyright (c) 2015-2016, 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
@@ -198,5 +198,40 @@
   }
 }
 
+void ScaleRect(const LayerRect &src_domain, const LayerRect &dst_domain, const LayerRect &in_rect,
+               LayerRect *out_rect) {
+  if (!IsValid(src_domain) || !IsValid(dst_domain) || !IsValid(in_rect)) {
+    return;
+  }
+
+  float src_domain_width = src_domain.right - src_domain.left;
+  float src_domain_height = src_domain.bottom - src_domain.top;
+  float dst_domain_width = dst_domain.right - dst_domain.left;
+  float dst_domain_height = dst_domain.bottom - dst_domain.top;
+
+  float width_ratio = dst_domain_width / src_domain_width;
+  float height_ratio = dst_domain_height / src_domain_height;
+
+  out_rect->left = width_ratio * in_rect.left;
+  out_rect->top = height_ratio * in_rect.top;
+  out_rect->right = width_ratio * in_rect.right;
+  out_rect->bottom = height_ratio * in_rect.bottom;
+}
+
+RectOrientation GetOrientation(const LayerRect &in_rect) {
+  if (!IsValid(in_rect)) {
+    return kOrientationUnknown;
+  }
+
+  float input_width = in_rect.right - in_rect.left;
+  float input_height = in_rect.bottom - in_rect.top;
+
+  if (input_width < input_height) {
+    return kOrientationPortrait;
+  }
+
+  return kOrientationLandscape;
+}
+
 }  // namespace sdm