Merge "sdm: Fix the MIN and MAX downscale factors for Rotator"
diff --git a/Android.mk b/Android.mk
index b8b893c..60a48f5 100644
--- a/Android.mk
+++ b/Android.mk
@@ -1,5 +1,5 @@
 sdm-libs := sdm/libs
-display-hals := libqservice libqdutils $(sdm-libs)/utils $(sdm-libs)/core
+display-hals := include libqservice libqdutils $(sdm-libs)/utils $(sdm-libs)/core
 
 ifneq ($(TARGET_IS_HEADLESS), true)
     display-hals += libcopybit liblight libmemtrack hdmi_cec \
diff --git a/common.mk b/common.mk
index af72e7b..d44a664 100644
--- a/common.mk
+++ b/common.mk
@@ -5,6 +5,10 @@
 common_flags := -DDEBUG_CALC_FPS -Wno-missing-field-initializers
 common_flags += -Wconversion -Wall -Werror -std=c++11
 
+ifeq ($(call is-board-platform-in-list, msmcobalt msm8998), true)
+common_flags += -DUSE_COLOR_METADATA
+endif
+
 use_hwc2 := false
 ifeq ($(TARGET_USES_HWC2), true)
     use_hwc2 := true
@@ -17,6 +21,7 @@
     common_includes += $(display_top)/libcopybit
 endif
 
+common_includes += $(display_top)/include
 common_includes += $(display_top)/sdm/include
 
 common_header_export_path := qcom/display
diff --git a/include/Android.mk b/include/Android.mk
new file mode 100644
index 0000000..4d0d9f7
--- /dev/null
+++ b/include/Android.mk
@@ -0,0 +1,9 @@
+LOCAL_PATH:= $(call my-dir)
+include $(LOCAL_PATH)/../common.mk
+include $(CLEAR_VARS)
+
+LOCAL_COPY_HEADERS_TO         := $(common_header_export_path)
+LOCAL_COPY_HEADERS            := color_metadata.h
+
+include $(BUILD_COPY_HEADERS)
+
diff --git a/include/color_metadata.h b/include/color_metadata.h
new file mode 100644
index 0000000..328cb0e
--- /dev/null
+++ b/include/color_metadata.h
@@ -0,0 +1,180 @@
+/*
+* Copyright (c) 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:
+*    * Redistributions of source code must retain the above copyright notice, this list of
+*      conditions and the following disclaimer.
+*    * Redistributions in binary form must reproduce the above copyright notice, this list of
+*      conditions and the following disclaimer in the documentation and/or other materials provided
+*      with the distribution.
+*    * Neither the name of The Linux Foundation nor the names of its contributors may be used to
+*      endorse or promote products derived from this software without specific prior written
+*      permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef __COLOR_METADATA_H__
+#define __COLOR_METADATA_H__
+
+#ifdef __cplusplus
+extern "C" {
+#else
+#include <stdbool.h>
+#endif
+
+typedef enum ColorRange {
+  Range_Limited = 0,
+  Range_Full    = 1,
+  Range_Max     = 0xff,
+} ColorRange;
+
+// The following values matches the HEVC spec
+typedef enum ColorPrimaries {
+  // Unused = 0;
+  ColorPrimaries_BT709_5     = 1,  // ITU-R BT.709-5 or equivalent
+  /* Unspecified = 2, Reserved = 3*/
+  ColorPrimaries_BT470_6M    = 4,  // ITU-R BT.470-6 System M or equivalent
+  ColorPrimaries_BT601_6_625 = 5,  // ITU-R BT.601-6 625 or equivalent
+  ColorPrimaries_BT601_6_525 = 6,  // ITU-R BT.601-6 525 or equivalent
+  ColorPrimaries_SMPTE_240M  = 7,  // SMPTE_240M
+  ColorPrimaries_GenericFilm = 8,  // Generic Film
+  ColorPrimaries_BT2020      = 9,  // ITU-R BT.2020 or equivalent
+  ColorPrimaries_SMPTE_ST428 = 10,  // SMPTE_240M
+  ColorPrimaries_AdobeRGB    = 11,
+  ColorPrimaries_DCIP3       = 12,
+  ColorPrimaries_Max         = 0xff,
+} ColorPrimaries;
+
+typedef enum GammaTransfer {
+  // Unused = 0;
+  Transfer_sRGB            = 1,  // ITR-BT.709-5
+  /* Unspecified = 2, Reserved = 3 */
+  Transfer_Gamma2_2        = 4,
+  Transfer_Gamma2_8        = 5,
+  Transfer_SMPTE_170M      = 6,  // BT.601-6 525 or 625
+  Transfer_SMPTE_240M      = 7,  // SMPTE_240M
+  Transfer_Linear          = 8,
+  Transfer_HLG             = 9,
+  Transfer_XvYCC           = 11,  // IEC 61966-2-4
+  Transfer_BT1361          = 12,  // Rec.ITU-R BT.1361 extended gamut
+  Transfer_SMPTE_ST2084    = 16,  // 2084
+  // transfers unlikely to be required by Android
+  Transfer_ST_428          = 17,  // SMPTE ST 428-1
+  Transfer_Max             = 0xff,
+} GammaTransfer;
+
+typedef enum MatrixCoEfficients {
+  MatrixCoEff_Identity           = 0,
+  MatrixCoEff_BT709_5            = 1,
+  /* Unspecified = 2, Reserved = 3 */
+  MatrixCoEff_BT601_6_625        = 5,
+  MatrixCoEff_BT601_6_525        = 6,
+  MatrixCoEff_SMPTE240M          = 7,  // used with 601_525_Unadjusted
+  MatrixCoEff_BT2020             = 9,
+  MatrixCoEff_BT2020Constant     = 10,
+  MatrixCoEff_BT601_6_Unadjusted = 11,  // Used with BT601_625(KR=0.222, KB=0.071)
+  MatrixCoEff_DCIP3              = 12,
+  MatrixCoEff_Max                = 0xff,
+} MatrixCoEfficients;
+
+typedef struct Primaries {
+  uint32_t rgbPrimaries[3][2];  // unit 1/50000;
+  uint32_t whitePoint[2];  // unit 1/50000;
+} Primaries;
+
+typedef struct MasteringDisplay {
+  bool      colorVolumeSEIEnabled;
+  Primaries primaries;
+  uint32_t  maxDisplayLuminance;  // unit: cd/m^2.
+  uint32_t  minDisplayLuminance;  // unit: 1/10000 cd/m^2.
+} MasteringDisplay;
+
+typedef struct ContentLightLevel {
+  bool     lightLevelSEIEnabled;
+  uint32_t maxContentLightLevel;  // unit: cd/m^2.
+  uint32_t minPicAverageLightLevel;  // unit: 1/10000 cd/m^2.
+} ContentLightLevel;
+
+typedef struct ColorRemappingInfo {
+  bool               criEnabled;
+  uint32_t           crId;
+  uint32_t           crCancelFlag;
+  uint32_t           crPersistenceFlag;
+  uint32_t           crVideoSignalInfoPresentFlag;
+  uint32_t           crRange;
+  ColorPrimaries     crPrimaries;
+  GammaTransfer      crTransferFunction;
+  MatrixCoEfficients crMatrixCoefficients;
+  uint32_t           crInputBitDepth;
+  uint32_t           crOutputBitDepth;
+  uint32_t           crPreLutNumValMinusOne[3];
+  uint32_t           crPreLutCodedValue[3*33];
+  uint32_t           crPreLutTargetValue[3*33];
+  uint32_t           crMatrixPresentFlag;
+  uint32_t           crLog2MatrixDenom;
+  int32_t            crCoefficients[3*3];
+  uint32_t           crPostLutNumValMinusOne[3];
+  uint32_t           crPostLutCodedValue[3*33];
+  uint32_t           crPostLutTargetValue[3*33];
+} ColorRemappingInfo;
+
+typedef struct ColorMetaData {
+  // Default values based on sRGB, needs to be overridden in gralloc
+  // based on the format and size.
+  ColorPrimaries     colorPrimaries;
+  ColorRange         range;
+  GammaTransfer      transfer;
+  MatrixCoEfficients matrixCoefficients;
+
+  MasteringDisplay   masteringDisplayInfo;
+  ContentLightLevel  contentLightLevel;
+  ColorRemappingInfo cRI;
+} ColorMetaData;
+
+typedef struct Color10Bit {
+  uint32_t R: 10;
+  uint32_t G: 10;
+  uint32_t B: 10;
+  uint32_t A: 2;
+} Color10Bit;
+
+typedef struct Lut3d {
+  uint16_t dim;  // dimension of each side of LUT cube (ex: 13, 17)in lutEntries
+  uint16_t gridSize;  // number of elements in the gridEntries
+  /* Matrix ordering convension
+  for (b = 0; b < dim; b++) {
+    for (g = 0; g < dim; g++) {
+      for (r = 0; r < dim; r++) {
+        read/write [mR mG mB] associated w/ 3DLUT[r][g][b] to/from file
+      }
+    }
+  } */
+  Color10Bit *lutEntries;
+  bool validLutEntries;  // Indicates if entries are valid and can be used.
+  /*
+   The grid is a 1D LUT for each of the R,G,B channels that can be
+   used to apply an independent nonlinear transformation to each
+   channel before it is used as a coordinate for addressing
+   the uniform 3D LUT.  This effectively creates a non-uniformly
+   sampled 3D LUT.  This is useful for having independent control
+   of the sampling grid density along each dimension for greater
+   precision in spite of having a relatively small number of samples.i
+  */
+  Color10Bit *gridEntries;
+  bool validGridEntries;  // Indicates if entries are valid and can be used.
+} Lut3d;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif  // __COLOR_METADATA_H__
diff --git a/libgralloc/mapper.cpp b/libgralloc/mapper.cpp
index 15bb71a..132c768 100644
--- a/libgralloc/mapper.cpp
+++ b/libgralloc/mapper.cpp
@@ -412,7 +412,30 @@
                     return res;
                 }
                 MetaData_t *metadata = (MetaData_t *)hnd->base_metadata;
