msm8998: Update to LA.UM.5.7.R1.07.00.00.253.052

msm8998: from hardware/qcom/display
  11f3152 Merge AU_LINUX_ANDROID_LA.UM.5.7.R1.07.00.00.253.042 on remote branch
  c8edaff Promotion of display.lnx.3.0-00073.
  4b9f87f sdm: Fix infinite frame invalidates during camera bandwidth mode change. During camera bandwidth mode change, need_invalidate is set to true for  to request new draw cycles to allow new bandwidth mode to take effect.  This variable is not reset after mode is changed.
  fcd4ec5 Merge "sdm: Enable autorefresh only one single buffer layer is present"
  d92bdf3 Merge "sdm: Fix Map rect for offset in source domain"
  982952a Merge "sdm: Multi rect partial update changes"
  1e4ca32 Merge "hwc1: Add support for getHdrCapabilities"
  6abdf82 Promotion of display.lnx.3.0-00070.
  c906e98 sdm: Enable autorefresh only one single buffer layer is present
  b82c9a0 sdm: Fix partial update control in display mode switch
  6064cad sdm: Fix Map rect for offset in source domain
  48a392c hwc1: Add support for getHdrCapabilities
  5036d3d hwc2: Protect AcceptDisplayChanges with the hwc session lock
  249e03b sdm: Multi rect partial update changes
  bce1d81 Merge "sdm: Issue two null commits for command mode panels"
  c41e42c sdm: Issue two null commits for command mode panels
  ebf4a0d hwc2: Fix missing unaligned width setting
  ecf1b50 sdm: color-manager: Detail Enhancer Enhancements.
  b2771bf display: Add color Metadata
  8b3dddc Merge "sdm : Allow configurable sdm layer limit for external"
  770e328 Merge "HWC: Set skip to layers with Non Integral Source Crop"
  e78a97f Merge "gralloc: Return an error if the buffer was not mapped"
  a61a5f8 sdm : Allow configurable sdm layer limit for external
  debd5ce gralloc: Return an error if the buffer was not mapped
  a9f9000 HWC: Set skip to layers with Non Integral Source Crop

Bug: 33556391
Change-Id: If1886c87a823d583e5cec891468f5e2e2199d607
Signed-off-by: Thierry Strudel <tstrudel@google.com>
diff --git a/msm8998/Android.mk b/msm8998/Android.mk
index b8b893c..60a48f5 100644
--- a/msm8998/Android.mk
+++ b/msm8998/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/msm8998/common.mk b/msm8998/common.mk
index af72e7b..d44a664 100644
--- a/msm8998/common.mk
+++ b/msm8998/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/msm8998/include/Android.mk b/msm8998/include/Android.mk
new file mode 100644
index 0000000..4d0d9f7
--- /dev/null
+++ b/msm8998/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/msm8998/include/color_metadata.h b/msm8998/include/color_metadata.h
new file mode 100644
index 0000000..328cb0e
--- /dev/null
+++ b/msm8998/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/msm8998/libgralloc/mapper.cpp b/msm8998/libgralloc/mapper.cpp
index d8880ef..132c768 100644
--- a/msm8998/libgralloc/mapper.cpp
+++ b/msm8998/libgralloc/mapper.cpp
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2008 The Android Open Source Project
- * Copyright (c) 2011-2015, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011-2016, The Linux Foundation. All rights reserved.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -55,6 +55,27 @@
     return memalloc;
 }
 
+static int gralloc_map_metadata(buffer_handle_t handle) {
+    private_handle_t* hnd = (private_handle_t*)handle;
+    hnd->base_metadata = 0;
+    IMemAlloc* memalloc = getAllocator(hnd->flags) ;
+    void *mappedAddress = MAP_FAILED;
+    unsigned int size = 0;
+    if (!(hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER)) {
+        mappedAddress = MAP_FAILED;
+        size = ROUND_UP_PAGESIZE(sizeof(MetaData_t));
+        int ret = memalloc->map_buffer(&mappedAddress, size,
+                                       hnd->offset_metadata, hnd->fd_metadata);
+        if(ret || mappedAddress == MAP_FAILED) {
+            ALOGE("Could not mmap metadata for handle %p, fd=%d (%s)",
+                  hnd, hnd->fd_metadata, strerror(errno));
+            return -errno;
+        }
+        hnd->base_metadata = uint64_t(mappedAddress) + hnd->offset_metadata;
+    }
+    return 0;
+}
+
 static int gralloc_map(gralloc_module_t const* module,
                        buffer_handle_t handle)
 {
@@ -68,7 +89,6 @@
     IMemAlloc* memalloc = getAllocator(hnd->flags) ;
     void *mappedAddress = MAP_FAILED;
     hnd->base = 0;
-    hnd->base_metadata = 0;
 
     // Dont map framebuffer and secure buffers
     if (!(hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER) &&
@@ -83,23 +103,21 @@
         }
 
         hnd->base = uint64_t(mappedAddress) + hnd->offset;
+    } else {
+        // Cannot map secure buffers or framebuffers, but still need to map
+        // metadata for secure buffers.
+        // If mapping a secure buffers fails, the framework needs to get
+        // an error code.
+        err = -EACCES;
     }
 
     //Allow mapping of metadata for all buffers including secure ones, but not
     //of framebuffer