-                if(metadata && metadata->operation & UPDATE_COLOR_SPACE) {
+                if (!metadata) {
+                    break;
+#ifdef USE_COLOR_METADATA
+                } else if (metadata->operation & COLOR_METADATA) {
+                    ColorMetaData *colorMetadata = &metadata->color;
+                    res = 0;
+                    switch (colorMetadata->colorPrimaries) {
+                    case ColorPrimaries_BT709_5:
+                        *color_space = HAL_CSC_ITU_R_709;
+                        break;
+                    case ColorPrimaries_BT601_6_525:
+                        *color_space = ((colorMetadata->range) ?
+                                        HAL_CSC_ITU_R_601_FR : HAL_CSC_ITU_R_601);
+                        break;
+                    case ColorPrimaries_BT2020:
+                        *color_space = (colorMetadata->range) ?
+                            HAL_CSC_ITU_R_2020_FR : HAL_CSC_ITU_R_2020;
+                        break;
+                    default:
+                        res = -EINVAL;
+                        break;
+                    }
+#endif
+                } else if(metadata->operation & UPDATE_COLOR_SPACE) {
                     *color_space = metadata->colorSpace;
                     res = 0;
                 }
diff --git a/libgralloc1/gr_buf_mgr.cpp b/libgralloc1/gr_buf_mgr.cpp
index 6c36345..9650583 100644
--- a/libgralloc1/gr_buf_mgr.cpp
+++ b/libgralloc1/gr_buf_mgr.cpp
@@ -588,7 +588,27 @@
         return GRALLOC1_ERROR_BAD_HANDLE;
       }
       MetaData_t *metadata = reinterpret_cast<MetaData_t *>(hnd->base_metadata);
-      if (metadata && metadata->operation & UPDATE_COLOR_SPACE) {
+      if (!metadata) {
+        return GRALLOC1_ERROR_BAD_HANDLE;
+#ifdef USE_COLOR_METADATA
+      } else if (metadata->operation & COLOR_METADATA) {
+        ColorMetaData *colorMetadata = &metadata->color;
+        switch (colorMetadata->colorPrimaries) {
+        case ColorPrimaries_BT709_5:
+          *color_space = HAL_CSC_ITU_R_709;
+          break;
+        case ColorPrimaries_BT601_6_525:
+          *color_space = ((colorMetadata->range) ? HAL_CSC_ITU_R_601_FR : HAL_CSC_ITU_R_601);
+           break;
+        case ColorPrimaries_BT2020:
+          *color_space = (colorMetadata->range) ? HAL_CSC_ITU_R_2020_FR : HAL_CSC_ITU_R_2020;
+          break;
+        default:
+          ALOGE("Unknown Color Space = %d", colorMetadata->colorPrimaries);
+          break;
+        }
+#endif
+      } else if (metadata->operation & UPDATE_COLOR_SPACE) {
         *color_space = metadata->colorSpace;
       }
     } break;
diff --git a/libmemtrack/kgsl.c b/libmemtrack/kgsl.c
index 11c7e8a..9ec69f0 100644
--- a/libmemtrack/kgsl.c
+++ b/libmemtrack/kgsl.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2013 The Android Open Source Project
+ * Copyright (C) 2013, 2016 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -48,7 +48,6 @@
     FILE *fp;
     char line[1024];
     char tmp[128];
-    bool is_surfaceflinger = false;
     size_t accounted_size = 0;
     size_t unaccounted_size = 0;
 
@@ -59,16 +58,6 @@
         return 0;
     }
 
-    snprintf(tmp, sizeof(tmp), "/proc/%d/cmdline", pid);
-    fp = fopen(tmp, "r");
-    if (fp != NULL) {
-        if (fgets(line, sizeof(line), fp)) {
-            if (strcmp(line, "/system/bin/surfaceflinger") == 0)
-                is_surfaceflinger = true;
-        }
-        fclose(fp);
-    }
-
     memcpy(records, record_templates,
            sizeof(struct memtrack_record) * allocated_records);
 
@@ -87,19 +76,20 @@
         char line_type[7];
         char flags[9];
         char line_usage[19];
-        int ret;
+        int ret, egl_surface_count = 0, egl_image_count = 0;
 
         if (fgets(line, sizeof(line), fp) == NULL) {
             break;
         }
 
         /* Format:
-         *  gpuaddr useraddr     size    id flags       type            usage sglen mapsize
-         * 545ba000 545ba000     4096     1 -----pY     gpumem      arraybuffer     1  4096
+         *  gpuaddr useraddr     size    id flags       type            usage sglen mapsize eglsrf eglimg
+         * 545ba000 545ba000     4096     1 -----pY     gpumem      arraybuffer     1  4096      0      0
          */