-    if (!(hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER)) {
-        mappedAddress = MAP_FAILED;
-        size = ROUND_UP_PAGESIZE(sizeof(MetaData_t));
-        err = memalloc->map_buffer(&mappedAddress, size,
-                                       hnd->offset_metadata, hnd->fd_metadata);
-        if(err || mappedAddress == MAP_FAILED) {
-            ALOGE("Could not mmap handle %p, fd=%d (%s)",
-                  handle, hnd->fd_metadata, strerror(errno));
-            return -errno;
-        }
-        hnd->base_metadata = uint64_t(mappedAddress) + hnd->offset_metadata;
+    int metadata_err = gralloc_map_metadata(handle);
+    if (!err) {
+        err = metadata_err;
     }
-    return 0;
+    return err;
 }
 
 static int gralloc_unmap(gralloc_module_t const* module,
@@ -153,20 +171,11 @@
     if (!module || private_handle_t::validate(handle) < 0)
         return -EINVAL;
 
-    /* NOTE: we need to initialize the buffer as not mapped/not locked
-     * because it shouldn't when this function is called the first time
-     * in a new process. Ideally these flags shouldn't be part of the
-     * handle, but instead maintained in the kernel or at least
-     * out-of-line
-     */
-
-    int err = gralloc_map(module, handle);
-    if (err) {
-        ALOGE("%s: gralloc_map failed", __FUNCTION__);
-        return err;
-    }
-
-    return 0;
+    int err =  gralloc_map(module, handle);
+    /* Do not fail register_buffer for secure buffers*/
+    if (err == -EACCES)
+        err = 0;
+    return err;
 }
 
 int gralloc_unregister_buffer(gralloc_module_t const* module,
@@ -403,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/msm8998/libgralloc1/gr_buf_mgr.cpp b/msm8998/libgralloc1/gr_buf_mgr.cpp
index 6c36345..9650583 100644
--- a/msm8998/libgralloc1/gr_buf_mgr.cpp
+++ b/msm8998/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/msm8998/libqdutils/qdMetaData.cpp b/msm8998/libqdutils/qdMetaData.cpp
index f62653a..c888baa 100644
--- a/msm8998/libqdutils/qdMetaData.cpp
+++ b/msm8998/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/msm8998/libqdutils/qdMetaData.h b/msm8998/libqdutils/qdMetaData.h
index 2b0b8c6..a0ac324 100644
--- a/msm8998/libqdutils/qdMetaData.h
+++ b/msm8998/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/msm8998/libqservice/IQService.h b/msm8998/libqservice/IQService.h
index d25a06d..bf4343a 100644
--- a/msm8998/libqservice/IQService.h
+++ b/msm8998/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/msm8998/sdm/include/private/color_params.h b/msm8998/sdm/include/private/color_params.h
index fdd0c9e..d2f8094 100644
--- a/msm8998/sdm/include/private/color_params.h
+++ b/msm8998/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/msm8998/sdm/include/private/extension_interface.h b/msm8998/sdm/include/private/extension_interface.h
index fc32616..baf18a1 100644
--- a/msm8998/sdm/include/private/extension_interface.h
+++ b/msm8998/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/msm8998/sdm/include/private/hw_info_types.h b/msm8998/sdm/include/private/hw_info_types.h
index 88384a8..b960955 100644
--- a/msm8998/sdm/include/private/hw_info_types.h
+++ b/msm8998/sdm/include/private/hw_info_types.h
@@ -236,6 +236,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) ||
@@ -249,8 +251,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) {
@@ -431,13 +434,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/msm8998/sdm/include/private/strategy_interface.h b/msm8998/sdm/include/private/strategy_interface.h
index 188c540..122a3c6 100644
--- a/msm8998/sdm/include/private/strategy_interface.h
+++ b/msm8998/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/msm8998/sdm/include/utils/debug.h b/msm8998/sdm/include/utils/debug.h
index 99254ad..540a25e 100644
--- a/msm8998/sdm/include/utils/debug.h
+++ b/msm8998/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/msm8998/sdm/libs/core/comp_manager.cpp b/msm8998/sdm/libs/core/comp_manager.cpp
index b98c74e..d1530dc 100644
--- a/msm8998/sdm/libs/core/comp_manager.cpp
+++ b/msm8998/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/msm8998/sdm/libs/core/comp_manager.h b/msm8998/sdm/libs/core/comp_manager.h
index 86554b9..ebb257b 100644
--- a/msm8998/sdm/libs/core/comp_manager.h
+++ b/msm8998/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/msm8998/sdm/libs/core/display_base.cpp b/msm8998/sdm/libs/core/display_base.cpp
index efd408d..843ed6e 100644
--- a/msm8998/sdm/libs/core/display_base.cpp
+++ b/msm8998/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/msm8998/sdm/libs/core/display_primary.cpp b/msm8998/sdm/libs/core/display_primary.cpp
index cb0884c..9f6c917 100644
--- a/msm8998/sdm/libs/core/display_primary.cpp
+++ b/msm8998/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/msm8998/sdm/libs/core/display_primary.h b/msm8998/sdm/libs/core/display_primary.h
index a6b8b4c..7471899 100644
--- a/msm8998/sdm/libs/core/display_primary.h
+++ b/msm8998/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/msm8998/sdm/libs/core/fb/hw_device.cpp b/msm8998/sdm/libs/core/fb/hw_device.cpp
index d06b161..f7aebe2 100644
--- a/msm8998/sdm/libs/core/fb/hw_device.cpp
+++ b/msm8998/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/msm8998/sdm/libs/core/fb/hw_primary.cpp b/msm8998/sdm/libs/core/fb/hw_primary.cpp
index 3dfa4dd..6f62143 100644
--- a/msm8998/sdm/libs/core/fb/hw_primary.cpp
+++ b/msm8998/sdm/libs/core/fb/hw_primary.cpp
@@ -363,18 +363,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/msm8998/sdm/libs/core/strategy.cpp b/msm8998/sdm/libs/core/strategy.cpp
index 1b99f1f..106e9e1 100644
--- a/msm8998/sdm/libs/core/strategy.cpp
+++ b/msm8998/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/msm8998/sdm/libs/hwc/hwc_color_manager.cpp b/msm8998/sdm/libs/hwc/hwc_color_manager.cpp
index 1200de3..7bf49ff 100644
--- a/msm8998/sdm/libs/hwc/hwc_color_manager.cpp
+++ b/msm8998/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/msm8998/sdm/libs/hwc/hwc_display.cpp b/msm8998/sdm/libs/hwc/hwc_display.cpp
index c7ae44d..3327ed9 100644
--- a/msm8998/sdm/libs/hwc/hwc_display.cpp
+++ b/msm8998/sdm/libs/hwc/hwc_display.cpp
@@ -454,6 +454,7 @@
   for (size_t i = 0; i < num_hw_layers; i++) {
     hwc_layer_1_t &hwc_layer = content_list->hwLayers[i];
 
+    const private_handle_t *pvt_handle = static_cast<const private_handle_t *>(hwc_layer.handle);
     Layer *layer = layer_stack_.layers.at(i);
     int ret = PrepareLayerParams(&content_list->hwLayers[i], layer);
 
@@ -471,6 +472,15 @@
     ApplyScanAdjustment(&scaled_display_frame);
 
     SetRect(scaled_display_frame, &layer->dst_rect);
+    if (pvt_handle) {
+        bool NonIntegralSourceCrop =  IsNonIntegralSourceCrop(hwc_layer.sourceCropf);
+        bool secure = (pvt_handle->flags & private_handle_t::PRIV_FLAGS_SECURE_BUFFER) ||
+                (pvt_handle->flags & private_handle_t::PRIV_FLAGS_PROTECTED_BUFFER) ||
+                (pvt_handle->flags & private_handle_t::PRIV_FLAGS_SECURE_DISPLAY);
+        if (NonIntegralSourceCrop && !secure) {
+            layer->flags.skip = true;
+        }
+    }
     SetRect(hwc_layer.sourceCropf, &layer->src_rect);
     ApplyDeInterlaceAdjustment(layer);
 
@@ -611,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) {
@@ -629,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;
@@ -799,6 +809,17 @@
          (layer_stack_.flags.geometry_changed));
 }
 