-        ret = sscanf(line, "%*x %*x %lu %*d %8s %6s %18s %*d %lu\n",
-                     &size, flags, line_type, line_usage, &mapsize);
-        if (ret != 5) {
+        ret = sscanf(line, "%*x %*x %lu %*d %8s %6s %18s %*d %lu %6d %6d\n",
+			&size, flags, line_type, line_usage, &mapsize,
+			&egl_surface_count, &egl_image_count);
+        if (ret != 7) {
             continue;
         }
 
@@ -112,9 +102,10 @@
                 unaccounted_size += size;
 
         } else if (type == MEMTRACK_TYPE_GRAPHICS && strcmp(line_type, "ion") == 0) {
-            if ( !(is_surfaceflinger == false && strcmp(line_usage, "egl_surface") == 0)) {
+            if (strcmp(line_usage, "egl_surface") == 0)
                 unaccounted_size += size;
-            }
+            else if (egl_surface_count == 0)
+		unaccounted_size += size / (egl_image_count ? egl_image_count : 1);
         }
     }
 
diff --git a/libqdutils/qdMetaData.cpp b/libqdutils/qdMetaData.cpp
index f62653a..c888baa 100644
--- a/libqdutils/qdMetaData.cpp
+++ b/libqdutils/qdMetaData.cpp
@@ -95,6 +95,11 @@
         case SET_VT_TIMESTAMP:
             data->vtTimeStamp = *((uint64_t *)param);
             break;
+#ifdef USE_COLOR_METADATA
+        case COLOR_METADATA:
+            data->color = *((ColorMetaData *)param);
+#endif
+            break;
         default:
             ALOGE("Unknown paramType %d", paramType);
             break;
@@ -196,6 +201,11 @@
         case GET_VT_TIMESTAMP:
             *((uint64_t *)param) = data->vtTimeStamp;
             break;
+#ifdef USE_COLOR_METADATA
+        case GET_COLOR_METADATA:
+            *((ColorMetaData *)param) = data->color;
+#endif
+            break;
         default:
             ALOGE("Unknown paramType %d", paramType);
             break;
diff --git a/libqdutils/qdMetaData.h b/libqdutils/qdMetaData.h
index 2b0b8c6..a0ac324 100644
--- a/libqdutils/qdMetaData.h
+++ b/libqdutils/qdMetaData.h
@@ -30,6 +30,10 @@
 #ifndef _QDMETADATA_H
 #define _QDMETADATA_H
 
+#ifdef USE_COLOR_METADATA
+#include <color_metadata.h>
+#endif
+
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -91,11 +95,15 @@
 
     /* Set by camera to program the VT Timestamp */
     uint64_t vtTimeStamp;