+bool HWCDisplay::IsNonIntegralSourceCrop(const hwc_frect_t &source) {
+     if ((source.left != roundf(source.left)) ||
+         (source.top != roundf(source.top)) ||
+         (source.right != roundf(source.right)) ||
+         (source.bottom != roundf(source.bottom))) {
+         return true;
+     } else {
+         return false;
+     }
+}
+
 void HWCDisplay::SetRect(const hwc_rect_t &source, LayerRect *target) {
   target->left = FLOAT(source.left);
   target->top = FLOAT(source.top);
diff --git a/msm8998/sdm/libs/hwc/hwc_display.h b/msm8998/sdm/libs/hwc/hwc_display.h
index f3a341f..7dab6d5 100644
--- a/msm8998/sdm/libs/hwc/hwc_display.h
+++ b/msm8998/sdm/libs/hwc/hwc_display.h
@@ -175,6 +175,7 @@
   DisplayError SetMetaData(const private_handle_t *pvt_handle, Layer *layer);
   bool NeedsFrameBufferRefresh(hwc_display_contents_1_t *content_list);
   bool IsLayerUpdating(hwc_display_contents_1_t *content_list, const Layer *layer);
+  bool IsNonIntegralSourceCrop(const hwc_frect_t &source);
   uint32_t GetUpdatingLayersCount(uint32_t app_layer_count);
   bool SingleVideoLayerUpdating(uint32_t app_layer_count);
   bool IsSurfaceUpdated(const std::vector<LayerRect> &dirty_regions);
@@ -209,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/msm8998/sdm/libs/hwc/hwc_display_primary.cpp b/msm8998/sdm/libs/hwc/hwc_display_primary.cpp
index 0028ed9..51402d7 100644
--- a/msm8998/sdm/libs/hwc/hwc_display_primary.cpp
+++ b/msm8998/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/msm8998/sdm/libs/hwc/hwc_session.cpp b/msm8998/sdm/libs/hwc/hwc_session.cpp
index 8b54536..cc8dc05 100644
--- a/msm8998/sdm/libs/hwc/hwc_session.cpp
+++ b/msm8998/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/msm8998/sdm/libs/hwc/hwc_session.h b/msm8998/sdm/libs/hwc/hwc_session.h
index 4519c29..c0dba84 100644
--- a/msm8998/sdm/libs/hwc/hwc_session.h
+++ b/msm8998/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/msm8998/sdm/libs/hwc2/hwc_color_manager.cpp b/msm8998/sdm/libs/hwc2/hwc_color_manager.cpp
index ec0dffe..c76f540 100644
--- a/msm8998/sdm/libs/hwc2/hwc_color_manager.cpp
+++ b/msm8998/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/msm8998/sdm/libs/hwc2/hwc_display.cpp b/msm8998/sdm/libs/hwc2/hwc_display.cpp
index 4559aee..0f2b900 100644
--- a/msm8998/sdm/libs/hwc2/hwc_display.cpp
+++ b/msm8998/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/msm8998/sdm/libs/hwc2/hwc_session.cpp b/msm8998/sdm/libs/hwc2/hwc_session.cpp
index 66ab568..96111d9 100644
--- a/msm8998/sdm/libs/hwc2/hwc_session.cpp
+++ b/msm8998/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/msm8998/sdm/libs/hwc2/hwc_session.h b/msm8998/sdm/libs/hwc2/hwc_session.h
index ce3e27f..7ae59ed 100644
--- a/msm8998/sdm/libs/hwc2/hwc_session.h
+++ b/msm8998/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/msm8998/sdm/libs/utils/debug.cpp b/msm8998/sdm/libs/utils/debug.cpp
index 4a8e070..fc8567a 100644
--- a/msm8998/sdm/libs/utils/debug.cpp
+++ b/msm8998/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/msm8998/sdm/libs/utils/rect.cpp b/msm8998/sdm/libs/utils/rect.cpp
index e1180e3..fc553a3 100644
--- a/msm8998/sdm/libs/utils/rect.cpp
+++ b/msm8998/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) {