+#ifdef USE_COLOR_METADATA
+    /* Color Aspects + HDR info */
+    ColorMetaData color;
+#endif
 };
 
 enum DispParamType {
     SET_VT_TIMESTAMP         = 0x0001,
-    UNUSED1                  = 0x0002,
+    COLOR_METADATA           = 0x0002,
     PP_PARAM_INTERLACED      = 0x0004,
     UNUSED2                  = 0x0008,
     UNUSED3                  = 0x0010,
@@ -114,6 +122,7 @@
 
 enum DispFetchParamType {
     GET_VT_TIMESTAMP         = 0x0001,
+    GET_COLOR_METADATA       = 0x0002,
     GET_PP_PARAM_INTERLACED  = 0x0004,
     GET_BUFFER_GEOMETRY      = 0x0080,
     GET_REFRESH_RATE         = 0x0100,
diff --git a/libqservice/IQService.h b/libqservice/IQService.h
index d25a06d..bf4343a 100644
--- a/libqservice/IQService.h
+++ b/libqservice/IQService.h
@@ -74,6 +74,7 @@
         GET_BW_TRANSACTION_STATUS = 32, //Client can query BW transaction status.
         SET_LAYER_MIXER_RESOLUTION = 33, // Enables client to set layer mixer resolution.
         SET_COLOR_MODE = 34, // Overrides the QDCM mode on the display
+        GET_HDR_CAPABILITIES = 35, // Get HDR capabilities for legacy HWC interface
         COMMAND_LIST_END = 400,
     };
 
diff --git a/sdm/include/private/color_params.h b/sdm/include/private/color_params.h
index fdd0c9e..d2f8094 100644
--- a/sdm/include/private/color_params.h
+++ b/sdm/include/private/color_params.h
@@ -238,6 +238,7 @@
 struct PPDETuningCfgData {
   uint32_t cfg_en = 0;
   PPDETuningCfg params;
+  bool cfg_pending = false;
 };
 
 struct SDEGamutCfg {
diff --git a/sdm/include/private/extension_interface.h b/sdm/include/private/extension_interface.h
index fc32616..baf18a1 100644
--- a/sdm/include/private/extension_interface.h
+++ b/sdm/include/private/extension_interface.h
@@ -58,8 +58,8 @@
                                            PartialUpdateInterface **interface) = 0;
   virtual DisplayError DestroyPartialUpdate(PartialUpdateInterface *interface) = 0;
 
-  virtual DisplayError CreateStrategyExtn(DisplayType type, HWDisplayMode mode,
-                                          HWS3DMode s3d_mode,
+  virtual DisplayError CreateStrategyExtn(DisplayType type, const HWResourceInfo &hw_resource_info,
+                                          const HWPanelInfo &hw_panel_info,
                                           const HWMixerAttributes &mixer_attributes,
                                           const DisplayConfigVariableInfo &fb_config,
                                           StrategyInterface **interface) = 0;
diff --git a/sdm/include/private/hw_info_types.h b/sdm/include/private/hw_info_types.h
index fd280fa..e6e8b6c 100644
--- a/sdm/include/private/hw_info_types.h
+++ b/sdm/include/private/hw_info_types.h
@@ -237,6 +237,8 @@
   char panel_name[256] = {0};         // Panel name
   HWS3DMode s3d_mode = kS3DModeNone;  // Panel's current s3d mode.
   int panel_max_brightness = 0;       // Max panel brightness
+  uint32_t left_roi_count = 1;        // Number if ROI supported on left panel
+  uint32_t right_roi_count = 1;       // Number if ROI supported on right panel
 
   bool operator !=(const HWPanelInfo &panel_info) {
     return ((port != panel_info.port) || (mode != panel_info.mode) ||
@@ -250,8 +252,9 @@
             (dfps_porch_mode != panel_info.dfps_porch_mode) ||
             (ping_pong_split != panel_info.ping_pong_split) ||
             (max_fps != panel_info.max_fps) || (is_primary_panel != panel_info.is_primary_panel) ||
-            (split_info != panel_info.split_info) ||
-            (s3d_mode != panel_info.s3d_mode));
+            (split_info != panel_info.split_info) || (s3d_mode != panel_info.s3d_mode) ||
+            (left_roi_count != panel_info.left_roi_count) ||
+            (right_roi_count != panel_info.right_roi_count));
   }
 
   bool operator ==(const HWPanelInfo &panel_info) {
@@ -432,13 +435,16 @@
   LayerRect updated_src_rect[kMaxSDELayers];  // Updated layer src rects in s3d mode
   LayerRect updated_dst_rect[kMaxSDELayers];  // Updated layer dst rects in s3d mode
   bool updating[kMaxSDELayers] = {0};  // Updated by strategy, considering plane_alpha+updating
+  uint32_t roi_index[kMaxSDELayers] = {0};  // Stores the ROI index where the layers are visible.
 
   uint32_t count = 0;              // Total number of layers which need to be set on hardware.
 
   int sync_handle = -1;
 
-  LayerRect left_partial_update;   // Left ROI.
-  LayerRect right_partial_update;  // Right ROI.
+  std::vector<LayerRect> left_frame_roi;   // Left ROI.
+  std::vector<LayerRect> right_frame_roi;  // Right ROI.
+
+  bool roi_split = false;          // Indicates separated left and right ROI
 
   bool use_hw_cursor = false;      // Indicates that HWCursor pipe needs to be used for cursor layer
   DestScaleInfoMap dest_scale_info_map = {};
diff --git a/sdm/include/private/strategy_interface.h b/sdm/include/private/strategy_interface.h
index 188c540..122a3c6 100644
--- a/sdm/include/private/strategy_interface.h
+++ b/sdm/include/private/strategy_interface.h
@@ -48,7 +48,8 @@
   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,
+  virtual DisplayError Reconfigure(const HWPanelInfo &hw_panel_info,
+                                   const HWResourceInfo &hw_res_info,
                                    const HWMixerAttributes &mixer_attributes,
                                    const DisplayConfigVariableInfo &fb_config) = 0;
   virtual DisplayError SetCompositionState(LayerComposition composition_type, bool enable) = 0;
diff --git a/sdm/include/utils/debug.h b/sdm/include/utils/debug.h
index 99254ad..540a25e 100644
--- a/sdm/include/utils/debug.h
+++ b/sdm/include/utils/debug.h
@@ -78,6 +78,7 @@
   static bool IsAVRDisabled();
   static bool IsExtAnimDisabled();
   static DisplayError GetMixerResolution(uint32_t *width, uint32_t *height);
+  static int GetExtMaxlayers();
   static bool GetProperty(const char *property_name, char *value);
   static bool SetProperty(const char *property_name, const char *value);
 
diff --git a/sdm/libs/core/comp_manager.cpp b/sdm/libs/core/comp_manager.cpp
index 2947b34..a78369e 100644
--- a/sdm/libs/core/comp_manager.cpp
+++ b/sdm/libs/core/comp_manager.cpp
@@ -119,6 +119,7 @@
   // resources for the added display is configured properly.
   if (!display_comp_ctx->is_primary_panel) {
     safe_mode_ = true;
+    max_sde_ext_layers_ = UINT32(Debug::GetExtMaxlayers());
   }
 
   DLOGV_IF(kTagCompManager, "registered display bit mask 0x%x, configured display bit mask 0x%x, " \
@@ -213,7 +214,7 @@
 
   // Limit 2 layer SDE Comp if its not a Primary Display
   if (!display_comp_ctx->is_primary_panel) {
-    constraints->max_layers = 2;
+    constraints->max_layers = max_sde_ext_layers_;
   }
 
   // If a strategy fails after successfully allocating resources, then set safe mode
diff --git a/sdm/libs/core/comp_manager.h b/sdm/libs/core/comp_manager.h
index 86554b9..ebb257b 100644
--- a/sdm/libs/core/comp_manager.h
+++ b/sdm/libs/core/comp_manager.h
@@ -106,6 +106,7 @@
   HWResourceInfo hw_res_info_;
   ExtensionInterface *extension_intf_ = NULL;
   uint32_t max_layers_ = kMaxSDELayers;
+  uint32_t max_sde_ext_layers_ = 0;
 };
 
 }  // namespace sdm
diff --git a/sdm/libs/core/display_base.cpp b/sdm/libs/core/display_base.cpp
index efd408d..843ed6e 100644
--- a/sdm/libs/core/display_base.cpp
+++ b/sdm/libs/core/display_base.cpp
@@ -518,14 +518,17 @@
   DumpImpl::AppendString(buffer, length, "\n");
 
   HWLayersInfo &layer_info = hw_layers_.info;
-  LayerRect &l_roi = layer_info.left_partial_update;
-  LayerRect &r_roi = layer_info.right_partial_update;
-  DumpImpl::AppendString(buffer, length, "\nROI(L T R B) : LEFT(%d %d %d %d)", INT(l_roi.left),
-                         INT(l_roi.top), INT(l_roi.right), INT(l_roi.bottom));
 
-  if (IsValid(r_roi)) {
-    DumpImpl::AppendString(buffer, length, ", RIGHT(%d %d %d %d)", INT(r_roi.left),
-                           INT(r_roi.top), INT(r_roi.right), INT(r_roi.bottom));
+  for (uint32_t i = 0; i < layer_info.left_frame_roi.size(); i++) {
+    LayerRect &l_roi = layer_info.left_frame_roi.at(i);
+    LayerRect &r_roi = layer_info.right_frame_roi.at(i);
+
+    DumpImpl::AppendString(buffer, length, "\nROI%d(L T R B) : LEFT(%d %d %d %d)", i,
+                           INT(l_roi.left), INT(l_roi.top), INT(l_roi.right), INT(l_roi.bottom));
+    if (IsValid(r_roi)) {
+      DumpImpl::AppendString(buffer, length, ", RIGHT(%d %d %d %d)", INT(r_roi.left),
+                             INT(r_roi.top), INT(r_roi.right), INT(r_roi.bottom));
+    }
   }
 
   const char *header  = "\n| Idx |  Comp Type  |  Split | WB |  Pipe |    W x H    |          Format          |  Src Rect (L T R B) |  Dst Rect (L T R B) |  Z |    Flags   | Deci(HxV) | CS |";  //NOLINT
diff --git a/sdm/libs/core/display_primary.cpp b/sdm/libs/core/display_primary.cpp
index cb0884c..9f6c917 100644
--- a/sdm/libs/core/display_primary.cpp
+++ b/sdm/libs/core/display_primary.cpp
@@ -106,10 +106,17 @@
 DisplayError DisplayPrimary::Commit(LayerStack *layer_stack) {
   lock_guard<recursive_mutex> obj(recursive_mutex_);
   DisplayError error = kErrorNone;
+  uint32_t app_layer_count = hw_layers_.info.app_layer_count;
 
   // Enabling auto refresh is async and needs to happen before commit ioctl
   if (hw_panel_info_.mode == kModeCommand) {
-    hw_intf_->SetAutoRefresh(layer_stack->flags.single_buffered_layer_present);
+    bool enable = (app_layer_count == 1) && layer_stack->flags.single_buffered_layer_present;
+    bool need_refresh = layer_stack->flags.single_buffered_layer_present && (app_layer_count > 1);
+
+    hw_intf_->SetAutoRefresh(enable);
+    if (need_refresh) {
+      event_handler_->Refresh();
+    }
   }
 
   bool set_idle_timeout = comp_manager_->CanSetIdleTimeout(display_comp_ctx_);
@@ -127,6 +134,10 @@
     } else {
       hw_intf_->SetIdleTimeoutMs(0);
     }
+  } else if (switch_to_cmd_) {
+    uint32_t pending;
+    switch_to_cmd_ = false;
+    ControlPartialUpdate(true /* enable */, &pending);
   }
 
   return error;
@@ -191,7 +202,7 @@
     ControlPartialUpdate(false /* enable */, &pending);
     hw_intf_->SetIdleTimeoutMs(idle_timeout_ms_);
   } else if (mode == kModeCommand) {
-    ControlPartialUpdate(true /* enable */, &pending);
+    switch_to_cmd_ = true;
     hw_intf_->SetIdleTimeoutMs(0);
   }
 
diff --git a/sdm/libs/core/display_primary.h b/sdm/libs/core/display_primary.h
index a6b8b4c..7471899 100644
--- a/sdm/libs/core/display_primary.h
+++ b/sdm/libs/core/display_primary.h
@@ -65,6 +65,7 @@
   std::vector<const char *> event_list_ = {"vsync_event", "show_blank_event", "idle_notify",
                                            "msm_fb_thermal_level", "thread_exit"};
   bool avr_prop_disabled_ = false;
+  bool switch_to_cmd_ = false;
 };
 
 }  // namespace sdm
diff --git a/sdm/libs/core/fb/hw_device.cpp b/sdm/libs/core/fb/hw_device.cpp
index d06b161..f7aebe2 100644
--- a/sdm/libs/core/fb/hw_device.cpp
+++ b/sdm/libs/core/fb/hw_device.cpp
@@ -799,8 +799,8 @@
   DLOGI("Device type = %d, Display Port = %d, Display Mode = %d, Device Node = %d, Is Primary = %d",
         device_type_, hw_panel_info_.port, hw_panel_info_.mode, fb_node_index_,
         hw_panel_info_.is_primary_panel);
-  DLOGI("Partial Update = %d, Dynamic FPS = %d",
-        hw_panel_info_.partial_update, hw_panel_info_.dynamic_fps);
+  DLOGI("Partial Update = %d, supported roi_count =%d, Dynamic FPS = %d",
+        hw_panel_info_.partial_update, hw_panel_info_.left_roi_count, hw_panel_info_.dynamic_fps);
   DLOGI("Align: left = %d, width = %d, top = %d, height = %d",
         hw_panel_info_.left_align, hw_panel_info_.width_align,
         hw_panel_info_.top_align, hw_panel_info_.height_align);
@@ -881,6 +881,9 @@
         panel_info->is_primary_panel = atoi(tokens[1]);
       } else if (!strncmp(tokens[0], "is_pluggable", strlen("is_pluggable"))) {
         panel_info->is_pluggable = atoi(tokens[1]);
+      } else if (!strncmp(tokens[0], "pu_roi_cnt", strlen("pu_roi_cnt"))) {
+        panel_info->left_roi_count = UINT32(atoi(tokens[1]));
+        panel_info->right_roi_count = UINT32(atoi(tokens[1]));
       }
     }
   }
diff --git a/sdm/libs/core/fb/hw_primary.cpp b/sdm/libs/core/fb/hw_primary.cpp
index 3dfa4dd..e4a055e 100644
--- a/sdm/libs/core/fb/hw_primary.cpp
+++ b/sdm/libs/core/fb/hw_primary.cpp
@@ -223,10 +223,11 @@
     return kErrorHardware;
   }
 
-  // If driver doesn't return width/height information, default to 160 dpi
+  // If driver doesn't return width/height information, default to 320 dpi
   if (INT(var_screeninfo.width) <= 0 || INT(var_screeninfo.height) <= 0) {
-    var_screeninfo.width  = UINT32(((FLOAT(var_screeninfo.xres) * 25.4f)/160.0f) + 0.5f);
-    var_screeninfo.height = UINT32(((FLOAT(var_screeninfo.yres) * 25.4f)/160.0f) + 0.5f);
+    var_screeninfo.width  = UINT32(((FLOAT(var_screeninfo.xres) * 25.4f)/320.0f) + 0.5f);
+    var_screeninfo.height = UINT32(((FLOAT(var_screeninfo.yres) * 25.4f)/320.0f) + 0.5f);
+    DLOGW("Driver doesn't report panel physical width and height - defaulting to 320dpi");
   }
 
   display_attributes_.x_pixels = var_screeninfo.xres;
@@ -363,18 +364,27 @@
 
   mdp_layer_commit_v1 &mdp_commit = mdp_disp_commit_.commit_v1;
 
-  LayerRect left_roi = hw_layer_info.left_partial_update;
-  LayerRect right_roi = hw_layer_info.right_partial_update;
+  LayerRect left_roi = hw_layer_info.left_frame_roi.at(0);
+  LayerRect right_roi = hw_layer_info.right_frame_roi.at(0);
+
   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);
   mdp_commit.left_roi.h = UINT32(left_roi.bottom - left_roi.top);
 
+  // Update second roi information in right_roi
+  if (hw_layer_info.left_frame_roi.size() == 2) {
+    right_roi = hw_layer_info.left_frame_roi.at(1);
+  }
+
   // 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 && IsValid(right_roi)) {
-    mdp_commit.right_roi.x = UINT32(right_roi.left) - mixer_attributes_.split_left;
+  if (IsValid(right_roi)) {
+    mdp_commit.right_roi.x = UINT32(right_roi.left);
+    if (!hw_resource_.is_src_split) {
+      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);
diff --git a/sdm/libs/core/strategy.cpp b/sdm/libs/core/strategy.cpp
index 1b99f1f..106e9e1 100644
--- a/sdm/libs/core/strategy.cpp
+++ b/sdm/libs/core/strategy.cpp
@@ -46,9 +46,8 @@
   DisplayError error = kErrorNone;
 
   if (extension_intf_) {
-    error = extension_intf_->CreateStrategyExtn(display_type_, hw_panel_info_.mode,
-                                                hw_panel_info_.s3d_mode, mixer_attributes_,
-                                                fb_config_, &strategy_intf_);
+    error = extension_intf_->CreateStrategyExtn(display_type_, hw_resource_info_, hw_panel_info_,
+                                                mixer_attributes_, fb_config_, &strategy_intf_);
     if (error != kErrorNone) {
       DLOGE("Failed to create strategy");
       return error;
@@ -182,15 +181,19 @@
     split_display = true;
   }
 
+  hw_layers_info_->left_frame_roi = {};
+  hw_layers_info_->right_frame_roi = {};
+
   if (split_display) {
     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};
+    hw_layers_info_->left_frame_roi.push_back(LayerRect(0.0f, 0.0f,
+                                left_split, layer_mixer_height));
+    hw_layers_info_->right_frame_roi.push_back(LayerRect(left_split,
+                                0.0f, layer_mixer_width, layer_mixer_height));
   } else {
-    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};
+    hw_layers_info_->left_frame_roi.push_back(LayerRect(0.0f, 0.0f,
+                                layer_mixer_width, layer_mixer_height));
+    hw_layers_info_->right_frame_roi.push_back(LayerRect(0.0f, 0.0f, 0.0f, 0.0f));
   }
 }
 
@@ -215,8 +218,8 @@
                                        mixer_attributes, display_attributes,
                                        &partial_update_intf_);
 
-  error = strategy_intf_->Reconfigure(hw_panel_info.mode, hw_panel_info.s3d_mode, mixer_attributes,
-                                     fb_config);
+  error = strategy_intf_->Reconfigure(hw_panel_info, hw_resource_info_, mixer_attributes,
+                                      fb_config);
   if (error != kErrorNone) {
     return error;
   }
diff --git a/sdm/libs/hwc/hwc_color_manager.cpp b/sdm/libs/hwc/hwc_color_manager.cpp
index 1200de3..7bf49ff 100644
--- a/sdm/libs/hwc/hwc_color_manager.cpp
+++ b/sdm/libs/hwc/hwc_color_manager.cpp
@@ -423,65 +423,67 @@
   DisplayDetailEnhancerData de_data;
 
   PPDETuningCfgData *de_tuning_cfg_data = reinterpret_cast<PPDETuningCfgData*>(params);
-  if (!de_tuning_cfg_data->cfg_en) {
-    de_data.override_flags = kOverrideDEEnable;
-    de_data.enable = 0;
-  } else {
-    de_data.override_flags = kOverrideDEEnable;
-    de_data.enable = 1;
+  if (de_tuning_cfg_data->cfg_pending == true) {
+    if (!de_tuning_cfg_data->cfg_en) {
+      de_data.override_flags = kOverrideDEEnable;
+      de_data.enable = 0;
+    } else {
+      de_data.override_flags = kOverrideDEEnable;
+      de_data.enable = 1;
 
-    if (de_tuning_cfg_data->params.flags & kDeTuningFlagSharpFactor) {
-      de_data.override_flags |= kOverrideDEEnable;
-      de_data.sharp_factor = de_tuning_cfg_data->params.sharp_factor;
-    }
+      if (de_tuning_cfg_data->params.flags & kDeTuningFlagSharpFactor) {
+        de_data.override_flags |= kOverrideDESharpen1;
+        de_data.sharp_factor = de_tuning_cfg_data->params.sharp_factor;
+      }
 
-    if (de_tuning_cfg_data->params.flags & kDeTuningFlagClip) {
-      de_data.override_flags |= kOverrideDEEnable;
-      de_data.clip = de_tuning_cfg_data->params.clip;
-    }
+      if (de_tuning_cfg_data->params.flags & kDeTuningFlagClip) {
+        de_data.override_flags |= kOverrideDEClip;
+        de_data.clip = de_tuning_cfg_data->params.clip;
+      }
 
-    if (de_tuning_cfg_data->params.flags & kDeTuningFlagThrQuiet) {
-      de_data.override_flags |= kOverrideDEEnable;
-      de_data.thr_quiet = de_tuning_cfg_data->params.thr_quiet;
-    }
+      if (de_tuning_cfg_data->params.flags & kDeTuningFlagThrQuiet) {
+        de_data.override_flags |= kOverrideDEThrQuiet;
+        de_data.thr_quiet = de_tuning_cfg_data->params.thr_quiet;
+      }
 
-    if (de_tuning_cfg_data->params.flags & kDeTuningFlagThrDieout) {
-      de_data.override_flags |= kOverrideDEEnable;
-      de_data.thr_dieout = de_tuning_cfg_data->params.thr_dieout;
-    }
+      if (de_tuning_cfg_data->params.flags & kDeTuningFlagThrDieout) {
+        de_data.override_flags |= kOverrideDEThrDieout;
+        de_data.thr_dieout = de_tuning_cfg_data->params.thr_dieout;
+      }
 
-    if (de_tuning_cfg_data->params.flags & kDeTuningFlagThrLow) {
-      de_data.override_flags |= kOverrideDEEnable;
-      de_data.thr_low = de_tuning_cfg_data->params.thr_low;
-    }
+      if (de_tuning_cfg_data->params.flags & kDeTuningFlagThrLow) {
+        de_data.override_flags |= kOverrideDEThrLow;
+        de_data.thr_low = de_tuning_cfg_data->params.thr_low;
+      }
 
-    if (de_tuning_cfg_data->params.flags & kDeTuningFlagThrHigh) {
-      de_data.override_flags |= kOverrideDEEnable;
-      de_data.thr_high = de_tuning_cfg_data->params.thr_high;
-    }
+      if (de_tuning_cfg_data->params.flags & kDeTuningFlagThrHigh) {
+        de_data.override_flags |= kOverrideDEThrHigh;
+        de_data.thr_high = de_tuning_cfg_data->params.thr_high;
+      }
 
-    if (de_tuning_cfg_data->params.flags & kDeTuningFlagContentQualLevel) {
-      de_data.override_flags |= kOverrideDEEnable;
-      switch (de_tuning_cfg_data->params.quality) {
-        case kDeContentQualLow:
-          de_data.quality_level = kContentQualityLow;
-          break;
-        case kDeContentQualMedium:
-          de_data.quality_level = kContentQualityMedium;
-          break;
-        case kDeContentQualHigh:
-          de_data.quality_level = kContentQualityHigh;
-          break;
-        case kDeContentQualUnknown:
-        default:
-          de_data.quality_level = kContentQualityUnknown;
-          break;
+      if (de_tuning_cfg_data->params.flags & kDeTuningFlagContentQualLevel) {
+        switch (de_tuning_cfg_data->params.quality) {
+          case kDeContentQualLow:
+            de_data.quality_level = kContentQualityLow;
+            break;
+          case kDeContentQualMedium:
+            de_data.quality_level = kContentQualityMedium;
+            break;
+          case kDeContentQualHigh:
+            de_data.quality_level = kContentQualityHigh;
+            break;
+          case kDeContentQualUnknown:
+          default:
+            de_data.quality_level = kContentQualityUnknown;
+            break;
+        }
       }
     }
-  }
-  err = hwc_display->SetDetailEnhancerConfig(de_data);
-  if (err) {
-    DLOGW("SetDetailEnhancerConfig failed. err = %d", err);
+    err = hwc_display->SetDetailEnhancerConfig(de_data);
+    if (err) {
+      DLOGW("SetDetailEnhancerConfig failed. err = %d", err);
+    }
+    de_tuning_cfg_data->cfg_pending = false;
   }
 
   return err;
diff --git a/sdm/libs/hwc/hwc_display.cpp b/sdm/libs/hwc/hwc_display.cpp
index 383aaa9..3327ed9 100644
--- a/sdm/libs/hwc/hwc_display.cpp
+++ b/sdm/libs/hwc/hwc_display.cpp
@@ -621,7 +621,7 @@
 
   size_t num_hw_layers = content_list->numHwLayers;
 
-  if (!skip_prepare_) {
+  if (!skip_prepare_cnt) {
     DisplayError error = display_intf_->Prepare(&layer_stack_);
     if (error != kErrorNone) {
       if (error == kErrorShutDown) {
@@ -639,7 +639,7 @@
   } else {
     // Skip is not set
     MarkLayersForGPUBypass(content_list);
-    skip_prepare_ = false;
+    skip_prepare_cnt = skip_prepare_cnt - 1;
     DLOGI("SecureDisplay %s, Skip Prepare/Commit and Flush", secure_display_active_ ? "Starting" :
           "Stopping");
     flush_ = true;
diff --git a/sdm/libs/hwc/hwc_display.h b/sdm/libs/hwc/hwc_display.h
index 47f2390..7dab6d5 100644
--- a/sdm/libs/hwc/hwc_display.h
+++ b/sdm/libs/hwc/hwc_display.h
@@ -210,7 +210,7 @@
   bool shutdown_pending_ = false;
   bool use_blit_comp_ = false;
   bool secure_display_active_ = false;
-  bool skip_prepare_ = false;
+  uint32_t skip_prepare_cnt = 0;
   bool solid_fill_enable_ = false;
   bool disable_animation_ = false;
   uint32_t solid_fill_color_ = 0;
diff --git a/sdm/libs/hwc/hwc_display_primary.cpp b/sdm/libs/hwc/hwc_display_primary.cpp
index 0028ed9..51402d7 100644
--- a/sdm/libs/hwc/hwc_display_primary.cpp
+++ b/sdm/libs/hwc/hwc_display_primary.cpp
@@ -303,14 +303,25 @@
     DLOGI("SecureDisplay state changed from %d to %d Needs Flush!!", secure_display_active_,
            secure_display_active);
     secure_display_active_ = secure_display_active;
-    skip_prepare_ = true;
+    skip_prepare_cnt = 1;
 
-    // Avoid flush for command mode panels when no external displays are connected
+    // Issue two null commits for command mode panels when external displays are connected.
+    // Two null commits are required to handle non secure to secure transitions at 30fps.
+    // TODO(user): Need two null commits on video mode also to handle transition cases of
+    // primary at higher fps (ex60) and external at lower fps.
+
+    // Avoid flush for command mode panels when no external displays are connected.
+    // This is to avoid flicker/blink on primary during transitions.
     DisplayConfigFixedInfo display_config;
     display_intf_->GetConfig(&display_config);
-    if ((display_config.is_cmdmode) && (force_flush == false)) {
-      DLOGI("Avoid flush for command mode panel");
-      skip_prepare_ = false;
+    if (display_config.is_cmdmode) {
+      if (force_flush) {
+        DLOGI("Issue two null commits for command mode panels");
+        skip_prepare_cnt = 2;
+      } else {
+        DLOGI("Avoid flush for command mode panel when no external displays are connected");
+        skip_prepare_cnt = 0;
+      }
     }
   }
 }
diff --git a/sdm/libs/hwc/hwc_session.cpp b/sdm/libs/hwc/hwc_session.cpp
index 56c4a6f..a7f4d67 100644
--- a/sdm/libs/hwc/hwc_session.cpp
+++ b/sdm/libs/hwc/hwc_session.cpp
@@ -45,6 +45,7 @@
 #include <sync/sync.h>
 #include <profiler.h>
 #include <bitset>
+#include <vector>
 
 #include "hwc_buffer_allocator.h"
 #include "hwc_buffer_sync_handler.h"
@@ -274,6 +275,7 @@
 
     if (hwc_session->need_invalidate_) {
       hwc_procs->invalidate(hwc_procs);
+      hwc_session->need_invalidate_ = false;
     }
 
     hwc_session->HandleSecureDisplaySession(displays);
@@ -775,6 +777,10 @@
     status = SetMixerResolution(input_parcel);
     break;
 
+  case qService::IQService::GET_HDR_CAPABILITIES:
+    status = GetHdrCapabilities(input_parcel, output_parcel);
+    break;
+
   default:
     DLOGW("QService command = %d is not supported", command);
     return -EINVAL;
@@ -1182,6 +1188,24 @@
   return 0;
 }
 
+android::status_t HWCSession::GetHdrCapabilities(const android::Parcel *input_parcel,
+                                                 android::Parcel *output_parcel) {
+  // TODO(akumarkr): Get values from display intf
+  // uint32_t dpy = UINT32(input_parcel->readInt32());
+  std::vector<int32_t> supported_hdr_types;
+  supported_hdr_types.push_back(HAL_HDR_HDR10);
+  float max_luminance = 500.0;
+  float max_average_luminance = 200.0;
+  float min_luminance = 0.5;
+  if (output_parcel != nullptr) {
+    output_parcel->writeInt32Vector(supported_hdr_types);
+    output_parcel->writeFloat(max_luminance);
+    output_parcel->writeFloat(max_average_luminance);
+    output_parcel->writeFloat(min_luminance);
+  }
+  return 0;
+}
+
 void HWCSession::DynamicDebug(const android::Parcel *input_parcel) {
   int type = input_parcel->readInt32();
   bool enable = (input_parcel->readInt32() > 0);
diff --git a/sdm/libs/hwc/hwc_session.h b/sdm/libs/hwc/hwc_session.h
index 4519c29..c0dba84 100644
--- a/sdm/libs/hwc/hwc_session.h
+++ b/sdm/libs/hwc/hwc_session.h
@@ -125,6 +125,8 @@
                                           android::Parcel *output_parcel);
   android::status_t SetMixerResolution(const android::Parcel *input_parcel);
   android::status_t SetDisplayPort(DisplayPort sdm_disp_port, int *hwc_disp_port);
+  android::status_t GetHdrCapabilities(const android::Parcel *input_parcel,
+                                       android::Parcel *output_parcel);
 
   static Locker locker_;
   CoreInterface *core_intf_ = NULL;
diff --git a/sdm/libs/hwc2/hwc_color_manager.cpp b/sdm/libs/hwc2/hwc_color_manager.cpp
index ec0dffe..c76f540 100644
--- a/sdm/libs/hwc2/hwc_color_manager.cpp
+++ b/sdm/libs/hwc2/hwc_color_manager.cpp
@@ -279,65 +279,67 @@
   DisplayDetailEnhancerData de_data;
 
   PPDETuningCfgData *de_tuning_cfg_data = reinterpret_cast<PPDETuningCfgData*>(params);
-  if (!de_tuning_cfg_data->cfg_en) {
-    de_data.override_flags = kOverrideDEEnable;
-    de_data.enable = 0;
-  } else {
-    de_data.override_flags = kOverrideDEEnable;
-    de_data.enable = 1;
+  if (de_tuning_cfg_data->cfg_pending == true) {
+    if (!de_tuning_cfg_data->cfg_en) {
+      de_data.override_flags = kOverrideDEEnable;
+      de_data.enable = 0;
+    } else {
+      de_data.override_flags = kOverrideDEEnable;
+      de_data.enable = 1;
 
-    if (de_tuning_cfg_data->params.flags & kDeTuningFlagSharpFactor) {
-      de_data.override_flags |= kOverrideDEEnable;
-      de_data.sharp_factor = de_tuning_cfg_data->params.sharp_factor;
-    }
+      if (de_tuning_cfg_data->params.flags & kDeTuningFlagSharpFactor) {
+        de_data.override_flags |= kOverrideDESharpen1;
+        de_data.sharp_factor = de_tuning_cfg_data->params.sharp_factor;
+      }
 
-    if (de_tuning_cfg_data->params.flags & kDeTuningFlagClip) {
-      de_data.override_flags |= kOverrideDEEnable;
-      de_data.clip = de_tuning_cfg_data->params.clip;
-    }
+      if (de_tuning_cfg_data->params.flags & kDeTuningFlagClip) {
+        de_data.override_flags |= kOverrideDEClip;
+        de_data.clip = de_tuning_cfg_data->params.clip;
+      }
 
-    if (de_tuning_cfg_data->params.flags & kDeTuningFlagThrQuiet) {
-      de_data.override_flags |= kOverrideDEEnable;
-      de_data.thr_quiet = de_tuning_cfg_data->params.thr_quiet;
-    }
+      if (de_tuning_cfg_data->params.flags & kDeTuningFlagThrQuiet) {
+        de_data.override_flags |= kOverrideDEThrQuiet;
+        de_data.thr_quiet = de_tuning_cfg_data->params.thr_quiet;
+      }
 
-    if (de_tuning_cfg_data->params.flags & kDeTuningFlagThrDieout) {
-      de_data.override_flags |= kOverrideDEEnable;
-      de_data.thr_dieout = de_tuning_cfg_data->params.thr_dieout;
-    }
+      if (de_tuning_cfg_data->params.flags & kDeTuningFlagThrDieout) {
+        de_data.override_flags |= kOverrideDEThrDieout;
+        de_data.thr_dieout = de_tuning_cfg_data->params.thr_dieout;
+      }
 
-    if (de_tuning_cfg_data->params.flags & kDeTuningFlagThrLow) {
-      de_data.override_flags |= kOverrideDEEnable;
-      de_data.thr_low = de_tuning_cfg_data->params.thr_low;
-    }
+      if (de_tuning_cfg_data->params.flags & kDeTuningFlagThrLow) {
+        de_data.override_flags |= kOverrideDEThrLow;
+        de_data.thr_low = de_tuning_cfg_data->params.thr_low;
+      }
 
-    if (de_tuning_cfg_data->params.flags & kDeTuningFlagThrHigh) {
-      de_data.override_flags |= kOverrideDEEnable;
-      de_data.thr_high = de_tuning_cfg_data->params.thr_high;
-    }
+      if (de_tuning_cfg_data->params.flags & kDeTuningFlagThrHigh) {
+        de_data.override_flags |= kOverrideDEThrHigh;
+        de_data.thr_high = de_tuning_cfg_data->params.thr_high;
+      }
 
-    if (de_tuning_cfg_data->params.flags & kDeTuningFlagContentQualLevel) {
-      de_data.override_flags |= kOverrideDEEnable;
-      switch (de_tuning_cfg_data->params.quality) {
-        case kDeContentQualLow:
-          de_data.quality_level = kContentQualityLow;
-          break;
-        case kDeContentQualMedium:
-          de_data.quality_level = kContentQualityMedium;
-          break;
-        case kDeContentQualHigh:
-          de_data.quality_level = kContentQualityHigh;
-          break;
-        case kDeContentQualUnknown:
-        default:
-          de_data.quality_level = kContentQualityUnknown;
-          break;
+      if (de_tuning_cfg_data->params.flags & kDeTuningFlagContentQualLevel) {
+        switch (de_tuning_cfg_data->params.quality) {
+          case kDeContentQualLow:
+            de_data.quality_level = kContentQualityLow;
+            break;
+          case kDeContentQualMedium:
+            de_data.quality_level = kContentQualityMedium;
+            break;
+          case kDeContentQualHigh:
+            de_data.quality_level = kContentQualityHigh;
+            break;
+          case kDeContentQualUnknown:
+          default:
+            de_data.quality_level = kContentQualityUnknown;
+            break;
+        }
       }
     }
-  }
-  err = hwc_display->SetDetailEnhancerConfig(de_data);
-  if (err) {
-    DLOGW("SetDetailEnhancerConfig failed. err = %d", err);
+    err = hwc_display->SetDetailEnhancerConfig(de_data);
+    if (err) {
+      DLOGW("SetDetailEnhancerConfig failed. err = %d", err);
+    }
+    de_tuning_cfg_data->cfg_pending = false;
   }
 
   return err;
diff --git a/sdm/libs/hwc2/hwc_display.cpp b/sdm/libs/hwc2/hwc_display.cpp
index 4559aee..0f2b900 100644
--- a/sdm/libs/hwc2/hwc_display.cpp
+++ b/sdm/libs/hwc2/hwc_display.cpp
@@ -386,6 +386,8 @@
       LayerBuffer *layer_buffer = layer->input_buffer;
       layer_buffer->width = UINT32(layer->dst_rect.right - layer->dst_rect.left);
       layer_buffer->height = UINT32(layer->dst_rect.bottom - layer->dst_rect.top);
+      layer_buffer->unaligned_width = layer_buffer->width;
+      layer_buffer->unaligned_height = layer_buffer->height;
       layer_buffer->acquire_fence_fd = -1;
       layer_buffer->release_fence_fd = -1;
       layer->src_rect.left = 0;
diff --git a/sdm/libs/hwc2/hwc_session.cpp b/sdm/libs/hwc2/hwc_session.cpp
index 66ab568..96111d9 100644
--- a/sdm/libs/hwc2/hwc_session.cpp
+++ b/sdm/libs/hwc2/hwc_session.cpp
@@ -215,7 +215,8 @@
 // HWC2 functions returned in GetFunction
 // Defined in the same order as in the HWC2 header
 
-static int32_t AcceptDisplayChanges(hwc2_device_t *device, hwc2_display_t display) {
+int32_t HWCSession::AcceptDisplayChanges(hwc2_device_t *device, hwc2_display_t display) {
+  SCOPE_LOCK(locker_);
   return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::AcceptDisplayChanges);
 }
 
@@ -590,7 +591,7 @@
 
   switch (descriptor) {
     case HWC2::FunctionDescriptor::AcceptDisplayChanges:
-      return AsFP<HWC2_PFN_ACCEPT_DISPLAY_CHANGES>(AcceptDisplayChanges);
+      return AsFP<HWC2_PFN_ACCEPT_DISPLAY_CHANGES>(HWCSession::AcceptDisplayChanges);
     case HWC2::FunctionDescriptor::CreateLayer:
       return AsFP<HWC2_PFN_CREATE_LAYER>(CreateLayer);
     case HWC2::FunctionDescriptor::CreateVirtualDisplay:
diff --git a/sdm/libs/hwc2/hwc_session.h b/sdm/libs/hwc2/hwc_session.h
index ce3e27f..7ae59ed 100644
--- a/sdm/libs/hwc2/hwc_session.h
+++ b/sdm/libs/hwc2/hwc_session.h
@@ -82,6 +82,7 @@
 
   // HWC2 Functions that require a concrete implementation in hwc session
   // and hence need to be member functions
+  static int32_t AcceptDisplayChanges(hwc2_device_t *device, hwc2_display_t display);
   static int32_t CreateLayer(hwc2_device_t *device, hwc2_display_t display,
                              hwc2_layer_t *out_layer_id);
   static int32_t CreateVirtualDisplay(hwc2_device_t *device, uint32_t width, uint32_t height,
diff --git a/sdm/libs/utils/debug.cpp b/sdm/libs/utils/debug.cpp
index 4a8e070..fc8567a 100644
--- a/sdm/libs/utils/debug.cpp
+++ b/sdm/libs/utils/debug.cpp
@@ -31,6 +31,7 @@
 #include <utils/debug.h>
 #include <utils/constants.h>
 #include <string>
+#include <algorithm>
 
 namespace sdm {
 
@@ -163,7 +164,7 @@
 }
 
 DisplayError Debug::GetMixerResolution(uint32_t *width, uint32_t *height) {
-  char value[64];
+  char value[64] = {};
 
   DisplayError error = debug_.debug_handler_->GetProperty("sdm.mixer_resolution", value);
   if (error !=kErrorNone) {
@@ -178,6 +179,13 @@
   return kErrorNone;
 }
 
+int Debug::GetExtMaxlayers() {
+  int max_external_layers = 0;
+  debug_.debug_handler_->GetProperty("sdm.max_external_layers", &max_external_layers);
+
+  return std::max(max_external_layers, 2);
+}
+
 bool Debug::GetProperty(const char* property_name, char* value) {
   if (debug_.debug_handler_->GetProperty(property_name, value) != kErrorNone) {
     return false;
diff --git a/sdm/libs/utils/rect.cpp b/sdm/libs/utils/rect.cpp
index e1180e3..fc553a3 100644
--- a/sdm/libs/utils/rect.cpp
+++ b/sdm/libs/utils/rect.cpp
@@ -205,6 +205,10 @@
     return;
   }
 
+  int x_offset = INT(src_domain.left);
+  int y_offset = INT(src_domain.top);
+
+  LayerRect modified_in_rect = Reposition(in_rect, -x_offset, -y_offset);
   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;
@@ -213,10 +217,10 @@
   float width_ratio = dst_domain_width / src_domain_width;
   float height_ratio = dst_domain_height / src_domain_height;
 
-  out_rect->left = dst_domain.left + (width_ratio * in_rect.left);
-  out_rect->top = dst_domain.top + (height_ratio * in_rect.top);
-  out_rect->right = dst_domain.left + (width_ratio * in_rect.right);
-  out_rect->bottom = dst_domain.top + (height_ratio * in_rect.bottom);
+  out_rect->left = dst_domain.left + (width_ratio * modified_in_rect.left);
+  out_rect->top = dst_domain.top + (height_ratio * modified_in_rect.top);
+  out_rect->right = dst_domain.left + (width_ratio * modified_in_rect.right);
+  out_rect->bottom = dst_domain.top + (height_ratio * modified_in_rect.bottom);
 }
 
 RectOrientation GetOrientation(const LayerRect &in_rect) {