Merge branch 'LA.HB.1.3.9_1' into display.lnx.3.0-dev

Change-Id: I72aff6fecdf580de749f1fb6f91d346dc0f91448
CRs-Fixed: 1058446
diff --git a/Android.mk b/Android.mk
index b5961ad..b8b893c 100644
--- a/Android.mk
+++ b/Android.mk
@@ -1,14 +1,17 @@
-display-hals := libcopybit liblight libmemtrack libqservice libqdutils
+sdm-libs := sdm/libs
+display-hals := libqservice libqdutils $(sdm-libs)/utils $(sdm-libs)/core
+
+ifneq ($(TARGET_IS_HEADLESS), true)
+    display-hals += libcopybit liblight libmemtrack hdmi_cec \
+                    $(sdm-libs)/hwc $(sdm-libs)/hwc2
+endif
+
 ifneq ($(TARGET_USES_GRALLOC1), true)
     display-hals += libgralloc
 else
     display-hals += libgralloc1
 endif
 
-display-hals += hdmi_cec
-sdm-libs := sdm/libs
-display-hals += $(sdm-libs)/utils $(sdm-libs)/core $(sdm-libs)/hwc $(sdm-libs)/hwc2
-
 ifeq ($(call is-vendor-board-platform,QCOM),true)
     include $(call all-named-subdir-makefiles,$(display-hals))
 else
diff --git a/Makefile.am b/Makefile.am
new file mode 100644
index 0000000..781b836
--- /dev/null
+++ b/Makefile.am
@@ -0,0 +1,5 @@
+# Makefile.am - Automake script for sdm
+
+ACLOCAL_AMFLAGS = -I m4
+
+SUBDIRS = libqservice libqdutils libgralloc sdm/libs/utils sdm/libs/core
diff --git a/common.mk b/common.mk
index ae0a6cc..af72e7b 100644
--- a/common.mk
+++ b/common.mk
@@ -3,7 +3,7 @@
 
 #Common C flags
 common_flags := -DDEBUG_CALC_FPS -Wno-missing-field-initializers
-common_flags += -Wconversion -Wall -Werror
+common_flags += -Wconversion -Wall -Werror -std=c++11
 
 use_hwc2 := false
 ifeq ($(TARGET_USES_HWC2), true)
@@ -13,7 +13,10 @@
 
 common_includes := $(display_top)/libqdutils
 common_includes += $(display_top)/libqservice
-common_includes += $(display_top)/libcopybit
+ifneq ($(TARGET_IS_HEADLESS), true)
+    common_includes += $(display_top)/libcopybit
+endif
+
 common_includes += $(display_top)/sdm/include
 
 common_header_export_path := qcom/display
@@ -21,6 +24,12 @@
 #Common libraries external to display HAL
 common_libs := liblog libutils libcutils libhardware
 
+ifeq ($(TARGET_IS_HEADLESS), true)
+    LOCAL_CLANG := false
+else
+    LOCAL_CLANG := true
+endif
+
 ifneq ($(TARGET_USES_GRALLOC1), true)
     common_flags += -isystem $(display_top)/libgralloc
 else
@@ -48,10 +57,14 @@
 kernel_includes :=
 
 # Executed only on QCOM BSPs
-# ifeq ($(TARGET_USES_QCOM_BSP),true)
+ifeq ($(TARGET_USES_QCOM_BSP),true)
 # Enable QCOM Display features
-#    common_flags += -DQTI_BSP
-# endif
+   common_flags += -DQTI_BSP
+endif
+
+ifeq ($(TARGET_IS_HEADLESS),true)
+    common_flags += -DTARGET_HEADLESS
+endif
 
 ifeq ($(TARGET_COMPILE_WITH_MSM_KERNEL),true)
 # This check is to pick the kernel headers from the right location.
diff --git a/configure.ac b/configure.ac
new file mode 100644
index 0000000..6fe7d0a
--- /dev/null
+++ b/configure.ac
@@ -0,0 +1,57 @@
+#                                               -*- Autoconf -*-
+# configure.ac -- Autoconf script for sdm
+#
+
+# Process this file with autoconf to produce a configure script
+
+# Requires autoconf tool later than 2.61
+AC_PREREQ(2.61)
+# Initialize the display package version 1.0.0
+AC_INIT([display],1.0.0)
+# Does not strictly follow GNU Coding standards
+AM_INIT_AUTOMAKE([foreign])
+# Disables auto rebuilding of configure, Makefile.ins
+AM_MAINTAINER_MODE
+# defines some macros variable to be included by source
+AC_CONFIG_HEADERS([config.h])
+AC_CONFIG_MACRO_DIR([m4])
+AC_SUBST([COMMON_CFLAGS], [-Wall -Werror -Wno-sign-conversion -Wconversion -DDEBUG_CALC_FPS])
+AC_SUBST([AM_CPPFLAGS], [--std=c++11])
+
+AC_ARG_WITH([core_includes],
+    AC_HELP_STRING([--with-core-includes=@<:@dir@:>@],
+       [Specify the location of the core headers]),
+    [core_incdir=$withval],
+    with_core_includes=no)
+
+if test "x$with_core_includes" != "xno"; then
+   CFLAGS="${CFLAGS} -I${core_incdir}"
+fi
+
+AC_ARG_WITH(sanitized-headers,
+   AS_HELP_STRING([--with-sanitized-headers=DIR],
+       [Specify the location of the sanitized Linux headers]),
+   [CPPFLAGS="$CPPFLAGS -idirafter $withval"])
+
+# Checks for programs.
+AC_PROG_CC
+AM_PROG_CC_C_O
+AC_PROG_CXX
+AC_PROG_LIBTOOL
+AC_PROG_AWK
+AC_PROG_CPP
+AC_PROG_INSTALL
+AC_PROG_LN_S
+AC_PROG_MAKE_SET
+
+AC_SUBST([CFLAGS])
+AC_SUBST([CC])
+AC_CONFIG_FILES([ \
+        Makefile \
+        libqservice/Makefile \
+        libqdutils/Makefile \
+        libgralloc/Makefile \
+        sdm/libs/utils/Makefile \
+        sdm/libs/core/Makefile
+        ])
+AC_OUTPUT
\ No newline at end of file
diff --git a/libgralloc/Android.mk b/libgralloc/Android.mk
index 03da814..5e499b3 100644
--- a/libgralloc/Android.mk
+++ b/libgralloc/Android.mk
@@ -21,10 +21,11 @@
 LOCAL_MODULE_RELATIVE_PATH    := hw
 LOCAL_MODULE_TAGS             := optional
 LOCAL_C_INCLUDES              := $(common_includes) $(kernel_includes)
-LOCAL_SHARED_LIBRARIES        := $(common_libs) libmemalloc libqdMetaData
-LOCAL_SHARED_LIBRARIES        += libqdutils libGLESv1_CM
+LOCAL_SHARED_LIBRARIES        := $(common_libs) libmemalloc libqdMetaData libqdutils
+ifneq ($(TARGET_IS_HEADLESS), true)
+LOCAL_SHARED_LIBRARIES        += libGLESv1_CM
+endif
 LOCAL_CFLAGS                  := $(common_flags) -DLOG_TAG=\"qdgralloc\" -Wno-sign-conversion
-LOCAL_CLANG                   := true
 LOCAL_ADDITIONAL_DEPENDENCIES := $(common_deps) $(kernel_deps)
 LOCAL_SRC_FILES               := gpu.cpp gralloc.cpp framebuffer.cpp mapper.cpp
 LOCAL_COPY_HEADERS_TO         := $(common_header_export_path)
@@ -40,7 +41,6 @@
 LOCAL_C_INCLUDES              := $(common_includes) $(kernel_includes)
 LOCAL_SHARED_LIBRARIES        := $(common_libs) libqdutils libdl
 LOCAL_CFLAGS                  := $(common_flags) -DLOG_TAG=\"qdmemalloc\" -Wno-sign-conversion
-LOCAL_CLANG                   := true
 LOCAL_ADDITIONAL_DEPENDENCIES := $(common_deps) $(kernel_deps)
 LOCAL_SRC_FILES               := ionalloc.cpp alloc_controller.cpp
 LOCAL_COPY_HEADERS            := alloc_controller.h memalloc.h
diff --git a/libgralloc/Makefile.am b/libgralloc/Makefile.am
new file mode 100644
index 0000000..2698df3
--- /dev/null
+++ b/libgralloc/Makefile.am
@@ -0,0 +1,37 @@
+h_sources = alloc_controller.h \
+            memalloc.h
+
+cpp_sources = ionalloc.cpp \
+              alloc_controller.cpp
+
+library_includedir = $(pkgincludedir)
+library_include_HEADERS = $(h_sources)
+
+lib_LTLIBRARIES = libmemalloc.la
+libmemalloc_la_CC = @CC@
+libmemalloc_la_SOURCES = $(cpp_sources)
+libmemalloc_la_CFLAGS = $(COMMON_CFLAGS) -DLOG_TAG=\"qdmemalloc\"
+libmemalloc_la_CPPFLAGS = $(AM_CPPFLAGS)
+libmemalloc_LDADD = -lhardware -lcutils -llog -lutils -ldl
+libmemalloc_la_LIBADD = ../libqdutils/libqdutils.la
+
+header_sources = gralloc_priv.h \
+                 gr.h
+
+c_sources = gpu.cpp \
+            gralloc.cpp \
+            framebuffer.cpp \
+            mapper.cpp
+
+library_includedir = $(pkgincludedir)
+library_include_HEADERS = $(header_sources)
+
+lib_LTLIBRARIES += libgralloc.la
+libgralloc_la_CC = @CC@
+libgralloc_la_SOURCES = $(c_sources)
+libgralloc_la_CFLAGS = $(COMMON_CFLAGS) -DLOG_TAG=\"qdgralloc\"
+libgralloc_la_CPPFLAGS = $(AM_CPPFLAGS)
+libgralloc_LDADD = -lhardware -lcutils -llog -lutils
+libgralloc_la_LIBADD = ../libqdutils/libqdutils.la
+libgralloc_la_LIBADD += ../libqdutils/libqdMetaData.la
+libgralloc_la_LIBADD += libmemalloc.la
\ No newline at end of file
diff --git a/libgralloc/alloc_controller.cpp b/libgralloc/alloc_controller.cpp
index 158fb68..0ef0a9a 100644
--- a/libgralloc/alloc_controller.cpp
+++ b/libgralloc/alloc_controller.cpp
@@ -39,7 +39,7 @@
 #include <qdMetaData.h>
 #include <utils/Singleton.h>
 #include <utils/Mutex.h>
-
+#include <algorithm>
 
 #ifdef VENUS_COLOR_FORMAT
 #include <media/msm_media_info.h>
@@ -101,6 +101,7 @@
 MDPCapabilityInfo :: MDPCapabilityInfo() {
   qdutils::querySDEInfo(HAS_MACRO_TILE, &isMacroTileSupported);
   qdutils::querySDEInfo(HAS_UBWC, &isUBwcSupported);
+  qdutils::querySDEInfo(HAS_WB_UBWC, &isWBUBWCSupported);
 }
 
 //------------- AdrenoMemInfo-----------------------//
@@ -958,11 +959,6 @@
             return false;
     }
 
-    // Workaround for bug 30191188/ CR 1047578
-    if ((usage & GRALLOC_USAGE_HW_VIDEO_ENCODER) && (usage & GRALLOC_USAGE_HW_COMPOSER)) {
-        return false;
-    }
-
     // Allow UBWC, if an OpenGL client sets UBWC usage flag and GPU plus MDP
     // support the format. OR if a non-OpenGL client like Rotator, sets UBWC
     // usage flag and MDP supports the format.
diff --git a/libgralloc/framebuffer.cpp b/libgralloc/framebuffer.cpp
index 5c297c1..dd4842f 100644
--- a/libgralloc/framebuffer.cpp
+++ b/libgralloc/framebuffer.cpp
@@ -34,7 +34,9 @@
 #include <linux/fb.h>
 #include <linux/msm_mdp.h>
 
+#ifndef TARGET_HEADLESS
 #include <GLES/gl.h>
+#endif
 
 #include "gralloc_priv.h"
 #include "fb_priv.h"
@@ -99,7 +101,9 @@
     if(!dev) {
         return -1;
     }
+#ifndef TARGET_HEADLESS
     glFinish();
+#endif
 
     return 0;
 }
diff --git a/libgralloc/gpu.cpp b/libgralloc/gpu.cpp
index c1d7788..5b22e6d 100644
--- a/libgralloc/gpu.cpp
+++ b/libgralloc/gpu.cpp
@@ -159,7 +159,7 @@
         hnd->offset = data.offset;
         hnd->base = (uint64_t)(data.base) + data.offset;
         hnd->gpuaddr = 0;
-        ColorSpace_t colorSpace = ITU_R_601_FR;
+        ColorSpace_t colorSpace = ITU_R_601;
         setMetaData(hnd, UPDATE_COLOR_SPACE, (void*) &colorSpace);
 
         *pHandle = hnd;
@@ -267,9 +267,13 @@
        format == HAL_PIXEL_FORMAT_YCbCr_420_888) {
         if (usage & GRALLOC_USAGE_PRIVATE_ALLOC_UBWC)
             grallocFormat = HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS_UBWC;
-        else if(usage & GRALLOC_USAGE_HW_VIDEO_ENCODER)
-            grallocFormat = HAL_PIXEL_FORMAT_NV12_ENCODEABLE; //NV12
-        else if((usage & GRALLOC_USAGE_HW_CAMERA_MASK)
+        else if(usage & GRALLOC_USAGE_HW_VIDEO_ENCODER) {
+            if(MDPCapabilityInfo::getInstance().isWBUBWCSupportedByMDP() &&
+               usage & GRALLOC_USAGE_HW_COMPOSER)
+              grallocFormat = HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS_UBWC;
+            else
+              grallocFormat = HAL_PIXEL_FORMAT_NV12_ENCODEABLE; //NV12
+        } else if((usage & GRALLOC_USAGE_HW_CAMERA_MASK)
                 == GRALLOC_USAGE_HW_CAMERA_ZSL)
             grallocFormat = HAL_PIXEL_FORMAT_NV21_ZSL; //NV21 ZSL
         else if(usage & GRALLOC_USAGE_HW_CAMERA_READ)
diff --git a/libgralloc/gr.h b/libgralloc/gr.h
index 5fe1bdb..578240a 100644
--- a/libgralloc/gr.h
+++ b/libgralloc/gr.h
@@ -203,6 +203,7 @@
 {
     int isMacroTileSupported = 0;
     int isUBwcSupported = 0;
+    int isWBUBWCSupported = 0;
 
     public:
         MDPCapabilityInfo();
@@ -220,6 +221,13 @@
         *          0 : not supported
         */
         int isUBwcSupportedByMDP() { return isUBwcSupported; }
+        /*
+        * Function to return whether MDP WB block outputs UBWC format
+        *
+        * @return  1 : supported
+        *          0 : not supported
+        */
+        int isWBUBWCSupportedByMDP() { return isWBUBWCSupported; }
 };
 
 #endif /* GR_H_ */
diff --git a/libgralloc/ionalloc.cpp b/libgralloc/ionalloc.cpp
index 96e0e3e..329e30f 100644
--- a/libgralloc/ionalloc.cpp
+++ b/libgralloc/ionalloc.cpp
@@ -36,6 +36,7 @@
 #include <cutils/log.h>
 #include <errno.h>
 #include <utils/Trace.h>
+#include <cutils/trace.h>
 #include "gralloc_priv.h"
 #include "ionalloc.h"
 
diff --git a/liblight/Android.mk b/liblight/Android.mk
index 8aff542..ff4825b 100644
--- a/liblight/Android.mk
+++ b/liblight/Android.mk
@@ -20,7 +20,7 @@
 LOCAL_SRC_FILES := lights.c
 LOCAL_MODULE_RELATIVE_PATH := hw
 LOCAL_SHARED_LIBRARIES := liblog
-LOCAL_CFLAGS := $(common_flags) -DLOG_TAG=\"qdlights\"
+LOCAL_CFLAGS := -DLOG_TAG=\"qdlights\"
 LOCAL_CLANG  := true
 LOCAL_MODULE := lights.$(TARGET_BOARD_PLATFORM)
 LOCAL_MODULE_TAGS := optional
diff --git a/libqdutils/Android.mk b/libqdutils/Android.mk
index f56f774..db6509c 100644
--- a/libqdutils/Android.mk
+++ b/libqdutils/Android.mk
@@ -4,10 +4,9 @@
 
 LOCAL_MODULE                  := libqdutils
 LOCAL_MODULE_TAGS             := optional
-LOCAL_SHARED_LIBRARIES        := $(common_libs) libui libbinder libqservice
+LOCAL_SHARED_LIBRARIES        := $(common_libs) libbinder libqservice
 LOCAL_C_INCLUDES              := $(common_includes) $(kernel_includes)
 LOCAL_CFLAGS                  := $(common_flags) -DLOG_TAG=\"qdutils\" -Wno-sign-conversion
-LOCAL_CLANG                   := true
 LOCAL_ADDITIONAL_DEPENDENCIES := $(common_deps)
 LOCAL_COPY_HEADERS_TO         := $(common_header_export_path)
 LOCAL_COPY_HEADERS            := display_config.h
@@ -26,7 +25,7 @@
 LOCAL_SRC_FILES                 := qdMetaData.cpp
 LOCAL_CFLAGS                    := $(common_flags) -Wno-sign-conversion
 LOCAL_CFLAGS                    += -DLOG_TAG=\"DisplayMetaData\"
-LOCAL_CLANG                     := true
+
 LOCAL_MODULE_TAGS               := optional
 LOCAL_MODULE                    := libqdMetaData
 include $(BUILD_SHARED_LIBRARY)
diff --git a/libqdutils/Makefile.am b/libqdutils/Makefile.am
new file mode 100644
index 0000000..ef2108d
--- /dev/null
+++ b/libqdutils/Makefile.am
@@ -0,0 +1,30 @@
+h_sources = qdMetaData.h
+
+cpp_sources = qdMetaData.cpp
+
+library_includedir = $(includedir)
+library_include_HEADERS = $(h_sources)
+
+lib_LTLIBRARIES = libqdMetaData.la
+libqdMetaData_la_CC = @CC@
+libqdMetaData_la_SOURCES = $(cpp_sources)
+libqdMetaData_la_CFLAGS = $(AM_CFLAGS) -DLOG_TAG=\"DisplayMetaData\"
+libqdMetaData_la_CPPFLAGS = $(AM_CPPFLAGS)
+libqdMetaData_LDADD = -lcutils -llog
+
+header_sources = display_config.h
+
+c_sources = profiler.cpp \
+            qd_utils.cpp \
+            display_config.cpp
+
+library_includedir = $(includedir)
+library_include_HEADERS = $(header_sources)
+
+lib_LTLIBRARIES += libqdutils.la
+libqdutils_la_CC = @CC@
+libqdutils_la_SOURCES = $(c_sources)
+libqdutils_la_CFLAGS = $(COMMON_CFLAGS) -DLOG_TAG=\"qdutils\"
+libqdutils_la_CPPFLAGS = $(AM_CPPFLAGS)
+libqdutils_LDADD = -lhardware -lcutils -llog -lbinder
+libqdutils_la_LIBADD = ../libqservice/libqservice.la
\ No newline at end of file
diff --git a/libqdutils/display_config.cpp b/libqdutils/display_config.cpp
index 3415ac6..c1335b1 100644
--- a/libqdutils/display_config.cpp
+++ b/libqdutils/display_config.cpp
@@ -78,7 +78,7 @@
         dpyattr.yres = outParcel.readInt32();
         dpyattr.xdpi = outParcel.readFloat();
         dpyattr.ydpi = outParcel.readFloat();
-        dpyattr.panel_type = (char) outParcel.readInt32();
+        dpyattr.panel_type = outParcel.readInt32();
     } else {
         ALOGE("%s() failed with err %d", __FUNCTION__, err);
     }
@@ -237,7 +237,7 @@
 }
 
 DisplayAttributes getDisplayAttributes(int configIndex, int /*dpy*/) {
-    DisplayAttributes dpyattr;
+    DisplayAttributes dpyattr = {};
     sp<IQService> binder = getBinder();
     if(binder != NULL) {
         Parcel inParcel, outParcel;
@@ -252,7 +252,7 @@
             dpyattr.yres = outParcel.readInt32();
             dpyattr.xdpi = outParcel.readFloat();
             dpyattr.ydpi = outParcel.readFloat();
-            dpyattr.panel_type = (char) outParcel.readInt32();
+            dpyattr.panel_type = outParcel.readInt32();
             dpyattr.is_yuv = outParcel.readInt32();
             ALOGI("%s() Received attrs for index %d: xres %d, yres %d",
                     __FUNCTION__, configIndex, dpyattr.xres, dpyattr.yres);
diff --git a/libqdutils/display_config.h b/libqdutils/display_config.h
index 15aba94..6512bf5 100644
--- a/libqdutils/display_config.h
+++ b/libqdutils/display_config.h
@@ -76,18 +76,26 @@
     COMMAND_MODE,
 };
 
+enum {
+    DISPLAY_PORT_DEFAULT = 0,
+    DISPLAY_PORT_DSI,
+    DISPLAY_PORT_DTV,
+    DISPLAY_PORT_WRITEBACK,
+    DISPLAY_PORT_LVDS,
+    DISPLAY_PORT_EDP,
+    DISPLAY_PORT_DP,
+};
+
 // Display Attributes that are available to clients of this library
 // Not to be confused with a similar struct in hwc_utils (in the hwc namespace)
 typedef struct DisplayAttributes {
-    uint32_t vsync_period; //nanoseconds
-    uint32_t xres;
-    uint32_t yres;
-    float xdpi;
-    float ydpi;
-    char panel_type;
-    bool is_yuv;
-    DisplayAttributes() : vsync_period(0), xres(0), yres(0), xdpi(0.0f),
-            ydpi(0.0f), panel_type(0), is_yuv(false) {}
+    uint32_t vsync_period = 0; //nanoseconds
+    uint32_t xres = 0;
+    uint32_t yres = 0;
+    float xdpi = 0.0f;
+    float ydpi = 0.0f;
+    int panel_type = DISPLAY_PORT_DEFAULT;
+    bool is_yuv = false;
 } DisplayAttributes_t;
 
 //=============================================================================
diff --git a/libqdutils/qdMetaData.cpp b/libqdutils/qdMetaData.cpp
index 4ada44b..c676098 100644
--- a/libqdutils/qdMetaData.cpp
+++ b/libqdutils/qdMetaData.cpp
@@ -38,18 +38,14 @@
 
 int setMetaData(private_handle_t *handle, DispParamType paramType,
                                                     void *param) {
-    if (!handle) {
-        ALOGE("%s: Private handle is null!", __func__);
+    if (private_handle_t::validate(handle)) {
+        ALOGE("%s: Private handle is invalid! handle=%p", __func__, handle);
         return -1;
     }
     if (handle->fd_metadata == -1) {
         ALOGE("%s: Bad fd for extra data!", __func__);
         return -1;
     }
-    if (!param) {
-        ALOGE("%s: input param is null!", __func__);
-        return -1;
-    }
     unsigned long size = ROUND_UP_PAGESIZE(sizeof(MetaData_t));
     void *base = mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_SHARED,
         handle->fd_metadata, 0);
@@ -58,6 +54,12 @@
         return -1;
     }
     MetaData_t *data = reinterpret_cast <MetaData_t *>(base);
+    // If parameter is NULL reset the specific MetaData Key
+    if (!param) {
+       data->operation &= ~paramType;
+       return munmap(base, size);
+    }
+
     data->operation |= paramType;
     switch (paramType) {
         case PP_PARAM_INTERLACED:
@@ -87,8 +89,42 @@
         case SET_SINGLE_BUFFER_MODE:
             data->isSingleBufferMode = *((uint32_t *)param);
             break;
-        case SET_VT_TIMESTAMP:
-            data->vtTimeStamp = *((uint64_t *)param);
+        case SET_S3D_COMP:
+            data->s3dComp = *((S3DGpuComp_t *)param);
+            break;
+        default:
+            ALOGE("Unknown paramType %d", paramType);
+            break;
+    }
+    if(munmap(base, size))
+        ALOGE("%s: failed to unmap ptr %p, err %d", __func__, (void*)base,
+                                                                        errno);
+    return 0;
+}
+
+int clearMetaData(private_handle_t *handle, DispParamType paramType) {
+    if (!handle) {
+        ALOGE("%s: Private handle is null!", __func__);
+        return -1;
+    }
+    if (handle->fd_metadata == -1) {
+        ALOGE("%s: Bad fd for extra data!", __func__);
+        return -1;
+    }
+
+    unsigned long size = ROUND_UP_PAGESIZE(sizeof(MetaData_t));
+    void *base = mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_SHARED,
+        handle->fd_metadata, 0);
+    if (base == reinterpret_cast<void*>(MAP_FAILED)) {
+        ALOGE("%s: mmap() failed: error is %s!", __func__, strerror(errno));
+        return -1;
+    }
+    MetaData_t *data = reinterpret_cast <MetaData_t *>(base);
+    data->operation &= ~paramType;
+    switch (paramType) {
+        case SET_S3D_COMP:
+            data->s3dComp.displayId = -1;
+            data->s3dComp.s3dMode = 0;
             break;
         default:
             ALOGE("Unknown paramType %d", paramType);
@@ -123,7 +159,6 @@
     }
 
     MetaData_t *data = reinterpret_cast <MetaData_t *>(base);
-    data->operation |= paramType;
     switch (paramType) {
         case GET_PP_PARAM_INTERLACED:
             *((int32_t *)param) = data->interlaced;
@@ -152,8 +187,8 @@
         case GET_SINGLE_BUFFER_MODE:
             *((uint32_t *)param) = data->isSingleBufferMode ;
             break;
-        case GET_VT_TIMESTAMP:
-            *((uint64_t *)param) = data->vtTimeStamp;
+        case GET_S3D_COMP:
+            *((S3DGpuComp_t *)param) = data->s3dComp;
             break;
         default:
             ALOGE("Unknown paramType %d", paramType);
diff --git a/libqdutils/qdMetaData.h b/libqdutils/qdMetaData.h
index deaeedd..8c0a0b0 100644
--- a/libqdutils/qdMetaData.h
+++ b/libqdutils/qdMetaData.h
@@ -57,6 +57,11 @@
     int32_t sliceHeight;
 };
 
+struct S3DGpuComp_t {
+    int32_t displayId; /* on which display S3D is composed by client */
+    uint32_t s3dMode; /* the S3D format of this layer to be accessed by client */
+};
+
 struct MetaData_t {
     int32_t operation;
     int32_t interlaced;
@@ -79,40 +84,40 @@
     /* Set by graphics to indicate that this buffer will be written to but not
      * swapped out */
     uint32_t isSingleBufferMode;
-    /* Set by camera to program the VT Timestamp */
-    uint64_t vtTimeStamp;
+    /* Indicate GPU to draw S3D layer on dedicate display device */
+    struct S3DGpuComp_t s3dComp;
 };
 
 enum DispParamType {
-    UNUSED0                = 0x0001,
-    UNUSED1                = 0x0002,
-    PP_PARAM_INTERLACED    = 0x0004,
-    UNUSED2                = 0x0008,
-    UNUSED3                = 0x0010,
-    UNUSED4                = 0x0020,
-    UNUSED5                = 0x0040,
+    UNUSED0             = 0x0001,
+    UNUSED1             = 0x0002,
+    PP_PARAM_INTERLACED = 0x0004,
+    UNUSED2             = 0x0008,
+    UNUSED3             = 0x0010,
+    UNUSED4             = 0x0020,
+    UNUSED5             = 0x0040,
     UPDATE_BUFFER_GEOMETRY = 0x0080,
-    UPDATE_REFRESH_RATE    = 0x0100,
-    UPDATE_COLOR_SPACE     = 0x0200,
-    MAP_SECURE_BUFFER      = 0x0400,
-    S3D_FORMAT             = 0x0800,
-    LINEAR_FORMAT          = 0x1000,
-    SET_IGC                = 0x2000,
+    UPDATE_REFRESH_RATE = 0x0100,
+    UPDATE_COLOR_SPACE = 0x0200,
+    MAP_SECURE_BUFFER = 0x400,
+    S3D_FORMAT = 0x800,
+    LINEAR_FORMAT = 0x1000,
+    SET_IGC = 0x2000,
     SET_SINGLE_BUFFER_MODE = 0x4000,
-    SET_VT_TIMESTAMP       = 0x8000,
+    SET_S3D_COMP = 0x8000,
 };
 
 enum DispFetchParamType {
-    GET_PP_PARAM_INTERLACED  = 0x0004,
-    GET_BUFFER_GEOMETRY      = 0x0080,
-    GET_REFRESH_RATE         = 0x0100,
-    GET_COLOR_SPACE          = 0x0200,
-    GET_MAP_SECURE_BUFFER    = 0x0400,
-    GET_S3D_FORMAT           = 0x0800,
-    GET_LINEAR_FORMAT        = 0x1000,
-    GET_IGC                  = 0x2000,
-    GET_SINGLE_BUFFER_MODE   = 0x4000,
-    GET_VT_TIMESTAMP         = 0x8000,
+    GET_PP_PARAM_INTERLACED = 0x0004,
+    GET_BUFFER_GEOMETRY = 0x0080,
+    GET_REFRESH_RATE = 0x0100,
+    GET_COLOR_SPACE = 0x0200,
+    GET_MAP_SECURE_BUFFER = 0x400,
+    GET_S3D_FORMAT = 0x800,
+    GET_LINEAR_FORMAT = 0x1000,
+    GET_IGC = 0x2000,
+    GET_SINGLE_BUFFER_MODE = 0x4000,
+    GET_S3D_COMP = 0x8000,
 };
 
 struct private_handle_t;
@@ -123,6 +128,9 @@
         void *param);
 
 int copyMetaData(struct private_handle_t *src, struct private_handle_t *dst);
+
+int clearMetaData(struct private_handle_t *handle, enum DispParamType paramType);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/libqdutils/qd_utils.cpp b/libqdutils/qd_utils.cpp
index 6453b58..43fb715 100644
--- a/libqdutils/qd_utils.cpp
+++ b/libqdutils/qd_utils.cpp
@@ -61,11 +61,12 @@
     case HAS_MACRO_TILE:
         featureName = "tile_format";
         break;
-
     case HAS_UBWC:
         featureName = "ubwc";
         break;
-
+    case HAS_WB_UBWC:
+        featureName = "wb_ubwc";
+        break;
     default:
         ALOGE("Invalid query type %d", type);
         return -EINVAL;
diff --git a/libqdutils/qd_utils.h b/libqdutils/qd_utils.h
index 0392e05..4722dcd 100644
--- a/libqdutils/qd_utils.h
+++ b/libqdutils/qd_utils.h
@@ -49,6 +49,7 @@
 enum HWQueryType {
     HAS_MACRO_TILE = 0,
     HAS_UBWC = 1,
+    HAS_WB_UBWC = 2
 };
 
 enum {
diff --git a/libqservice/Android.mk b/libqservice/Android.mk
index 285afca..5c1eaba 100644
--- a/libqservice/Android.mk
+++ b/libqservice/Android.mk
@@ -7,7 +7,6 @@
 LOCAL_C_INCLUDES              := $(common_includes) $(kernel_includes)
 LOCAL_SHARED_LIBRARIES        := $(common_libs) libbinder
 LOCAL_CFLAGS                  := $(common_flags) -DLOG_TAG=\"qdqservice\" -Wno-sign-conversion
-LOCAL_CLANG                   := true
 LOCAL_ADDITIONAL_DEPENDENCIES := $(common_deps)
 LOCAL_SRC_FILES               := QService.cpp \
                                  IQService.cpp \
diff --git a/libqservice/IQService.cpp b/libqservice/IQService.cpp
index d47f2e9..e1c5219 100644
--- a/libqservice/IQService.cpp
+++ b/libqservice/IQService.cpp
@@ -92,6 +92,7 @@
             callerUid == AID_GRAPHICS ||
             callerUid == AID_ROOT ||
             callerUid == AID_CAMERASERVER ||
+            callerUid == AID_AUDIO ||
             callerUid == AID_SYSTEM);
 
     if (code == CONNECT_HWC_CLIENT) {
diff --git a/libqservice/Makefile.am b/libqservice/Makefile.am
new file mode 100644
index 0000000..155060d
--- /dev/null
+++ b/libqservice/Makefile.am
@@ -0,0 +1,17 @@
+h_sources = IQService.h \
+            IQClient.h
+
+cpp_sources = QService.cpp \
+              IQService.cpp \
+              IQClient.cpp \
+              IQHDMIClient.cpp
+
+library_includedir = $(includedir)
+library_include_HEADERS = $(h_sources)
+
+lib_LTLIBRARIES = libqservice.la
+libqservice_la_CC = @CC@
+libqservice_la_SOURCES = $(cpp_sources)
+libqservice_la_CFLAGS = $(COMMON_CFLAGS) -DLOG_TAG=\"qdqservice\"
+libqservice_la_CPPFLAGS = $(AM_CPPFLAGS)
+libqservice_LDADD = -lhardware -lcutils -llog -lbinder
\ No newline at end of file
diff --git a/sdm/include/core/display_interface.h b/sdm/include/core/display_interface.h
index bb89d1d..ccaa0b5 100644
--- a/sdm/include/core/display_interface.h
+++ b/sdm/include/core/display_interface.h
@@ -118,6 +118,20 @@
   kContentQualityMax,
 };
 
+/*! @brief This enum represents the display port.
+
+  @sa DisplayInterface::GetDisplayPort
+*/
+enum DisplayPort {
+  kPortDefault,
+  kPortDSI,        // Display is connected to DSI port.
+  kPortDTV,        // Display is connected to DTV port
+  kPortWriteBack,  // Display is connected to writeback port
+  kPortLVDS,       // Display is connected to LVDS port
+  kPortEDP,        // Display is connected to EDP port
+  kPortDP,         // Display is connected to DP port.
+};
+
 /*! @brief This structure defines configuration for fixed properties of a display device.
 
   @sa DisplayInterface::GetConfig
@@ -573,6 +587,20 @@
   */
   virtual DisplayError SetDetailEnhancerData(const DisplayDetailEnhancerData &de_data) = 0;
 
+  /*! @brief Method to get display port information.
+
+    @param[out] port \link DisplayPort \endlink
+
+    @return \link DisplayError \endlink
+  */
+  virtual DisplayError GetDisplayPort(DisplayPort *port) = 0;
+
+  /*! @brief Method to query whether it is Primrary device.
+
+    @return \link Bool \endlink
+  */
+  virtual bool IsPrimaryDisplay() = 0;
+
  protected:
   virtual ~DisplayInterface() { }
 };
diff --git a/sdm/include/core/layer_buffer.h b/sdm/include/core/layer_buffer.h
index 801938d..0bf1aa4 100644
--- a/sdm/include/core/layer_buffer.h
+++ b/sdm/include/core/layer_buffer.h
@@ -259,7 +259,8 @@
   LayerBufferFlags flags;       //!< Flags associated with this buffer.
 
   LayerBufferS3DFormat s3d_format = kS3dFormatNone;
-                                //!< Represents the format of the buffer content in 3D.
+                                //!< Represents the format of the buffer content in 3D. This field
+                                //!< could be modified by both client and SDM.
   uint64_t buffer_id __attribute__((aligned(8))) = 0;
                                 //!< Specifies the buffer id.
 };
diff --git a/sdm/include/core/layer_stack.h b/sdm/include/core/layer_stack.h
index 7493418..0fcab25 100644
--- a/sdm/include/core/layer_stack.h
+++ b/sdm/include/core/layer_stack.h
@@ -64,35 +64,65 @@
   @sa Layer
 */
 enum LayerComposition {
+  /* ==== List of composition types set by SDM === */
+  /* These composition types represent SDM composition decision for the layers which need to
+     be blended. Composition types are set during Prepare() by SDM.
+     Client can set default composition type to any of the below before calling into Prepare(),
+     however client's input value is ignored and does not play any role in composition decision.
+  */
   kCompositionGPU,          //!< This layer will be drawn onto the target buffer by GPU. Display
-                            //!< device will mark the layer for GPU composition if it can not handle
-                            //!< it completely.
+                            //!< device will mark the layer for GPU composition if it can not
+                            //!< handle composition for it.
+                            //!< This composition type is used only if GPUTarget layer is provided
+                            //!< in a composition cycle.
 
-  kCompositionSDE,          //!< This layer will be handled by SDE. It must not be composed by GPU.
+  kCompositionGPUS3D,       //!< This layer will be drawn onto the target buffer in s3d mode by GPU.
+                            //!< Display device will mark the layer for GPU composition if it can
+                            //!< not handle composition for it.
+                            //!< This composition type is used only if GPUTarget layer is provided
+                            //!< in a composition cycle.
 
-  kCompositionHWCursor,     //!< This layer will be handled by SDE using HWCursor. It must not be
-                            //!< composed by GPU
+  kCompositionSDE,          //!< This layer will be composed by SDE. It must not be composed by
+                            //!< GPU or Blit.
 
-  kCompositionHybrid,       //!< This layer will be drawn by a blit engine and SDE together. Display
-                            //!< device will split the layer, update the blit rectangle that
-                            //!< need to be composed by a blit engine and update original source
-                            //!< rectangle that will be composed by SDE.
+  kCompositionHWCursor,     //!< This layer will be composed by SDE using HW Cursor. It must not be
+                            //!< composed by GPU or Blit.
 
-  kCompositionBlit,         //!< This layer will be composed using Blit Engine
+  kCompositionHybrid,       //!< This layer will be drawn by a blit engine and SDE together.
+                            //!< Display device will split the layer, update the blit rectangle
+                            //!< that need to be composed by a blit engine and update original
+                            //!< source rectangle that will be composed by SDE.
+                            //!< This composition type is used only if GPUTarget and BlitTarget
+                            //!< layers are provided in a composition cycle.
 
+  kCompositionBlit,         //!< This layer will be composed using Blit Engine.
+                            //!< This composition type is used only if BlitTarget layer is provided
+                            //!< in a composition cycle.
+
+  /* === List of composition types set by Client === */
+  /* These composition types represent target buffer layers onto which GPU or Blit will draw if SDM
+     decide to have some or all layers drawn by respective composition engine.
+     If client does not provide a target buffer layer, SDM will assume that respective composition
+     engine is not available and will not mark any layer for such a composition. If SDM is unable
+     to handle layers without support of such a composition engine, Prepare() call will return
+     failure.
+  */
   kCompositionGPUTarget,    //!< This layer will hold result of composition for layers marked for
                             //!< GPU composition.
-                            //!< If display device does not set any layer for SDE composition then
-                            //!< this would be ignored during Commit().
+                            //!< If display device does not set any layer for GPU composition then
+                            //!< this layer would be ignored. Else, this layer will be composed
+                            //!< with other layers marked for SDE composition by SDE.
                             //!< Only one layer shall be marked as target buffer by the caller.
-                            //!< GPU target layer shall be after application layers in layer stack.
+                            //!< GPU target layer shall be placed after all application layers
+                            //!< in the layer stack.
 
   kCompositionBlitTarget,   //!< This layer will hold result of composition for blit rectangles
                             //!< from the layers marked for hybrid composition. Nth blit rectangle
                             //!< in a layer shall be composed onto Nth blit target.
                             //!< If display device does not set any layer for hybrid composition
-                            //!< then this would be ignored during Commit().
-                            //!< Blit target layers shall be after GPU target layer in layer stack.
+                            //!< then this would be ignored.
+                            //!< Blit target layers shall be placed after GPUTarget in the layer
+                            //!< stack.
 };
 
 /*! @brief This structure defines rotation and flip values for a display layer.
diff --git a/sdm/include/private/color_params.h b/sdm/include/private/color_params.h
index 8bca55f..fdd0c9e 100644
--- a/sdm/include/private/color_params.h
+++ b/sdm/include/private/color_params.h
@@ -50,6 +50,7 @@
   kSetPanelBrightness = BITMAP(5),
   kEnableFrameCapture = BITMAP(6),
   kDisableFrameCapture = BITMAP(7),
+  kConfigureDetailedEnhancer = BITMAP(8),
   kNoAction = BITMAP(31),
 };
 
@@ -102,8 +103,9 @@
   static const uint32_t kSDEGamutV17 = 9;
   static const uint32_t kSDEPaV17 = 11;
   static const uint32_t kSDEPccV17 = 13;
-  static const uint32_t kSDEPADitherV17 = 15;
-  static const uint32_t kSDELegacyPP = 17;
+  static const uint32_t kSDELegacyPP = 15;
+  static const uint32_t kSDEPADitherV17 = 16;
+  static const uint32_t kSDEIgcV30 = 17;
 
   uint32_t version[kMaxNumPPFeatures];
   PPFeatureVersion() { memset(version, 0, sizeof(version)); }
@@ -143,16 +145,16 @@
     return ret;
   }
 
-  DisplayError CreatePayloadBytes(uint8_t *output, uint32_t size_in_bytes) {
+  DisplayError CreatePayloadBytes(uint32_t size_in_bytes, uint8_t **output) {
     DisplayError ret = kErrorNone;
 
     payload = new uint8_t[size_in_bytes]();
     if (!payload) {
       ret = kErrorMemory;
-      output = NULL;
+      *output = NULL;
     } else {
       this->size = size_in_bytes;
-      output = payload;
+      *output = payload;
       own_payload = true;
     }
     return ret;
@@ -198,6 +200,46 @@
   uint32_t buffer_size;
 };
 
+static const uint32_t kDeTuningFlagSharpFactor = 0x01;
+static const uint32_t kDeTuningFlagClip = 0x02;
+static const uint32_t kDeTuningFlagThrQuiet = 0x04;
+static const uint32_t kDeTuningFlagThrDieout = 0x08;
+static const uint32_t kDeTuningFlagThrLow = 0x10;
+static const uint32_t kDeTuningFlagThrHigh = 0x20;
+static const uint32_t kDeTuningFlagContentQualLevel = 0x40;
+
+typedef enum {
+  kDeContentQualUnknown,
+  kDeContentQualLow,
+  kDeContentQualMedium,
+  kDeContentQualHigh,
+  kDeContentQualMax,
+} PPDEContentQualLevel;
+
+typedef enum {
+  kDeContentTypeUnknown,
+  kDeContentTypeVideo,
+  kDeContentTypeGraphics,
+  kDeContentTypeMax,
+} PPDEContentType;
+
+struct PPDETuningCfg {
+  uint32_t flags = 0;
+  int32_t sharp_factor = 0;
+  uint16_t thr_quiet = 0;
+  uint16_t thr_dieout = 0;
+  uint16_t thr_low = 0;
+  uint16_t thr_high = 0;
+  uint16_t clip = 0;
+  PPDEContentQualLevel quality = kDeContentQualUnknown;
+  PPDEContentType content_type = kDeContentTypeUnknown;
+};
+
+struct PPDETuningCfgData {
+  uint32_t cfg_en = 0;
+  PPDETuningCfg params;
+};
+
 struct SDEGamutCfg {
   static const int kGamutTableNum = 4;
   static const int kGamutScaleoffTableNum = 3;
@@ -246,7 +288,7 @@
 };
 
 struct SDEPADitherData {
-  uint32_t data_flags;
+  uint64_t data_flags;
   uint32_t matrix_size;
   uint64_t matrix_data_addr;
   uint32_t strength;
@@ -307,6 +349,15 @@
   uint32_t *c2_data = NULL;
 };
 
+struct SDEIgcV30LUTData {
+  static const int kMaxIgcLUTEntries = 256;
+  uint32_t table_fmt = 0;
+  uint32_t len = 0;
+  uint64_t c0_c1_data = 0;
+  uint64_t c2_data = 0;
+  uint32_t strength = 0;
+};
+
 struct SDEPgcLUTData {
   static const int kPgcLUTEntries = 1024;
   uint32_t len = 0;
@@ -377,6 +428,22 @@
   uint32_t *buffer_ = NULL;
 };
 
+class SDEIgcV30LUTWrapper : private SDEIgcV30LUTData {
+ public:
+  static SDEIgcV30LUTWrapper *Init(uint32_t arg __attribute__((__unused__)));
+  ~SDEIgcV30LUTWrapper() {
+    if (buffer_)
+      delete[] buffer_;
+  }
+  inline SDEIgcV30LUTData *GetConfig(void) { return this; }
+
+ private:
+  SDEIgcV30LUTWrapper(const SDEIgcV30LUTWrapper& src) { /* do not create copies */ }
+  SDEIgcV30LUTWrapper& operator=(const SDEIgcV30LUTWrapper&) { return *this; }
+  SDEIgcV30LUTWrapper() {}
+  uint32_t *buffer_ = NULL;
+};
+
 class SDEPgcLUTWrapper : private SDEPgcLUTData {
  public:
   static SDEPgcLUTWrapper *Init(uint32_t arg __attribute__((__unused__)));
@@ -466,6 +533,7 @@
 
   inline Locker &GetLocker(void) { return locker_; }
   inline PPFrameCaptureData *GetFrameCaptureData(void) { return &frame_capture_data; }
+  inline PPDETuningCfgData *GetDETuningCfgData(void) { return &de_tuning_data_; }
   // Once all features are consumed, destroy/release all TFeatureInfo<T> on the list,
   // then clear dirty_ flag and return the lock to the TFeatureInfo<T> producer.
   void Reset();
@@ -482,6 +550,7 @@
   PPFeatureInfo *feature_[kMaxNumPPFeatures];  // reference to TFeatureInfo<T>.
   uint32_t next_idx_ = 0;
   PPFrameCaptureData frame_capture_data;
+  PPDETuningCfgData de_tuning_data_;
 };
 
 }  // namespace sdm
diff --git a/sdm/include/private/hw_info_types.h b/sdm/include/private/hw_info_types.h
index e806d92..4ae696d 100644
--- a/sdm/include/private/hw_info_types.h
+++ b/sdm/include/private/hw_info_types.h
@@ -34,6 +34,8 @@
 #include <bitset>
 
 namespace sdm {
+using std::string;
+
 const int kMaxSDELayers = 16;   // Maximum number of layers that can be handled by hardware in a
                                 // given layer stack.
 #define MAX_PLANES 4
@@ -63,15 +65,6 @@
   kModeCommand,
 };
 
-enum HWDisplayPort {
-  kPortDefault,
-  kPortDSI,
-  kPortDTv,
-  kPortWriteBack,
-  kPortLVDS,
-  kPortEDP,
-};
-
 enum PipeType {
   kPipeTypeUnused,
   kPipeTypeVIG,
@@ -110,6 +103,11 @@
   kMultiRectParallelMode = 0x04,
 };
 
+enum HWAVRModes {
+  kContinuousMode,  // Mode to enable AVR feature for every frame.
+  kOneShotMode,     // Mode to enable AVR feature for particular frame.
+};
+
 typedef std::map<HWSubBlockType, std::vector<LayerBufferFormat>> FormatsMap;
 
 struct HWDynBwLimitInfo {
@@ -188,6 +186,7 @@
   FormatsMap supported_formats_map;
   HWRotatorInfo hw_rot_info;
   HWDestScalarInfo hw_dest_scalar_info;
+  bool has_avr = false;
 
   void Reset() { *this = HWResourceInfo(); }
 };
@@ -215,7 +214,7 @@
 };
 
 struct HWPanelInfo {
-  HWDisplayPort port = kPortDefault;  // Display port
+  DisplayPort port = kPortDefault;    // Display port
   HWDisplayMode mode = kModeDefault;  // Display mode
   bool partial_update = false;        // Partial update feature
   int left_align = 0;                 // ROI left alignment restriction
@@ -226,6 +225,7 @@
   int min_roi_height = 0;             // Min height needed for ROI
   bool needs_roi_merge = false;       // Merge ROI's of both the DSI's
   bool dynamic_fps = false;           // Panel Supports dynamic fps
+  bool dfps_porch_mode = false;       // dynamic fps VFP or HFP mode
   uint32_t min_fps = 0;               // Min fps supported by panel
   uint32_t max_fps = 0;               // Max fps supported by panel
   bool is_primary_panel = false;      // Panel is primary display
@@ -244,6 +244,7 @@
             (min_roi_height != panel_info.min_roi_height) ||
             (needs_roi_merge != panel_info.needs_roi_merge) ||
             (dynamic_fps != panel_info.dynamic_fps) || (min_fps != panel_info.min_fps) ||
+            (dfps_porch_mode != panel_info.dfps_porch_mode) ||
             (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));
@@ -386,6 +387,11 @@
 
 typedef std::map<uint32_t, HWDestScaleInfo *> DestScaleInfoMap;
 
+struct HWAVRInfo {
+  bool enable = false;                // Flag to Enable AVR feature
+  HWAVRModes mode = kContinuousMode;  // Specifies the AVR mode
+};
+
 struct HWPipeInfo {
   uint32_t pipe_id = 0;
   HWSubBlockType sub_block_type = kHWSubBlockMax;
@@ -412,6 +418,8 @@
 
 struct HWLayersInfo {
   LayerStack *stack = NULL;        // Input layer stack. Set by the caller.
+  uint32_t app_layer_count = 0;    // Total number of app layers. Must not be 0.
+  uint32_t gpu_target_index = 0;   // GPU target layer index. 0 if not present.
 
   uint32_t index[kMaxSDELayers];   // Indexes of the layers from the layer stack which need to be
                                    // programmed on hardware.
@@ -436,6 +444,7 @@
   float output_compression = 1.0f;
   uint32_t bandwidth = 0;
   uint32_t clock = 0;
+  HWAVRInfo hw_avr_info = {};
 };
 
 struct HWDisplayAttributes : DisplayConfigVariableInfo {
diff --git a/sdm/include/utils/debug.h b/sdm/include/utils/debug.h
index 23ba181..a0d8967 100644
--- a/sdm/include/utils/debug.h
+++ b/sdm/include/utils/debug.h
@@ -69,11 +69,14 @@
   static bool IsRotatorDownScaleDisabled();
   static bool IsDecimationDisabled();
   static int GetMaxPipesPerMixer(DisplayType display_type);
+  static int GetMaxVideoUpscale();
   static bool IsVideoModeEnabled();
   static bool IsRotatorUbwcDisabled();
   static bool IsRotatorSplitDisabled();
   static bool IsScalarDisabled();
   static bool IsUbwcTiledFrameBuffer();
+  static bool IsAVRDisabled();
+  static bool IsExtAnimDisabled();
   static bool GetProperty(const char *property_name, char *value);
   static bool SetProperty(const char *property_name, const char *value);
 
diff --git a/sdm/include/utils/locker.h b/sdm/include/utils/locker.h
index fffe634..0096098 100644
--- a/sdm/include/utils/locker.h
+++ b/sdm/include/utils/locker.h
@@ -146,7 +146,7 @@
     ts.tv_sec = tv.tv_sec + ms/1000;
     ts.tv_nsec = tv.tv_usec*1000 + (ms%1000)*1000000;
     ts.tv_sec += ts.tv_nsec/1000000000L;
-    ts.tv_nsec += ts.tv_nsec%1000000000L;
+    ts.tv_nsec %= 1000000000L;
     return pthread_cond_timedwait(&condition_, &mutex_, &ts);
   }
 
diff --git a/sdm/include/utils/sys.h b/sdm/include/utils/sys.h
index c06b7f8..b90007a 100644
--- a/sdm/include/utils/sys.h
+++ b/sdm/include/utils/sys.h
@@ -49,7 +49,11 @@
 #endif
 
   // Pointers to system calls which are either mapped to actual system call or virtual driver.
+#ifdef TARGET_HEADLESS
+  typedef int (*ioctl)(int, unsigned long int, ...);  // NOLINT
+#else
   typedef int (*ioctl)(int, int, ...);
+#endif
   typedef int (*open)(const char *, int, ...);
   typedef int (*close)(int);
   typedef int (*poll)(struct pollfd *, nfds_t, int);
diff --git a/sdm/libs/core/Android.mk b/sdm/libs/core/Android.mk
index 5e88683..08d81b4 100644
--- a/sdm/libs/core/Android.mk
+++ b/sdm/libs/core/Android.mk
@@ -5,12 +5,9 @@
 LOCAL_MODULE                  := libsdmcore
 LOCAL_MODULE_TAGS             := optional
 LOCAL_C_INCLUDES              := $(common_includes) $(kernel_includes)
-LOCAL_CFLAGS                  := -Wno-missing-field-initializers -Wno-unused-parameter \
-                                 -std=c++11 -fcolor-diagnostics\
-                                 -DLOG_TAG=\"SDM\" $(common_flags)
-LOCAL_CLANG                   := true
+LOCAL_CFLAGS                  := -Wno-unused-parameter -DLOG_TAG=\"SDM\" $(common_flags)
 LOCAL_HW_INTF_PATH            := fb
-LOCAL_SHARED_LIBRARIES        := libdl libsdmutils libc++
+LOCAL_SHARED_LIBRARIES        := libdl libsdmutils
 LOCAL_ADDITIONAL_DEPENDENCIES := $(common_deps) $(kernel_deps)
 LOCAL_SRC_FILES               := core_interface.cpp \
                                  core_impl.cpp \
diff --git a/sdm/libs/core/Makefile.am b/sdm/libs/core/Makefile.am
new file mode 100644
index 0000000..8dbbe2f
--- /dev/null
+++ b/sdm/libs/core/Makefile.am
@@ -0,0 +1,43 @@
+HEADER_PATH := ${WORKSPACE}/display/display-hal/sdm/include
+
+c_sources = core_interface.cpp \
+            core_impl.cpp \
+            display_base.cpp \
+            display_primary.cpp \
+            display_hdmi.cpp \
+            display_virtual.cpp \
+            comp_manager.cpp \
+            strategy.cpp \
+            resource_default.cpp \
+            dump_impl.cpp \
+            color_manager.cpp \
+            fb/hw_info.cpp \
+            fb/hw_device.cpp \
+            fb/hw_primary.cpp \
+            fb/hw_hdmi.cpp \
+            fb/hw_virtual.cpp \
+            fb/hw_color_manager.cpp \
+            fb/hw_scale.cpp \
+            fb/hw_events.cpp
+
+core_h_sources = $(HEADER_PATH)/core/*.h
+
+core_includedir = $(includedir)/sdm/core
+core_include_HEADERS = $(core_h_sources)
+
+private_h_sources = $(HEADER_PATH)/private/*.h
+
+private_includedir = $(includedir)/sdm/private
+private_include_HEADERS = $(private_h_sources)
+
+utils_h_sources = $(HEADER_PATH)/utils/*.h
+
+utils_includedir = $(includedir)/sdm/utils
+utils_include_HEADERS = $(utils_h_sources)
+
+lib_LTLIBRARIES = libsdmcore.la
+libsdmcore_la_CC = @CC@
+libsdmcore_la_SOURCES = $(c_sources)
+libsdmcore_la_CFLAGS = $(COMMON_CFLAGS) -DLOG_TAG=\"SDM\"
+libsdmcore_la_CPPFLAGS = $(AM_CPPFLAGS)
+libsdmcore_la_LIBADD = ../utils/libsdmutils.la
\ No newline at end of file
diff --git a/sdm/libs/core/display_base.cpp b/sdm/libs/core/display_base.cpp
index 2f6e577..bd2d7d3 100644
--- a/sdm/libs/core/display_base.cpp
+++ b/sdm/libs/core/display_base.cpp
@@ -130,34 +130,45 @@
   }
 
   comp_manager_->UnregisterDisplay(display_comp_ctx_);
-
   HWEventsInterface::Destroy(hw_events_intf_);
+  HWInterface::Destroy(hw_intf_);
 
   return kErrorNone;
 }
 
-DisplayError DisplayBase::ValidateGPUTarget(LayerStack *layer_stack) {
-  uint32_t i = 0;
-  std::vector<Layer *>layers = layer_stack->layers;
+DisplayError DisplayBase::BuildLayerStackStats(LayerStack *layer_stack) {
+  std::vector<Layer *> &layers = layer_stack->layers;
+  HWLayersInfo &hw_layers_info = hw_layers_.info;
 
-  // TODO(user): Remove this check once we have query display attributes on virtual display
-  if (display_type_ == kVirtual) {
-    return kErrorNone;
-  }
-  uint32_t layer_count = UINT32(layers.size());
-  while ((i < layer_count) && (layers.at(i)->composition != kCompositionGPUTarget)) {
-    i++;
+  hw_layers_info.stack = layer_stack;
+
+  for (auto &layer : layers) {
+    if (layer->composition == kCompositionGPUTarget) {
+      hw_layers_info.gpu_target_index = hw_layers_info.app_layer_count;
+      break;
+    }
+    hw_layers_info.app_layer_count++;
   }
 
-  if (i >= layer_count) {
-    DLOGE("Either layer count is zero or GPU target layer is not present");
+  DLOGV_IF(kTagNone, "LayerStack layer_count: %d, app_layer_count: %d, gpu_target_index: %d, "
+           "display type: %d", layers.size(), hw_layers_info.app_layer_count,
+           hw_layers_info.gpu_target_index, display_type_);
+
+  if (!hw_layers_info.app_layer_count) {
+    DLOGE("Layer count is zero");
     return kErrorParameters;
   }
 
-  uint32_t gpu_target_index = i;
+  if (hw_layers_info.gpu_target_index) {
+    return ValidateGPUTargetParams();
+  }
 
-  // Check GPU target layer
-  Layer *gpu_target_layer = layers.at(gpu_target_index);
+  return kErrorNone;
+}
+
+DisplayError DisplayBase::ValidateGPUTargetParams() {
+  HWLayersInfo &hw_layers_info = hw_layers_.info;
+  Layer *gpu_target_layer = hw_layers_info.stack->layers.at(hw_layers_info.gpu_target_index);
 
   if (!IsValid(gpu_target_layer->src_rect)) {
     DLOGE("Invalid src rect for GPU target layer");
@@ -184,9 +195,9 @@
 
   if (gpu_target_layer_dst_xpixels > mixer_attributes_.width ||
     gpu_target_layer_dst_ypixels > mixer_attributes_.height) {
-    DLOGE("GPU target layer dst rect is not with in limits gpu wxh %fx%f mixer wxh %dx%d",
-    gpu_target_layer_dst_xpixels, gpu_target_layer_dst_ypixels, mixer_attributes_.width,
-    mixer_attributes_.height);
+    DLOGE("GPU target layer dst rect is not with in limits gpu wxh %fx%f, mixer wxh %dx%d",
+                  gpu_target_layer_dst_xpixels, gpu_target_layer_dst_ypixels,
+                  mixer_attributes_.width, mixer_attributes_.height);
     return kErrorParameters;
   }
 
@@ -205,7 +216,7 @@
     return kErrorParameters;
   }
 
-  error = ValidateGPUTarget(layer_stack);
+  error = BuildLayerStackStats(layer_stack);
   if (error != kErrorNone) {
     return error;
   }
@@ -219,11 +230,6 @@
     disable_pu_one_frame_ = false;
   }
 
-  // Clean hw layers for reuse.
-  hw_layers_ = HWLayers();
-  hw_layers_.info.stack = layer_stack;
-  hw_layers_.output_compression = 1.0f;
-
   comp_manager_->PrePrepare(display_comp_ctx_, &hw_layers_);
   while (true) {
     error = comp_manager_->Prepare(display_comp_ctx_, &hw_layers_);
@@ -1046,4 +1052,22 @@
   return kErrorNone;
 }
 
+DisplayError DisplayBase::GetDisplayPort(DisplayPort *port) {
+  lock_guard<recursive_mutex> obj(recursive_mutex_);
+
+  if (!port) {
+    return kErrorParameters;
+  }
+
+  *port = hw_panel_info_.port;
+
+  return kErrorNone;
+}
+
+bool DisplayBase::IsPrimaryDisplay() {
+  lock_guard<recursive_mutex> obj(recursive_mutex_);
+
+  return hw_panel_info_.is_primary_panel;
+}
+
 }  // namespace sdm
diff --git a/sdm/libs/core/display_base.h b/sdm/libs/core/display_base.h
index 7fdb714..2bc94b7 100644
--- a/sdm/libs/core/display_base.h
+++ b/sdm/libs/core/display_base.h
@@ -109,14 +109,18 @@
   virtual DisplayError SetFrameBufferConfig(const DisplayConfigVariableInfo &variable_info);
   virtual DisplayError GetFrameBufferConfig(DisplayConfigVariableInfo *variable_info);
   virtual DisplayError SetDetailEnhancerData(const DisplayDetailEnhancerData &de_data);
+  virtual DisplayError GetDisplayPort(DisplayPort *port);
+  virtual bool IsPrimaryDisplay();
 
  protected:
+  DisplayError BuildLayerStackStats(LayerStack *layer_stack);
+  virtual DisplayError ValidateGPUTargetParams();
+
   // DumpImpl method
   void AppendDump(char *buffer, uint32_t length);
 
   bool IsRotationRequired(HWLayers *hw_layers);
   const char *GetName(const LayerComposition &composition);
-  DisplayError ValidateGPUTarget(LayerStack *layer_stack);
   DisplayError ReconfigureDisplay();
   bool NeedsMixerReconfiguration(LayerStack *layer_stack, uint32_t *new_mixer_width,
                                  uint32_t *new_mixer_height);
diff --git a/sdm/libs/core/display_hdmi.cpp b/sdm/libs/core/display_hdmi.cpp
index e09959f..3c3d9f4 100644
--- a/sdm/libs/core/display_hdmi.cpp
+++ b/sdm/libs/core/display_hdmi.cpp
@@ -31,7 +31,6 @@
 #include "display_hdmi.h"
 #include "hw_interface.h"
 #include "hw_info_interface.h"
-#include "fb/hw_hdmi.h"
 
 #define __CLASS__ "DisplayHDMI"
 
@@ -47,8 +46,8 @@
 DisplayError DisplayHDMI::Init() {
   lock_guard<recursive_mutex> obj(recursive_mutex_);
 
-  DisplayError error = HWHDMI::Create(&hw_intf_, hw_info_intf_,
-                                      DisplayBase::buffer_sync_handler_);
+  DisplayError error = HWInterface::Create(kHDMI, hw_info_intf_, buffer_sync_handler_,
+                                           &hw_intf_);
   if (error != kErrorNone) {
     return error;
   }
@@ -65,12 +64,12 @@
 
   error = hw_intf_->SetDisplayAttributes(active_mode_index);
   if (error != kErrorNone) {
-    HWHDMI::Destroy(hw_intf_);
+    HWInterface::Destroy(hw_intf_);
   }
 
   error = DisplayBase::Init();
   if (error != kErrorNone) {
-    HWHDMI::Destroy(hw_intf_);
+    HWInterface::Destroy(hw_intf_);
     return error;
   }
 
@@ -91,22 +90,13 @@
   error = HWEventsInterface::Create(INT(display_type_), this, &event_list_, &hw_events_intf_);
   if (error != kErrorNone) {
     DisplayBase::Deinit();
-    HWHDMI::Destroy(hw_intf_);
+    HWInterface::Destroy(hw_intf_);
     DLOGE("Failed to create hardware events interface. Error = %d", error);
   }
 
   return error;
 }
 
-DisplayError DisplayHDMI::Deinit() {
-  lock_guard<recursive_mutex> obj(recursive_mutex_);
-
-  DisplayError error = DisplayBase::Deinit();
-  HWHDMI::Destroy(hw_intf_);
-
-  return error;
-}
-
 DisplayError DisplayHDMI::Prepare(LayerStack *layer_stack) {
   lock_guard<recursive_mutex> obj(recursive_mutex_);
   DisplayError error = kErrorNone;
@@ -124,6 +114,9 @@
 
   SetS3DMode(layer_stack);
 
+  // Clean hw layers for reuse.
+  hw_layers_ = HWLayers();
+
   return DisplayBase::Prepare(layer_stack);
 }
 
@@ -154,7 +147,7 @@
     return error;
   }
 
-  return kErrorNone;
+  return DisplayBase::ReconfigureDisplay();
 }
 
 bool DisplayHDMI::IsUnderscanSupported() {
diff --git a/sdm/libs/core/display_hdmi.h b/sdm/libs/core/display_hdmi.h
index 3a3c0dc..091cdc3 100644
--- a/sdm/libs/core/display_hdmi.h
+++ b/sdm/libs/core/display_hdmi.h
@@ -41,7 +41,6 @@
               BufferSyncHandler *buffer_sync_handler, CompManager *comp_manager,
               RotatorInterface *rotator_intf);
   virtual DisplayError Init();
-  virtual DisplayError Deinit();
   virtual DisplayError Prepare(LayerStack *layer_stack);
   virtual DisplayError GetRefreshRateRange(uint32_t *min_refresh_rate, uint32_t *max_refresh_rate);
   virtual DisplayError SetRefreshRate(uint32_t refresh_rate);
diff --git a/sdm/libs/core/display_primary.cpp b/sdm/libs/core/display_primary.cpp
index ad1d3d6..e8689ea 100644
--- a/sdm/libs/core/display_primary.cpp
+++ b/sdm/libs/core/display_primary.cpp
@@ -33,7 +33,6 @@
 #include "display_primary.h"
 #include "hw_interface.h"
 #include "hw_info_interface.h"
-#include "fb/hw_primary.h"
 
 #define __CLASS__ "DisplayPrimary"
 
@@ -49,16 +48,15 @@
 DisplayError DisplayPrimary::Init() {
   lock_guard<recursive_mutex> obj(recursive_mutex_);
 
-  DisplayError error = HWPrimary::Create(&hw_intf_, hw_info_intf_,
-                                         DisplayBase::buffer_sync_handler_);
-
+  DisplayError error = HWInterface::Create(kPrimary, hw_info_intf_, buffer_sync_handler_,
+                                           &hw_intf_);
   if (error != kErrorNone) {
     return error;
   }
 
   error = DisplayBase::Init();
   if (error != kErrorNone) {
-    HWPrimary::Destroy(hw_intf_);
+    HWInterface::Destroy(hw_intf_);
     return error;
   }
 
@@ -72,25 +70,18 @@
     }
   }
 
+  avr_prop_disabled_ = Debug::IsAVRDisabled();
+
   error = HWEventsInterface::Create(INT(display_type_), this, &event_list_, &hw_events_intf_);
   if (error != kErrorNone) {
     DLOGE("Failed to create hardware events interface. Error = %d", error);
     DisplayBase::Deinit();
-    HWPrimary::Destroy(hw_intf_);
+    HWInterface::Destroy(hw_intf_);
   }
 
   return error;
 }
 
-DisplayError DisplayPrimary::Deinit() {
-  lock_guard<recursive_mutex> obj(recursive_mutex_);
-
-  DisplayError error = DisplayBase::Deinit();
-  HWPrimary::Destroy(hw_intf_);
-
-  return error;
-}
-
 DisplayError DisplayPrimary::Prepare(LayerStack *layer_stack) {
   lock_guard<recursive_mutex> obj(recursive_mutex_);
   DisplayError error = kErrorNone;
@@ -106,6 +97,10 @@
     }
   }
 
+  // Clean hw layers for reuse.
+  hw_layers_ = HWLayers();
+  hw_layers_.hw_avr_info.enable = NeedsAVREnable();
+
   return DisplayBase::Prepare(layer_stack);
 }
 
@@ -305,5 +300,15 @@
   return kErrorNone;
 }
 
+bool DisplayPrimary::NeedsAVREnable() {
+  if (avr_prop_disabled_) {
+    return false;
+  }
+
+  return (hw_panel_info_.mode == kModeVideo && ((hw_panel_info_.dynamic_fps &&
+          hw_panel_info_.dfps_porch_mode) || (!hw_panel_info_.dynamic_fps &&
+          hw_panel_info_.min_fps != hw_panel_info_.max_fps)));
+}
+
 }  // namespace sdm
 
diff --git a/sdm/libs/core/display_primary.h b/sdm/libs/core/display_primary.h
index 962f00c..7a03005 100644
--- a/sdm/libs/core/display_primary.h
+++ b/sdm/libs/core/display_primary.h
@@ -40,7 +40,6 @@
                  BufferSyncHandler *buffer_sync_handler, CompManager *comp_manager,
                  RotatorInterface *rotator_intf);
   virtual DisplayError Init();
-  virtual DisplayError Deinit();
   virtual DisplayError Prepare(LayerStack *layer_stack);
   virtual DisplayError Commit(LayerStack *layer_stack);
   virtual DisplayError ControlPartialUpdate(bool enable, uint32_t *pending);
@@ -61,9 +60,12 @@
   virtual void CECMessage(char *message) { }
 
  private:
+  bool NeedsAVREnable();
+
   uint32_t idle_timeout_ms_ = 0;
   std::vector<const char *> event_list_ = {"vsync_event", "show_blank_event", "idle_notify",
                                            "msm_fb_thermal_level", "thread_exit"};
+  bool avr_prop_disabled_ = false;
 };
 
 }  // namespace sdm
diff --git a/sdm/libs/core/display_virtual.cpp b/sdm/libs/core/display_virtual.cpp
index f835ea4..6beea5c 100644
--- a/sdm/libs/core/display_virtual.cpp
+++ b/sdm/libs/core/display_virtual.cpp
@@ -28,7 +28,6 @@
 #include "display_virtual.h"
 #include "hw_interface.h"
 #include "hw_info_interface.h"
-#include "fb/hw_virtual.h"
 
 #define __CLASS__ "DisplayVirtual"
 
@@ -44,8 +43,8 @@
 DisplayError DisplayVirtual::Init() {
   lock_guard<recursive_mutex> obj(recursive_mutex_);
 
-  DisplayError error = HWVirtual::Create(&hw_intf_, hw_info_intf_,
-                                         DisplayBase::buffer_sync_handler_);
+  DisplayError error = HWInterface::Create(kVirtual, hw_info_intf_, buffer_sync_handler_,
+                                           &hw_intf_);
   if (error != kErrorNone) {
     return error;
   }
@@ -54,21 +53,12 @@
 
   error = DisplayBase::Init();
   if (error != kErrorNone) {
-    HWVirtual::Destroy(hw_intf_);
+    HWInterface::Destroy(hw_intf_);
   }
 
   return error;
 }
 
-DisplayError DisplayVirtual::Deinit() {
-  lock_guard<recursive_mutex> obj(recursive_mutex_);
-
-  DisplayError error = DisplayBase::Deinit();
-  HWVirtual::Destroy(hw_intf_);
-
-  return error;
-}
-
 DisplayError DisplayVirtual::GetNumVariableInfoConfigs(uint32_t *count) {
   lock_guard<recursive_mutex> obj(recursive_mutex_);
   *count = 1;
@@ -140,5 +130,15 @@
   return kErrorNone;
 }
 
+DisplayError DisplayVirtual::Prepare(LayerStack *layer_stack) {
+  lock_guard<recursive_mutex> obj(recursive_mutex_);
+
+  // Clean hw layers for reuse.
+  hw_layers_ = HWLayers();
+
+  return DisplayBase::Prepare(layer_stack);
+}
+
+
 }  // namespace sdm
 
diff --git a/sdm/libs/core/display_virtual.h b/sdm/libs/core/display_virtual.h
index 69af7f0..d6ce915 100644
--- a/sdm/libs/core/display_virtual.h
+++ b/sdm/libs/core/display_virtual.h
@@ -39,7 +39,7 @@
                  BufferSyncHandler *buffer_sync_handler, CompManager *comp_manager,
                  RotatorInterface *rotator_intf);
   virtual DisplayError Init();
-  virtual DisplayError Deinit();
+  virtual DisplayError Prepare(LayerStack *layer_stack);
   virtual DisplayError GetNumVariableInfoConfigs(uint32_t *count);
   virtual DisplayError GetConfig(uint32_t index, DisplayConfigVariableInfo *variable_info);
   virtual DisplayError GetActiveConfig(uint32_t *index);
@@ -62,6 +62,11 @@
   virtual DisplayError SetDetailEnhancerData(const DisplayDetailEnhancerData &de_data) {
     return kErrorNotSupported;
   }
+  virtual DisplayError ValidateGPUTargetParams() {
+    // TODO(user): Validate GPU target for virtual display when query display attributes
+    // on virtual display is functional.
+    return kErrorNone;
+  }
 };
 
 }  // namespace sdm
diff --git a/sdm/libs/core/fb/hw_color_manager.cpp b/sdm/libs/core/fb/hw_color_manager.cpp
index 27116a0..a6c78b0 100644
--- a/sdm/libs/core/fb/hw_color_manager.cpp
+++ b/sdm/libs/core/fb/hw_color_manager.cpp
@@ -153,9 +153,13 @@
 DisplayError HWColorManager::SetPADither(const PPFeatureInfo &feature,
                                          msmfb_mdp_pp *kernel_params) {
   DisplayError ret = kErrorNone;
-
-  // TODO(user): Kernel IOCTL preparation
-
+#ifdef PA_DITHER
+  kernel_params->op = mdp_op_pa_dither_cfg;
+  kernel_params->data.dither_cfg_data.version = feature.feature_version_;
+  kernel_params->data.dither_cfg_data.block = MDP_LOGICAL_BLOCK_DISP_0 + feature.disp_id_;
+  kernel_params->data.dither_cfg_data.flags = feature.enable_flags_;
+  kernel_params->data.dither_cfg_data.cfg_payload = feature.GetConfigData();
+#endif
   return ret;
 }
 
diff --git a/sdm/libs/core/fb/hw_device.cpp b/sdm/libs/core/fb/hw_device.cpp
index 6cb919d..5b1bc80 100644
--- a/sdm/libs/core/fb/hw_device.cpp
+++ b/sdm/libs/core/fb/hw_device.cpp
@@ -48,6 +48,9 @@
 #include <string>
 
 #include "hw_device.h"
+#include "hw_primary.h"
+#include "hw_hdmi.h"
+#include "hw_virtual.h"
 #include "hw_info_interface.h"
 
 #define __CLASS__ "HWDevice"
@@ -58,6 +61,46 @@
 
 namespace sdm {
 
+DisplayError HWInterface::Create(DisplayType type, HWInfoInterface *hw_info_intf,
+                                        BufferSyncHandler *buffer_sync_handler,
+                                        HWInterface **intf) {
+  DisplayError error = kErrorNone;
+  HWDevice *hw = nullptr;
+
+  switch (type) {
+    case kPrimary:
+      hw = new HWPrimary(buffer_sync_handler, hw_info_intf);
+      break;
+    case kHDMI:
+      hw = new HWHDMI(buffer_sync_handler, hw_info_intf);
+      break;
+    case kVirtual:
+      hw = new HWVirtual(buffer_sync_handler, hw_info_intf);
+      break;
+    default:
+      DLOGE("Undefined display type");
+      return kErrorUndefined;
+  }
+
+  error = hw->Init();
+  if (error != kErrorNone) {
+    delete hw;
+    DLOGE("Init on HW Intf type %d failed", type);
+    return error;
+  }
+  *intf = hw;
+
+  return error;
+}
+
+DisplayError HWInterface::Destroy(HWInterface *intf) {
+  HWDevice *hw = static_cast<HWDevice *>(intf);
+  hw->Deinit();
+  delete hw;
+
+  return kErrorNone;
+}
+
 HWDevice::HWDevice(BufferSyncHandler *buffer_sync_handler)
   : fb_node_index_(-1), fb_path_("/sys/devices/virtual/graphics/fb"),
     buffer_sync_handler_(buffer_sync_handler), synchronous_commit_(false) {
@@ -477,6 +520,8 @@
 
     if (hw_rotator_session->hw_block_count) {
       input_buffer = &hw_rotator_session->output_buffer;
+      input_buffer->release_fence_fd = Sys::dup_(mdp_commit.release_fence);
+      continue;
     }
 
     // Make sure the release fence is duplicated only once for each buffer.
@@ -798,6 +843,8 @@
         panel_info->needs_roi_merge = atoi(tokens[1]);
       } else if (!strncmp(tokens[0], "dyn_fps_en", strlen("dyn_fps_en"))) {
         panel_info->dynamic_fps = atoi(tokens[1]);
+      } else if (!strncmp(tokens[0], "dfps_porch_mode", strlen("dfps_porch_mode"))) {
+        panel_info->dfps_porch_mode = atoi(tokens[1]);
       } else if (!strncmp(tokens[0], "min_fps", strlen("min_fps"))) {
         panel_info->min_fps = UINT32(atoi(tokens[1]));
       } else if (!strncmp(tokens[0], "max_fps", strlen("max_fps"))) {
@@ -810,13 +857,16 @@
     }
   }
 
-  GetHWDisplayPortAndMode(device_node, &panel_info->port, &panel_info->mode);
+  GetHWDisplayPortAndMode(device_node, panel_info);
   GetSplitInfo(device_node, panel_info);
   GetHWPanelNameByNode(device_node, panel_info);
   GetHWPanelMaxBrightnessFromNode(panel_info);
 }
 
-void HWDevice::GetHWDisplayPortAndMode(int device_node, HWDisplayPort *port, HWDisplayMode *mode) {
+void HWDevice::GetHWDisplayPortAndMode(int device_node, HWPanelInfo *panel_info) {
+  DisplayPort *port = &panel_info->port;
+  HWDisplayMode *mode = &panel_info->mode;
+
   *port = kPortDefault;
   *mode = kModeDefault;
 
@@ -846,11 +896,14 @@
     *port = kPortEDP;
     *mode = kModeVideo;
   } else if ((strncmp(line.c_str(), "dtv panel", strlen("dtv panel")) == 0)) {
-    *port = kPortDTv;
+    *port = kPortDTV;
     *mode = kModeVideo;
   } else if ((strncmp(line.c_str(), "writeback panel", strlen("writeback panel")) == 0)) {
     *port = kPortWriteBack;
     *mode = kModeCommand;
+  } else if ((strncmp(line.c_str(), "dp panel", strlen("dp panel")) == 0)) {
+    *port = kPortDP;
+    *mode = kModeVideo;
   }
 
   return;
@@ -1057,6 +1110,10 @@
 DisplayError HWDevice::SetVSyncState(bool enable) {
   int vsync_on = enable ? 1 : 0;
   if (Sys::ioctl_(device_fd_, MSMFB_OVERLAY_VSYNC_CTRL, &vsync_on) < 0) {
+    if (errno == ESHUTDOWN) {
+      DLOGI_IF(kTagDriverConfig, "Driver is processing shutdown sequence");
+      return kErrorShutDown;
+    }
     IOCTL_LOGE(MSMFB_OVERLAY_VSYNC_CTRL, device_type_);
     return kErrorHardware;
   }
@@ -1145,6 +1202,10 @@
   cfg.payload = reinterpret_cast<uint64_t>(&mdp_lut_info);
 
   if (Sys::ioctl_(device_fd_, MSMFB_MDP_SET_CFG, &cfg) < 0) {
+    if (errno == ESHUTDOWN) {
+      DLOGI_IF(kTagDriverConfig, "Driver is processing shutdown sequence");
+      return kErrorShutDown;
+    }
     IOCTL_LOGE(MSMFB_MDP_SET_CFG, device_type_);
     return kErrorHardware;
   }
diff --git a/sdm/libs/core/fb/hw_device.h b/sdm/libs/core/fb/hw_device.h
index d82a420..e2e146e 100644
--- a/sdm/libs/core/fb/hw_device.h
+++ b/sdm/libs/core/fb/hw_device.h
@@ -49,9 +49,13 @@
 class HWInfoInterface;
 
 class HWDevice : public HWInterface {
+ public:
+  virtual ~HWDevice() {}
+  virtual DisplayError Init();
+  virtual DisplayError Deinit();
+
  protected:
   explicit HWDevice(BufferSyncHandler *buffer_sync_handler);
-  virtual ~HWDevice() {}
 
   // From HWInterface
   virtual DisplayError GetActiveConfig(uint32_t *active_config);
@@ -89,10 +93,6 @@
   virtual DisplayError SetMixerAttributes(const HWMixerAttributes &mixer_attributes);
   virtual DisplayError GetMixerAttributes(HWMixerAttributes *mixer_attributes);
 
-  // For HWDevice derivatives
-  virtual DisplayError Init();
-  virtual DisplayError Deinit();
-
   enum {
     kHWEventVSync,
     kHWEventBlank,
@@ -115,7 +115,7 @@
   void PopulateHWPanelInfo();
   void GetHWPanelInfoByNode(int device_node, HWPanelInfo *panel_info);
   void GetHWPanelNameByNode(int device_node, HWPanelInfo *panel_info);
-  void GetHWDisplayPortAndMode(int device_node, HWDisplayPort *port, HWDisplayMode *mode);
+  void GetHWDisplayPortAndMode(int device_node, HWPanelInfo *panel_info);
   void GetSplitInfo(int device_node, HWPanelInfo *panel_info);
   void GetHWPanelMaxBrightnessFromNode(HWPanelInfo *panel_info);
   int ParseLine(const char *input, char *tokens[], const uint32_t max_token, uint32_t *count);
diff --git a/sdm/libs/core/fb/hw_events.cpp b/sdm/libs/core/fb/hw_events.cpp
index 5ae53a4..4015796 100644
--- a/sdm/libs/core/fb/hw_events.cpp
+++ b/sdm/libs/core/fb/hw_events.cpp
@@ -80,7 +80,7 @@
 pollfd HWEvents::InitializePollFd(HWEventData *event_data) {
   char node_path[kMaxStringLength] = {0};
   char data[kMaxStringLength] = {0};
-  pollfd poll_fd;
+  pollfd poll_fd = {0};
   poll_fd.fd = -1;
 
   if (!strncmp(event_data->event_name, "thread_exit", strlen("thread_exit"))) {
diff --git a/sdm/libs/core/fb/hw_hdmi.cpp b/sdm/libs/core/fb/hw_hdmi.cpp
index d9116e6..e825272 100644
--- a/sdm/libs/core/fb/hw_hdmi.cpp
+++ b/sdm/libs/core/fb/hw_hdmi.cpp
@@ -79,29 +79,6 @@
   return true;
 }
 
-DisplayError HWHDMI::Create(HWInterface **intf, HWInfoInterface *hw_info_intf,
-                            BufferSyncHandler *buffer_sync_handler) {
-  DisplayError error = kErrorNone;
-  HWHDMI *hw_fb_hdmi = NULL;
-
-  hw_fb_hdmi = new HWHDMI(buffer_sync_handler, hw_info_intf);
-  error = hw_fb_hdmi->Init();
-  if (error != kErrorNone) {
-    delete hw_fb_hdmi;
-  } else {
-    *intf = hw_fb_hdmi;
-  }
-  return error;
-}
-
-DisplayError HWHDMI::Destroy(HWInterface *intf) {
-  HWHDMI *hw_fb_hdmi = static_cast<HWHDMI *>(intf);
-  hw_fb_hdmi->Deinit();
-  delete hw_fb_hdmi;
-
-  return kErrorNone;
-}
-
 HWHDMI::HWHDMI(BufferSyncHandler *buffer_sync_handler,  HWInfoInterface *hw_info_intf)
   : HWDevice(buffer_sync_handler), hw_scan_info_(), active_config_index_(0) {
   HWDevice::device_type_ = kDeviceHDMI;
@@ -141,6 +118,12 @@
 
   ReadScanInfo();
 
+  error = GetPanelS3DMode();
+  if (error != kErrorNone) {
+    Deinit();
+    return error;
+  }
+
   s3d_mode_sdm_to_mdp_.insert(std::pair<HWS3DMode, msm_hdmi_s3d_mode>
                              (kS3DModeNone, HDMI_S3D_NONE));
   s3d_mode_sdm_to_mdp_.insert(std::pair<HWS3DMode, msm_hdmi_s3d_mode>
@@ -155,10 +138,6 @@
   return error;
 }
 
-DisplayError HWHDMI::Deinit() {
-  return HWDevice::Deinit();
-}
-
 DisplayError HWHDMI::GetNumDisplayAttributes(uint32_t *count) {
   *count = UINT32(hdmi_modes_.size());
   if (*count <= 0) {
@@ -691,17 +670,140 @@
   hw_panel_info_.s3d_mode = s3d_mode;
   Sys::close_(s3d_mode_node);
 
-  DLOGI_IF(kTagDriverConfig, "s3d mode %d", hw_panel_info_.s3d_mode);
+  DLOGI_IF(kTagDriverConfig, "Set s3d mode %d", hw_panel_info_.s3d_mode);
+  return kErrorNone;
+}
+
+DisplayError HWHDMI::GetPanelS3DMode() {
+  ssize_t length = -1;
+  char s3d_mode_path[kMaxStringLength] = {'\0'};
+  char s3d_mode_string[kMaxStringLength] = {'\0'};
+  snprintf(s3d_mode_path, sizeof(s3d_mode_path), "%s%d/s3d_mode", fb_path_, fb_node_index_);
+  int panel_s3d_mode = 0;
+
+  int s3d_mode_node = Sys::open_(s3d_mode_path, O_RDWR);
+  if (s3d_mode_node < 0) {
+    DLOGE("%s could not be opened : %s", s3d_mode_path, strerror(errno));
+    return kErrorNotSupported;
+  }
+
+  length = Sys::pread_(s3d_mode_node, s3d_mode_string, sizeof(s3d_mode_string), 0);
+  if (length <= 0) {
+    DLOGE("Failed read s3d node: %s", strerror(errno));
+    Sys::close_(s3d_mode_node);
+    return kErrorNotSupported;
+  }
+
+  panel_s3d_mode = atoi(s3d_mode_string);
+  if (panel_s3d_mode < HDMI_S3D_NONE || panel_s3d_mode >= HDMI_S3D_MAX) {
+    Sys::close_(s3d_mode_node);
+    DLOGW("HDMI panel S3D mode is not supported panel_s3d_mode = %d", panel_s3d_mode);
+    return kErrorUndefined;
+  }
+
+  active_mdp_s3d_mode_  = static_cast<msm_hdmi_s3d_mode>(panel_s3d_mode);
+  Sys::close_(s3d_mode_node);
+
+  DLOGI_IF(kTagDriverConfig, "Get HDMI panel s3d mode %d", active_mdp_s3d_mode_);
+  return kErrorNone;
+}
+
+DisplayError HWHDMI::GetDynamicFrameRateMode(uint32_t refresh_rate, uint32_t *mode,
+                                             DynamicFPSData *data, uint32_t *config_index) {
+  msm_hdmi_mode_timing_info *cur = NULL;
+  msm_hdmi_mode_timing_info *dst = NULL;
+  uint32_t i = 0;
+  int pre_refresh_rate_diff = 0;
+  bool pre_unstd_mode = false;
+
+  for (i = 0; i < hdmi_modes_.size(); i++) {
+    msm_hdmi_mode_timing_info *timing_mode = &supported_video_modes_[i];
+    if (timing_mode->video_format == hdmi_modes_[active_config_index_]) {
+      cur = timing_mode;
+      break;
+    }
+  }
+
+  if (cur == NULL) {
+    DLOGE("can't find timing info for active config index(%d)", active_config_index_);
+    return kErrorUndefined;
+  }
+
+  if (cur->refresh_rate != frame_rate_) {
+    pre_unstd_mode = true;
+  }
+
+  if (i >= hdmi_modes_.size()) {
+    return kErrorNotSupported;
+  }
+
+  dst = cur;
+  pre_refresh_rate_diff = static_cast<int>(dst->refresh_rate) - static_cast<int>(refresh_rate);
+
+  for (i = 0; i < hdmi_modes_.size(); i++) {
+    msm_hdmi_mode_timing_info *timing_mode = &supported_video_modes_[i];
+    if (cur->active_h == timing_mode->active_h &&
+       cur->active_v == timing_mode->active_v &&
+       cur->pixel_formats == timing_mode->pixel_formats ) {
+      int cur_refresh_rate_diff = static_cast<int>(timing_mode->refresh_rate) -
+                                  static_cast<int>(refresh_rate);
+      if (abs(pre_refresh_rate_diff) > abs(cur_refresh_rate_diff)) {
+        pre_refresh_rate_diff = cur_refresh_rate_diff;
+        dst = timing_mode;
+      }
+    }
+  }
+
+  if (pre_refresh_rate_diff > kThresholdRefreshRate) {
+    return kErrorNotSupported;
+  }
+
+  GetConfigIndex(dst->video_format, config_index);
+
+  data->hor_front_porch = dst->front_porch_h;
+  data->hor_back_porch = dst->back_porch_h;
+  data->hor_pulse_width = dst->pulse_width_h;
+  data->clk_rate_hz = dst->pixel_freq;
+  data->fps = refresh_rate;
+
+  if (dst->front_porch_h != cur->front_porch_h) {
+    *mode = kModeHFP;
+  }
+
+  if (dst->refresh_rate != refresh_rate || dst->pixel_freq != cur->pixel_freq) {
+    if (*mode == kModeHFP) {
+      if (dst->refresh_rate != refresh_rate) {
+        *mode = kModeHFPCalcClock;
+      } else {
+        *mode = kModeClockHFP;
+      }
+    } else {
+        *mode = kModeClock;
+    }
+  }
+
+  if (pre_unstd_mode && (*mode == kModeHFP)) {
+    *mode = kModeClockHFP;
+  }
+
   return kErrorNone;
 }
 
 DisplayError HWHDMI::SetRefreshRate(uint32_t refresh_rate) {
   char mode_path[kMaxStringLength] = {0};
   char node_path[kMaxStringLength] = {0};
-  uint32_t mode = kModeHFP;
+  uint32_t mode = kModeClock;
+  uint32_t config_index = 0;
+  DynamicFPSData data;
+  DisplayError error = kErrorNone;
 
   if (refresh_rate == frame_rate_) {
-    return kErrorNone;
+    return error;
+  }
+
+  error = GetDynamicFrameRateMode(refresh_rate, &mode, &data, &config_index);
+  if (error != kErrorNone) {
+    return error;
   }
 
   snprintf(mode_path, sizeof(mode_path), "%s%d/msm_fb_dfps_mode", fb_path_, fb_node_index_);
@@ -709,7 +811,7 @@
 
   int fd_mode = Sys::open_(mode_path, O_WRONLY);
   if (fd_mode < 0) {
-    DLOGE("Failed to open %s with error %s", node_path, strerror(errno));
+    DLOGE("Failed to open %s with error %s", mode_path, strerror(errno));
     return kErrorFileDescriptor;
   }
 
@@ -731,8 +833,14 @@
   }
 
   char refresh_rate_string[kMaxStringLength];
-  snprintf(refresh_rate_string, sizeof(refresh_rate_string), "%d", refresh_rate);
-  DLOGI_IF(kTagDriverConfig, "Setting refresh rate = %d", refresh_rate);
+  if (mode == kModeHFP || mode == kModeClock) {
+    snprintf(refresh_rate_string, sizeof(refresh_rate_string), "%d", data.fps);
+    DLOGI_IF(kTagDriverConfig, "Setting refresh rate = %d", data.fps);
+  } else {
+    snprintf(refresh_rate_string, sizeof(refresh_rate_string), "%d %d %d %d %d",
+             data.hor_front_porch, data.hor_back_porch, data.hor_pulse_width,
+             data.clk_rate_hz, data.fps);
+  }
   len = Sys::pwrite_(fd_node, refresh_rate_string, strlen(refresh_rate_string), 0);
   if (len < 0) {
     DLOGE("Failed to write %d with error %s", refresh_rate, strerror(errno));
@@ -741,15 +849,21 @@
   }
   Sys::close_(fd_node);
 
-  DisplayError error = ReadTimingInfo();
+  error = ReadTimingInfo();
   if (error != kErrorNone) {
     return error;
   }
 
-  GetDisplayAttributes(active_config_index_, &display_attributes_);
+  GetDisplayAttributes(config_index, &display_attributes_);
   UpdateMixerAttributes();
 
   frame_rate_ = refresh_rate;
+  active_config_index_ = config_index;
+
+  DLOGI_IF(kTagDriverConfig, "config_index(%d) Mode(%d) frame_rate(%d)",
+           config_index,
+           mode,
+           frame_rate_);
 
   return kErrorNone;
 }
diff --git a/sdm/libs/core/fb/hw_hdmi.h b/sdm/libs/core/fb/hw_hdmi.h
index d2bd658..ce9e597 100644
--- a/sdm/libs/core/fb/hw_hdmi.h
+++ b/sdm/libs/core/fb/hw_hdmi.h
@@ -37,9 +37,7 @@
 
 class HWHDMI : public HWDevice {
  public:
-  static DisplayError Create(HWInterface **intf, HWInfoInterface *hw_info_intf,
-                             BufferSyncHandler *buffer_sync_handler);
-  static DisplayError Destroy(HWInterface *intf);
+  HWHDMI(BufferSyncHandler *buffer_sync_handler, HWInfoInterface *hw_info_intf);
 
  protected:
   enum HWFramerateUpdate {
@@ -51,12 +49,30 @@
     kModeVFP,
     // Switch framerate by tuning horizontal front porch
     kModeHFP,
+    // Switch framerate by tuning horizontal front porch and clock
+    kModeClockHFP,
+    // Switch framerate by tuning horizontal front porch and re-caculate clock
+    kModeHFPCalcClock,
     kModeMAX
   };
 
-  HWHDMI(BufferSyncHandler *buffer_sync_handler, HWInfoInterface *hw_info_intf);
+  /**
+   * struct DynamicFPSData - defines dynamic fps related data
+   * @hor_front_porch: horizontal front porch
+   * @hor_back_porch: horizontal back porch
+   * @hor_pulse_width: horizontal pulse width
+   * @clk_rate_hz: panel clock rate in HZ
+   * @fps: frames per second
+   */
+  struct DynamicFPSData {
+    uint32_t hor_front_porch;
+    uint32_t hor_back_porch;
+    uint32_t hor_pulse_width;
+    uint32_t clk_rate_hz;
+    uint32_t fps;
+  };
+
   virtual DisplayError Init();
-  virtual DisplayError Deinit();
   virtual DisplayError GetNumDisplayAttributes(uint32_t *count);
   // Requirement to call this only after the first config has been explicitly set by client
   virtual DisplayError GetActiveConfig(uint32_t *active_config);
@@ -82,11 +98,15 @@
   bool ReadResolutionFile(char *config_buffer);
   bool IsResolutionFilePresent();
   void SetSourceProductInformation(const char *node, const char *name);
-  DisplayError GetDisplayS3DSupport(uint32_t num_modes,
+  DisplayError GetDisplayS3DSupport(uint32_t index,
                                     HWDisplayAttributes *attrib);
+  DisplayError GetPanelS3DMode();
   bool IsSupportedS3DMode(HWS3DMode s3d_mode);
   void UpdateMixerAttributes();
 
+  DisplayError GetDynamicFrameRateMode(uint32_t refresh_rate, uint32_t*mode,
+                                       DynamicFPSData *data, uint32_t *config_index);
+  static const int kThresholdRefreshRate = 1000;
   vector<uint32_t> hdmi_modes_;
   // Holds the hdmi timing information. Ex: resolution, fps etc.,
   vector<msm_hdmi_mode_timing_info> supported_video_modes_;
@@ -94,7 +114,7 @@
   uint32_t active_config_index_;
   std::map<HWS3DMode, msm_hdmi_s3d_mode> s3d_mode_sdm_to_mdp_;
   vector<HWS3DMode> supported_s3d_modes_;
-  int active_mdp_s3d_mode_ = HDMI_S3D_NONE;
+  msm_hdmi_s3d_mode active_mdp_s3d_mode_ = HDMI_S3D_NONE;
   uint32_t frame_rate_ = 0;
 };
 
diff --git a/sdm/libs/core/fb/hw_info.cpp b/sdm/libs/core/fb/hw_info.cpp
index dc01e39..81d81a3 100644
--- a/sdm/libs/core/fb/hw_info.cpp
+++ b/sdm/libs/core/fb/hw_info.cpp
@@ -249,6 +249,8 @@
             hw_resource->has_qseed3 = true;
           } else if (!strncmp(tokens[i], "concurrent_writeback", strlen("concurrent_writeback"))) {
             hw_resource->has_concurrent_writeback = true;
+          } else if (!strncmp(tokens[i], "avr", strlen("avr"))) {
+            hw_resource->has_avr = true;
           }
         }
       } else if (!strncmp(tokens[0], "pipe_count", strlen("pipe_count"))) {
diff --git a/sdm/libs/core/fb/hw_primary.cpp b/sdm/libs/core/fb/hw_primary.cpp
index 09e7f80..1659625 100644
--- a/sdm/libs/core/fb/hw_primary.cpp
+++ b/sdm/libs/core/fb/hw_primary.cpp
@@ -57,36 +57,20 @@
 #define MDP_COMMIT_CWB_DSPP 0x1000
 #endif
 
+#ifndef MDP_COMMIT_AVR_EN
+#define MDP_COMMIT_AVR_EN 0x08
+#endif
+
+#ifndef MDP_COMMIT_AVR_ONE_SHOT_MODE
+#define MDP_COMMIT_AVR_ONE_SHOT_MODE 0x10
+#endif
+
 namespace sdm {
 
 using std::string;
 using std::to_string;
 using std::fstream;
 
-DisplayError HWPrimary::Create(HWInterface **intf, HWInfoInterface *hw_info_intf,
-                               BufferSyncHandler *buffer_sync_handler) {
-  DisplayError error = kErrorNone;
-  HWPrimary *hw_primary = NULL;
-
-  hw_primary = new HWPrimary(buffer_sync_handler, hw_info_intf);
-  error = hw_primary->Init();
-  if (error != kErrorNone) {
-    delete hw_primary;
-  } else {
-    *intf = hw_primary;
-  }
-
-  return error;
-}
-
-DisplayError HWPrimary::Destroy(HWInterface *intf) {
-  HWPrimary *hw_primary = static_cast<HWPrimary *>(intf);
-  hw_primary->Deinit();
-  delete hw_primary;
-
-  return kErrorNone;
-}
-
 HWPrimary::HWPrimary(BufferSyncHandler *buffer_sync_handler, HWInfoInterface *hw_info_intf)
   : HWDevice(buffer_sync_handler) {
   HWDevice::device_type_ = kDevicePrimary;
@@ -168,6 +152,8 @@
   string line;
   while (Sys::getline_(fs, line)) {
     DisplayConfigVariableInfo config;
+    // std::getline (unlike ::getline) removes \n while driver expects it in mode, so add back
+    line += '\n';
     size_t xpos = line.find(':');
     size_t ypos = line.find('x');
 
@@ -188,10 +174,6 @@
   }
 }
 
-DisplayError HWPrimary::Deinit() {
-  return HWDevice::Deinit();
-}
-
 DisplayError HWPrimary::GetNumDisplayAttributes(uint32_t *count) {
   *count = IsResolutionSwitchEnabled() ? UINT32(display_configs_.size()) : 1;
   return kErrorNone;
@@ -417,6 +399,10 @@
     DLOGI_IF(kTagDriverConfig, "****************************************************************");
   }
 
+  if (hw_resource_.has_avr) {
+    SetAVRFlags(hw_layers->hw_avr_info, &mdp_commit.flags);
+  }
+
   return HWDevice::Validate(hw_layers);
 }
 
@@ -511,7 +497,7 @@
 }
 
 DisplayError HWPrimary::SetPanelBrightness(int level) {
-  char buffer[MAX_SYSFS_COMMAND_LENGTH] = {0};
+  char buffer[kMaxSysfsCommandLength] = {0};
 
   DLOGV_IF(kTagDriverConfig, "Set brightness level to %d", level);
   int fd = Sys::open_(kBrightnessNode, O_RDWR);
@@ -521,7 +507,7 @@
     return kErrorFileDescriptor;
   }
 
-  int32_t bytes = snprintf(buffer, MAX_SYSFS_COMMAND_LENGTH, "%d\n", level);
+  int32_t bytes = snprintf(buffer, kMaxSysfsCommandLength, "%d\n", level);
   if (bytes < 0) {
     DLOGV_IF(kTagDriverConfig, "Failed to copy new brightness level = %d", level);
     Sys::close_(fd);
@@ -585,7 +571,12 @@
 DisplayError HWPrimary::GetPPFeaturesVersion(PPFeatureVersion *vers) {
   mdp_pp_feature_version version = {};
 
+#ifdef PA_DITHER
+  uint32_t feature_id_mapping[kMaxNumPPFeatures] = { PCC, IGC, GC, GC, PA,
+                                                     DITHER, GAMUT, PA_DITHER };
+#else
   uint32_t feature_id_mapping[kMaxNumPPFeatures] = { PCC, IGC, GC, GC, PA, DITHER, GAMUT };
+#endif
 
   for (int i(0); i < kMaxNumPPFeatures; i++) {
     version.pp_feature = feature_id_mapping[i];
@@ -648,5 +639,15 @@
       hw_panel_info_.split_info.left_split : mixer_attributes_.width;
 }
 
+void HWPrimary::SetAVRFlags(const HWAVRInfo &hw_avr_info, uint32_t *avr_flags) {
+  if (hw_avr_info.enable) {
+    *avr_flags |= MDP_COMMIT_AVR_EN;
+  }
+
+  if (hw_avr_info.mode == kOneShotMode) {
+    *avr_flags |= MDP_COMMIT_AVR_ONE_SHOT_MODE;
+  }
+}
+
 }  // namespace sdm
 
diff --git a/sdm/libs/core/fb/hw_primary.h b/sdm/libs/core/fb/hw_primary.h
index 18e9d72..ae45318 100644
--- a/sdm/libs/core/fb/hw_primary.h
+++ b/sdm/libs/core/fb/hw_primary.h
@@ -32,19 +32,13 @@
 #include "hw_device.h"
 
 namespace sdm {
-#define MAX_SYSFS_COMMAND_LENGTH 12
-struct DisplayConfigVariableInfo;
 
 class HWPrimary : public HWDevice {
  public:
-  static DisplayError Create(HWInterface **intf, HWInfoInterface *hw_info_intf,
-                             BufferSyncHandler *buffer_sync_handler);
-  static DisplayError Destroy(HWInterface *intf);
+  HWPrimary(BufferSyncHandler *buffer_sync_handler, HWInfoInterface *hw_info_intf);
 
  protected:
-  HWPrimary(BufferSyncHandler *buffer_sync_handler, HWInfoInterface *hw_info_intf);
   virtual DisplayError Init();
-  virtual DisplayError Deinit();
   virtual DisplayError GetNumDisplayAttributes(uint32_t *count);
   virtual DisplayError GetActiveConfig(uint32_t *active_config);
   virtual DisplayError GetDisplayAttributes(uint32_t index,
@@ -74,11 +68,16 @@
     kModeLPMCommand,
   };
 
+  enum {
+    kMaxSysfsCommandLength = 12,
+  };
+
   DisplayError PopulateDisplayAttributes();
   void InitializeConfigs();
   bool IsResolutionSwitchEnabled() { return !display_configs_.empty(); }
   bool GetCurrentModeFromSysfs(size_t *curr_x_pixels, size_t *curr_y_pixels);
   void UpdateMixerAttributes();
+  void SetAVRFlags(const HWAVRInfo &hw_avr_info, uint32_t *avr_flags);
 
   std::vector<DisplayConfigVariableInfo> display_configs_;
   std::vector<std::string> display_config_strings_;
diff --git a/sdm/libs/core/fb/hw_virtual.cpp b/sdm/libs/core/fb/hw_virtual.cpp
index d297efa..455d0d2 100644
--- a/sdm/libs/core/fb/hw_virtual.cpp
+++ b/sdm/libs/core/fb/hw_virtual.cpp
@@ -34,30 +34,6 @@
 
 namespace sdm {
 
-DisplayError HWVirtual::Create(HWInterface **intf, HWInfoInterface *hw_info_intf,
-                               BufferSyncHandler *buffer_sync_handler) {
-  DisplayError error = kErrorNone;
-  HWVirtual *hw_virtual = NULL;
-
-  hw_virtual = new HWVirtual(buffer_sync_handler, hw_info_intf);
-  error = hw_virtual->Init();
-  if (error != kErrorNone) {
-    delete hw_virtual;
-  } else {
-    *intf = hw_virtual;
-  }
-
-  return error;
-}
-
-DisplayError HWVirtual::Destroy(HWInterface *intf) {
-  HWVirtual *hw_virtual = static_cast<HWVirtual *>(intf);
-  hw_virtual->Deinit();
-  delete hw_virtual;
-
-  return kErrorNone;
-}
-
 HWVirtual::HWVirtual(BufferSyncHandler *buffer_sync_handler, HWInfoInterface *hw_info_intf)
   : HWDevice(buffer_sync_handler) {
   HWDevice::device_type_ = kDeviceVirtual;
diff --git a/sdm/libs/core/fb/hw_virtual.h b/sdm/libs/core/fb/hw_virtual.h
index c083127..eb82731 100644
--- a/sdm/libs/core/fb/hw_virtual.h
+++ b/sdm/libs/core/fb/hw_virtual.h
@@ -31,9 +31,7 @@
 
 class HWVirtual : public HWDevice {
  public:
-  static DisplayError Create(HWInterface **intf, HWInfoInterface *hw_info_intf,
-                             BufferSyncHandler *buffer_sync_handler);
-  static DisplayError Destroy(HWInterface *intf);
+  HWVirtual(BufferSyncHandler *buffer_sync_handler, HWInfoInterface *hw_info_intf);
   virtual DisplayError SetVSyncState(bool enable) { return kErrorNotSupported; }
   virtual DisplayError SetMixerAttributes(const HWMixerAttributes &mixer_attributes) {
     return kErrorNotSupported;
@@ -42,7 +40,6 @@
   virtual DisplayError SetDisplayAttributes(const HWDisplayAttributes &display_attributes);
 
  protected:
-  HWVirtual(BufferSyncHandler *buffer_sync_handler, HWInfoInterface *hw_info_intf);
   virtual DisplayError Init();
   virtual DisplayError Validate(HWLayers *hw_layers);
 };
diff --git a/sdm/libs/core/hw_interface.h b/sdm/libs/core/hw_interface.h
index 56a1513..da3ac4d 100644
--- a/sdm/libs/core/hw_interface.h
+++ b/sdm/libs/core/hw_interface.h
@@ -31,6 +31,8 @@
 #include <utils/constants.h>
 #include <core/buffer_sync_handler.h>
 
+#include "hw_info_interface.h"
+
 namespace sdm {
 
 enum HWScanSupport {
@@ -64,6 +66,10 @@
 
 class HWInterface {
  public:
+  static DisplayError Create(DisplayType type, HWInfoInterface *hw_info_intf,
+                             BufferSyncHandler *buffer_sync_handler, HWInterface **intf);
+  static DisplayError Destroy(HWInterface *intf);
+
   virtual DisplayError GetActiveConfig(uint32_t *active_config) = 0;
   virtual DisplayError GetNumDisplayAttributes(uint32_t *count) = 0;
   virtual DisplayError GetDisplayAttributes(uint32_t index,
diff --git a/sdm/libs/core/strategy.cpp b/sdm/libs/core/strategy.cpp
index 8519f7e..7a983e5 100644
--- a/sdm/libs/core/strategy.cpp
+++ b/sdm/libs/core/strategy.cpp
@@ -80,19 +80,6 @@
   hw_layers_info_ = hw_layers_info;
   extn_start_success_ = false;
   tried_default_ = false;
-  uint32_t i = 0;
-  LayerStack *layer_stack = hw_layers_info_->stack;
-  uint32_t layer_count = UINT32(layer_stack->layers.size());
-  for (; i < layer_count; i++) {
-    if (layer_stack->layers.at(i)->composition == kCompositionGPUTarget) {
-      fb_layer_index_ = i;
-      break;
-    }
-  }
-
-  if (i == layer_count) {
-    return kErrorUndefined;
-  }
 
   if (partial_update_intf_) {
     partial_update_intf_->ControlPartialUpdate(partial_update_enable);
@@ -130,6 +117,11 @@
     }
   }
 
+  // Default composition is not possible if GPU composition is not supported.
+  if (!hw_layers_info_->gpu_target_index) {
+    return kErrorNotSupported;
+  }
+
   // Default composition is already tried.
   if (tried_default_) {
     return kErrorUndefined;
@@ -141,25 +133,17 @@
   uint32_t &hw_layer_count = hw_layers_info_->count;
   hw_layer_count = 0;
 
-  for (uint32_t i = 0; i < layer_stack->layers.size(); i++) {
-    Layer *layer = layer_stack->layers.at(i);
-    LayerComposition &composition = layer->composition;
-    if (composition == kCompositionGPUTarget) {
-      hw_layers_info_->updated_src_rect[hw_layer_count] = layer->src_rect;
-      hw_layers_info_->updated_dst_rect[hw_layer_count] = layer->dst_rect;
-      hw_layers_info_->index[hw_layer_count++] = i;
-    } else if (composition != kCompositionBlitTarget) {
-      composition = kCompositionGPU;
-    }
+  for (uint32_t i = 0; i < hw_layers_info_->app_layer_count; i++) {
+    layer_stack->layers.at(i)->composition = kCompositionGPU;
   }
 
+  Layer *gpu_target_layer = layer_stack->layers.at(hw_layers_info_->gpu_target_index);
+  hw_layers_info_->updated_src_rect[hw_layer_count] = gpu_target_layer->src_rect;
+  hw_layers_info_->updated_dst_rect[hw_layer_count] = gpu_target_layer->dst_rect;
+  hw_layers_info_->index[hw_layer_count++] = hw_layers_info_->gpu_target_index;
+
   tried_default_ = true;
 
-  // There can be one and only one GPU target buffer.
-  if (hw_layer_count != 1) {
-    return kErrorParameters;
-  }
-
   return kErrorNone;
 }
 
diff --git a/sdm/libs/core/strategy.h b/sdm/libs/core/strategy.h
index b284d61..8b4b6f4 100644
--- a/sdm/libs/core/strategy.h
+++ b/sdm/libs/core/strategy.h
@@ -62,7 +62,6 @@
   HWMixerAttributes mixer_attributes_ = {};
   HWDisplayAttributes display_attributes_ = {};
   DisplayConfigVariableInfo fb_config_ = {};
-  uint32_t fb_layer_index_ = 0;
   bool extn_start_success_ = false;
   bool tried_default_ = false;
 };
diff --git a/sdm/libs/hwc/hwc_color_manager.cpp b/sdm/libs/hwc/hwc_color_manager.cpp
index 203ab09..acf5f37 100644
--- a/sdm/libs/hwc/hwc_color_manager.cpp
+++ b/sdm/libs/hwc/hwc_color_manager.cpp
@@ -343,14 +343,12 @@
 
   if (enable) {
     std::memset(&buffer_info, 0x00, sizeof(buffer_info));
-    hwc_display->GetFrameBufferResolution(&buffer_info.buffer_config.width,
-                                          &buffer_info.buffer_config.height);
+    hwc_display->GetPanelResolution(&buffer_info.buffer_config.width,
+                                    &buffer_info.buffer_config.height);
     if (frame_capture_data->input_params.out_pix_format == PP_PIXEL_FORMAT_RGB_888) {
       buffer_info.buffer_config.format = kFormatRGB888;
     } else if (frame_capture_data->input_params.out_pix_format == PP_PIXEL_FORMAT_RGB_2101010) {
-      // TODO(user): Complete the implementation
-      DLOGE("RGB 10-bit format NOT supported");
-      return -EFAULT;
+      buffer_info.buffer_config.format = kFormatRGBA1010102;
     } else {
       DLOGE("Pixel-format: %d NOT support.", frame_capture_data->input_params.out_pix_format);
       return -EFAULT;
@@ -370,7 +368,7 @@
     ret = buffer_allocator_->AllocateBuffer(&buffer_info);
     if (ret != 0) {
       DLOGE("Buffer allocation failed. ret: %d", ret);
-      delete[] buffer_allocator_;
+      delete buffer_allocator_;
       buffer_allocator_ = NULL;
       return -ENOMEM;
     } else {
@@ -382,7 +380,7 @@
         DLOGE("mmap failed. err = %d", errno);
         frame_capture_data->buffer = NULL;
         ret = buffer_allocator_->FreeBuffer(&buffer_info);
-        delete[] buffer_allocator_;
+        delete buffer_allocator_;
         buffer_allocator_ = NULL;
         return -EFAULT;
       } else {
@@ -390,27 +388,105 @@
         frame_capture_data->buffer_stride = buffer_info.alloc_buffer_info.stride;
         frame_capture_data->buffer_size = buffer_info.alloc_buffer_info.size;
       }
-      // TODO(user): Call HWC interface to provide the buffer and rectangle information
+      ret = hwc_display->FrameCaptureAsync(buffer_info, 1);
+      if (ret < 0) {
+        DLOGE("FrameCaptureAsync failed. ret = %d", ret);
+      }
     }
   } else {
-    if (frame_capture_data->buffer != NULL) {
-      if (munmap(frame_capture_data->buffer, buffer_info.alloc_buffer_info.size) != 0) {
-        DLOGE("munmap failed. err = %d", errno);
+    ret = hwc_display->GetFrameCaptureStatus();
+    if (!ret) {
+      if (frame_capture_data->buffer != NULL) {
+        if (munmap(frame_capture_data->buffer, buffer_info.alloc_buffer_info.size) != 0) {
+          DLOGE("munmap failed. err = %d", errno);
+        }
       }
-    }
-    if (buffer_allocator_ != NULL) {
-      std::memset(frame_capture_data, 0x00, sizeof(PPFrameCaptureData));
-      ret = buffer_allocator_->FreeBuffer(&buffer_info);
-      if (ret != 0) {
-        DLOGE("FreeBuffer failed. ret = %d", ret);
+      if (buffer_allocator_ != NULL) {
+        std::memset(frame_capture_data, 0x00, sizeof(PPFrameCaptureData));
+        ret = buffer_allocator_->FreeBuffer(&buffer_info);
+        if (ret != 0) {
+          DLOGE("FreeBuffer failed. ret = %d", ret);
+        }
+        delete buffer_allocator_;
+        buffer_allocator_ = NULL;
       }
-      delete[] buffer_allocator_;
-      buffer_allocator_ = NULL;
+    } else {
+      DLOGE("GetFrameCaptureStatus failed. ret = %d", ret);
     }
   }
   return ret;
 }
 
+int HWCColorManager::SetDetailedEnhancer(void *params, HWCDisplay *hwc_display) {
+  SCOPE_LOCK(locker_);
+  DisplayError err = kErrorNone;
+  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->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 & kDeTuningFlagClip) {
+      de_data.override_flags |= kOverrideDEEnable;
+      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 & kDeTuningFlagThrDieout) {
+      de_data.override_flags |= kOverrideDEEnable;
+      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 & kDeTuningFlagThrHigh) {
+      de_data.override_flags |= kOverrideDEEnable;
+      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;
+      }
+    }
+  }
+  err = hwc_display->SetDetailEnhancerConfig(de_data);
+  if (err) {
+    DLOGW("SetDetailEnhancerConfig failed. err = %d", err);
+  }
+
+  return err;
+}
+
 const HWCQDCMModeManager::ActiveFeatureCMD HWCQDCMModeManager::kActiveFeatureCMD[] = {
     HWCQDCMModeManager::ActiveFeatureCMD("cabl:on", "cabl:off", "cabl:status", "running"),
     HWCQDCMModeManager::ActiveFeatureCMD("ad:on", "ad:off", "ad:query:status", "running"),
diff --git a/sdm/libs/hwc/hwc_color_manager.h b/sdm/libs/hwc/hwc_color_manager.h
index 981b14a..792d5ca 100644
--- a/sdm/libs/hwc/hwc_color_manager.h
+++ b/sdm/libs/hwc/hwc_color_manager.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015, The Linux Foundataion. All rights reserved.
+/* Copyright (c) 2015-2016, The Linux Foundataion. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
@@ -119,6 +119,7 @@
   bool SolidFillLayersPrepare(hwc_display_contents_1_t **displays, HWCDisplay *hwc_display);
   bool SolidFillLayersSet(hwc_display_contents_1_t **displays, HWCDisplay *hwc_display);
   int SetFrameCapture(void *params, bool enable, HWCDisplay *hwc_display);
+  int SetDetailedEnhancer(void *params, HWCDisplay *hwc_display);
 
  protected:
   int CreateSolidFillLayers(HWCDisplay *hwc_display);
diff --git a/sdm/libs/hwc/hwc_display.cpp b/sdm/libs/hwc/hwc_display.cpp
index dd6f83a..b40884e 100644
--- a/sdm/libs/hwc/hwc_display.cpp
+++ b/sdm/libs/hwc/hwc_display.cpp
@@ -109,6 +109,8 @@
   s3d_format_hwc_to_sdm_.insert(std::pair<int, LayerBufferS3DFormat>(HAL_3D_TOP_BOTTOM,
                                 kS3dFormatTopBottom));
 
+  disable_animation_ = Debug::IsExtAnimDisabled();
+
   return 0;
 }
 
@@ -486,16 +488,24 @@
 
     // For dim layers, SurfaceFlinger
     //    - converts planeAlpha to per pixel alpha,
-    //    - sets RGB color to 000,
+    //    - sets appropriate RGB color,
     //    - sets planeAlpha to 0xff,
     //    - blending to Premultiplied.
     // This can be achieved at hardware by
-    //    - solid fill ARGB to 0xff000000,
+    //    - solid fill ARGB to appropriate value,
     //    - incoming planeAlpha,
     //    - blending to Coverage.
     if (hwc_layer.flags & kDimLayer) {
       layer->input_buffer->format = kFormatARGB8888;
       layer->solid_fill_color = 0xff000000;
+#ifdef QTI_BSP
+      // Get ARGB color from HWC Dim Layer color
+      uint32_t a = UINT32(hwc_layer.color.a) << 24;
+      uint32_t r = UINT32(hwc_layer.color.r) << 16;
+      uint32_t g = UINT32(hwc_layer.color.g) << 8;
+      uint32_t b = UINT32(hwc_layer.color.b);
+      layer->solid_fill_color = a | r | g | b;
+#endif
       SetBlending(HWC_BLENDING_COVERAGE, &layer->blending);
     } else {
       SetBlending(hwc_layer.blending, &layer->blending);
@@ -564,6 +574,19 @@
   return 0;
 }
 
+void HWCDisplay::SetLayerS3DMode(const LayerBufferS3DFormat &source, uint32_t *target) {
+#ifdef QTI_BSP
+    switch (source) {
+    case kS3dFormatNone: *target = HWC_S3DMODE_NONE; break;
+    case kS3dFormatLeftRight: *target = HWC_S3DMODE_LR; break;
+    case kS3dFormatRightLeft: *target = HWC_S3DMODE_RL; break;
+    case kS3dFormatTopBottom: *target = HWC_S3DMODE_TB; break;
+    case kS3dFormatFramePacking: *target = HWC_S3DMODE_FP; break;
+    default: *target = HWC_S3DMODE_MAX; break;
+    }
+#endif
+}
+
 int HWCDisplay::PrepareLayerStack(hwc_display_contents_1_t *content_list) {
   if (shutdown_pending_) {
     return 0;
@@ -581,8 +604,9 @@
         // To prevent surfaceflinger infinite wait, flush the previous frame during Commit()
         // so that previous buffer and fences are released, and override the error.
         flush_ = true;
+      } else {
+        DLOGI("Prepare failed for Display = %d Error = %d", type_, error);
       }
-
       return 0;
     }
   } else {
@@ -598,12 +622,26 @@
     hwc_layer_1_t &hwc_layer = content_list->hwLayers[i];
     Layer *layer = layer_stack_.layers.at(i);
     LayerComposition composition = layer->composition;
+    private_handle_t* pvt_handle  = static_cast<private_handle_t*>
+      (const_cast<native_handle_t*>(hwc_layer.handle));
+    MetaData_t *meta_data = pvt_handle ?
+      reinterpret_cast<MetaData_t *>(pvt_handle->base_metadata) : NULL;
 
     if ((composition == kCompositionSDE) || (composition == kCompositionHybrid) ||
         (composition == kCompositionBlit)) {
       hwc_layer.hints |= HWC_HINT_CLEAR_FB;
     }
     SetComposition(composition, &hwc_layer.compositionType);
+
+    if (meta_data != NULL) {
+      if (composition == kCompositionGPUS3D) {
+        // Align HWC and client's dispaly ID in case of HDMI as primary
+        meta_data->s3dComp.displayId =
+          display_intf_->IsPrimaryDisplay() ? HWC_DISPLAY_PRIMARY: id_;
+        SetLayerS3DMode(layer->input_buffer->s3d_format,
+            &meta_data->s3dComp.s3dMode);
+      }
+    }
   }
 
   return 0;
@@ -658,6 +696,8 @@
         // To prevent surfaceflinger infinite wait, flush the previous frame during Commit()
         // so that previous buffer and fences are released, and override the error.
         flush_ = true;
+      } else {
+        DLOGI("Commit failed for Display = %d Error = %d", type_, error);
       }
     }
   }
@@ -699,9 +739,11 @@
       // framebuffer layer throughout animation and do not allow framework to do eglswapbuffer on
       // framebuffer target. So graphics doesn't close the release fence fd of framebuffer target,
       // Hence close the release fencefd of framebuffer target here.
-      if (layer->composition == kCompositionGPUTarget && animating_) {
-        close(hwc_layer.releaseFenceFd);
-        hwc_layer.releaseFenceFd = -1;
+      if (disable_animation_) {
+        if (layer->composition == kCompositionGPUTarget && animating_) {
+          close(hwc_layer.releaseFenceFd);
+          hwc_layer.releaseFenceFd = -1;
+        }
       }
     }
 
@@ -765,6 +807,7 @@
   switch (source) {
   case kCompositionGPUTarget:   *target = HWC_FRAMEBUFFER_TARGET; break;
   case kCompositionGPU:         *target = HWC_FRAMEBUFFER;        break;
+  case kCompositionGPUS3D:      *target = HWC_FRAMEBUFFER;        break;
   case kCompositionHWCursor:    *target = HWC_CURSOR_OVERLAY;     break;
   default:                      *target = HWC_OVERLAY;            break;
   }
@@ -1303,7 +1346,7 @@
 
 // TODO(user): HWC needs to know updating for dyn_fps, cpu hint features,
 // once the features are moved to SDM, the two functions below can be removed.
-bool HWCDisplay::SingleLayerUpdating(uint32_t app_layer_count) {
+uint32_t HWCDisplay::GetUpdatingLayersCount(uint32_t app_layer_count) {
   uint32_t updating_count = 0;
 
   for (uint i = 0; i < app_layer_count; i++) {
@@ -1313,7 +1356,7 @@
     }
   }
 
-  return (updating_count == 1);
+  return updating_count;
 }
 
 bool HWCDisplay::SingleVideoLayerUpdating(uint32_t app_layer_count) {
@@ -1321,7 +1364,12 @@
 
   for (uint i = 0; i < app_layer_count; i++) {
     Layer *layer = layer_stack_.layers[i];
-    if (layer->flags.updating && (layer->input_buffer->flags.video == true)) {
+    // TODO(user): disable DRC feature in S3D playbacl case.S3D video
+    // need play in dedicate resolution and fps, if DRC switch the
+    // mode to an non S3D supported mode, it would break S3D playback.
+    // Need figure out a way to make S3D and DRC co-exist.
+    if (layer->flags.updating && (layer->input_buffer->flags.video == true) &&
+       (layer->input_buffer->s3d_format == kS3dFormatNone)) {
       updating_count++;
     }
   }
@@ -1381,4 +1429,9 @@
   return (dirty_regions.empty() || IsValid(dirty_regions.at(0)));
 }
 
+int HWCDisplay::GetDisplayPort(DisplayPort *port) {
+  return display_intf_->GetDisplayPort(port) == kErrorNone ? 0 : -1;
+}
+
+
 }  // namespace sdm
diff --git a/sdm/libs/hwc/hwc_display.h b/sdm/libs/hwc/hwc_display.h
index 1dfface..5b59fb8 100644
--- a/sdm/libs/hwc/hwc_display.h
+++ b/sdm/libs/hwc/hwc_display.h
@@ -49,6 +49,14 @@
 
 class HWCDisplay : public DisplayEventHandler {
  public:
+  enum {
+    SET_METADATA_DYN_REFRESH_RATE,
+    SET_BINDER_DYN_REFRESH_RATE,
+    SET_DISPLAY_MODE,
+    SET_QDCM_SOLID_FILL_INFO,
+    UNSET_QDCM_SOLID_FILL_INFO,
+  };
+
   virtual ~HWCDisplay() { }
   virtual int Init();
   virtual int Deinit();
@@ -94,6 +102,10 @@
   // 0 : Success.
   virtual int GetFrameCaptureStatus() { return -EAGAIN; }
 
+  virtual DisplayError SetDetailEnhancerConfig(const DisplayDetailEnhancerData &de_data) {
+    return kErrorNotSupported;
+  }
+
   // Display Configurations
   virtual int SetActiveDisplayConfig(int config);
   virtual int GetActiveDisplayConfig(uint32_t *config);
@@ -109,6 +121,7 @@
                            PPPendingParams *pending_action);
   int GetVisibleDisplayRect(hwc_rect_t* rect);
   DisplayClass GetDisplayClass();
+  int GetDisplayPort(DisplayPort *port);
 
  protected:
   enum DisplayStatus {
@@ -151,6 +164,7 @@
   inline void SetComposition(const LayerComposition &source, int32_t *target);
   inline void SetBlending(const int32_t &source, LayerBlending *target);
   int SetFormat(const int32_t &source, const int flags, LayerBufferFormat *target);
+  void SetLayerS3DMode(const LayerBufferS3DFormat &source, uint32_t *target);
   LayerBufferFormat GetSDMFormat(const int32_t &source, const int flags);
   const char *GetHALPixelFormatString(int format);
   const char *GetDisplayString();
@@ -161,7 +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 SingleLayerUpdating(uint32_t app_layer_count);
+  uint32_t GetUpdatingLayersCount(uint32_t app_layer_count);
   bool SingleVideoLayerUpdating(uint32_t app_layer_count);
   bool IsSurfaceUpdated(const std::vector<LayerRect> &dirty_regions);
 
@@ -197,6 +211,7 @@
   bool secure_display_active_ = false;
   bool skip_prepare_ = false;
   bool solid_fill_enable_ = false;
+  bool disable_animation_ = false;
   uint32_t solid_fill_color_ = 0;
   LayerRect display_rect_;
   std::map<int, LayerBufferS3DFormat> s3d_format_hwc_to_sdm_;
diff --git a/sdm/libs/hwc/hwc_display_external.cpp b/sdm/libs/hwc/hwc_display_external.cpp
index a1ad661..ed916d4 100644
--- a/sdm/libs/hwc/hwc_display_external.cpp
+++ b/sdm/libs/hwc/hwc_display_external.cpp
@@ -51,6 +51,7 @@
   uint32_t external_width = 0;
   uint32_t external_height = 0;
   int drc_enabled = 0;
+  int drc_reset_fps_enabled = 0;
   DisplayError error = kErrorNone;
 
   HWCDisplay *hwc_display_external = new HWCDisplayExternal(core_intf, hwc_procs, qservice);
@@ -89,6 +90,10 @@
   HWCDebugHandler::Get()->GetProperty("sdm.hdmi.drc_enabled", &(drc_enabled));
   reinterpret_cast<HWCDisplayExternal *>(hwc_display_external)->drc_enabled_ = drc_enabled;
 
+  HWCDebugHandler::Get()->GetProperty("sdm.hdmi.drc_reset_fps", &(drc_reset_fps_enabled));
+  reinterpret_cast<HWCDisplayExternal *>(hwc_display_external)->drc_reset_fps_enabled_ =
+                                                                drc_reset_fps_enabled;
+
   *hwc_display = hwc_display_external;
 
   return status;
@@ -131,16 +136,15 @@
 
   bool one_video_updating_layer = SingleVideoLayerUpdating(UINT32(content_list->numHwLayers - 1));
 
-  if (current_refresh_rate_ != metadata_refresh_rate_ && one_video_updating_layer && drc_enabled_) {
-    error = display_intf_->SetRefreshRate(metadata_refresh_rate_);
+  uint32_t refresh_rate = GetOptimalRefreshRate(one_video_updating_layer);
+  if (current_refresh_rate_ != refresh_rate) {
+    error = display_intf_->SetRefreshRate(refresh_rate);
+    if (error == kErrorNone) {
+      // On success, set current refresh rate to new refresh rate
+      current_refresh_rate_ = refresh_rate;
+    }
   }
 
-  if (error == kErrorNone) {
-    // On success, set current refresh rate to new refresh rate
-    current_refresh_rate_ = metadata_refresh_rate_;
-  }
-
-
   status = PrepareLayerStack(content_list);
   if (status) {
     return status;
@@ -248,6 +252,11 @@
   static const uint32_t mapping_fps[] = {59940, 60000, 60000, 59940, 60000, 50000, 59940, 60000};
   uint32_t frame_rate = (uint32_t)(fps * 1000);
 
+  // process non valid
+  if (frame_rate == 0) {
+    return current_refresh_rate_;
+  }
+
   int count = INT(sizeof(standard_fps) / sizeof(standard_fps[0]));
   for (int i = 0; i < count; i++) {
     // Most likely used for video, the fps for frames should be stable from video side.
@@ -269,10 +278,57 @@
 
 void HWCDisplayExternal::PrepareDynamicRefreshRate(Layer *layer) {
   if (layer->input_buffer->flags.video) {
-    metadata_refresh_rate_ = SanitizeRefreshRate(layer->frame_rate);
+    if (layer->frame_rate != 0) {
+      metadata_refresh_rate_ = SanitizeRefreshRate(layer->frame_rate);
+    } else {
+      metadata_refresh_rate_ = current_refresh_rate_;
+    }
     layer->frame_rate = current_refresh_rate_;
   }
 }
 
+void HWCDisplayExternal::ForceRefreshRate(uint32_t refresh_rate) {
+  if ((refresh_rate && (refresh_rate < min_refresh_rate_ || refresh_rate > max_refresh_rate_)) ||
+       force_refresh_rate_ == refresh_rate) {
+    // Cannot honor force refresh rate, as its beyond the range or new request is same
+    return;
+  }
+
+  force_refresh_rate_ = refresh_rate;
+}
+
+uint32_t HWCDisplayExternal::GetOptimalRefreshRate(bool one_updating_layer) {
+  if (force_refresh_rate_) {
+    return force_refresh_rate_;
+  } else if (one_updating_layer && drc_enabled_) {
+    return metadata_refresh_rate_;
+  }
+
+  if (drc_reset_fps_enabled_) {
+    DisplayConfigVariableInfo fb_config;
+    display_intf_->GetFrameBufferConfig(&fb_config);
+    return (fb_config.fps * 1000);
+  }
+
+  return current_refresh_rate_;
+}
+
+int HWCDisplayExternal::Perform(uint32_t operation, ...) {
+  va_list args;
+  va_start(args, operation);
+  int val = va_arg(args, int32_t);
+  va_end(args);
+  switch (operation) {
+    case SET_BINDER_DYN_REFRESH_RATE:
+      ForceRefreshRate(UINT32(val));
+      break;
+    default:
+      DLOGW("Invalid operation %d", operation);
+      return -EINVAL;
+  }
+
+  return 0;
+}
+
 }  // namespace sdm
 
diff --git a/sdm/libs/hwc/hwc_display_external.h b/sdm/libs/hwc/hwc_display_external.h
index c54f738..ac70489 100644
--- a/sdm/libs/hwc/hwc_display_external.h
+++ b/sdm/libs/hwc/hwc_display_external.h
@@ -40,11 +40,13 @@
   virtual int Prepare(hwc_display_contents_1_t *content_list);
   virtual int Commit(hwc_display_contents_1_t *content_list);
   virtual void SetSecureDisplay(bool secure_display_active);
+  virtual int Perform(uint32_t operation, ...);
 
  protected:
   virtual uint32_t RoundToStandardFPS(float fps);
   virtual void PrepareDynamicRefreshRate(Layer *layer);
   int drc_enabled_ = 0;
+  int drc_reset_fps_enabled_ = 0;
 
  private:
   HWCDisplayExternal(CoreInterface *core_intf, hwc_procs_t const **hwc_procs,
@@ -52,6 +54,8 @@
   void ApplyScanAdjustment(hwc_rect_t *display_frame);
   static void GetDownscaleResolution(uint32_t primary_width, uint32_t primary_height,
                                      uint32_t *virtual_width, uint32_t *virtual_height);
+  void ForceRefreshRate(uint32_t refresh_rate);
+  uint32_t GetOptimalRefreshRate(bool one_updating_layer);
 };
 
 }  // namespace sdm
diff --git a/sdm/libs/hwc/hwc_display_primary.cpp b/sdm/libs/hwc/hwc_display_primary.cpp
index f4775b1..50805d4 100644
--- a/sdm/libs/hwc/hwc_display_primary.cpp
+++ b/sdm/libs/hwc/hwc_display_primary.cpp
@@ -167,8 +167,12 @@
     layer_stack_.flags.post_processed_output = post_processed_output_;
   }
 
-  bool one_updating_layer = SingleLayerUpdating(UINT32(content_list->numHwLayers - 1));
-  ToggleCPUHint(one_updating_layer);
+  uint32_t num_updating_layers = GetUpdatingLayersCount(UINT32(content_list->numHwLayers - 1));
+  bool one_updating_layer = (num_updating_layers == 1);
+
+  if (num_updating_layers != 0) {
+    ToggleCPUHint(one_updating_layer);
+  }
 
   uint32_t refresh_rate = GetOptimalRefreshRate(one_updating_layer);
   if (current_refresh_rate_ != refresh_rate) {
@@ -459,12 +463,12 @@
   GetPanelResolution(&panel_width, &panel_height);
   GetFrameBufferResolution(&fb_width, &fb_height);
 
-  if (post_processed_output && (output_buffer_info_.buffer_config.width < panel_width ||
-                                output_buffer_info_.buffer_config.height < panel_height)) {
+  if (post_processed_output && (output_buffer_info.buffer_config.width < panel_width ||
+                                output_buffer_info.buffer_config.height < panel_height)) {
     DLOGE("Buffer dimensions should not be less than panel resolution");
     return -1;
-  } else if (!post_processed_output && (output_buffer_info_.buffer_config.width < fb_width ||
-                                        output_buffer_info_.buffer_config.height < fb_height)) {
+  } else if (!post_processed_output && (output_buffer_info.buffer_config.width < fb_width ||
+                                        output_buffer_info.buffer_config.height < fb_height)) {
     DLOGE("Buffer dimensions should not be less than FB resolution");
     return -1;
   }
@@ -479,6 +483,15 @@
   return 0;
 }
 
+DisplayError HWCDisplayPrimary::SetDetailEnhancerConfig(
+                                    const DisplayDetailEnhancerData &de_data) {
+  DisplayError error = kErrorNotSupported;
+  if (display_intf_) {
+    error = display_intf_->SetDetailEnhancerData(de_data);
+  }
+  return error;
+}
+
 DisplayError HWCDisplayPrimary::ControlPartialUpdate(bool enable, uint32_t *pending) {
   DisplayError error = kErrorNone;
 
diff --git a/sdm/libs/hwc/hwc_display_primary.h b/sdm/libs/hwc/hwc_display_primary.h
index f25a877..901d856 100644
--- a/sdm/libs/hwc/hwc_display_primary.h
+++ b/sdm/libs/hwc/hwc_display_primary.h
@@ -32,14 +32,6 @@
 
 class HWCDisplayPrimary : public HWCDisplay {
  public:
-  enum {
-    SET_METADATA_DYN_REFRESH_RATE,
-    SET_BINDER_DYN_REFRESH_RATE,
-    SET_DISPLAY_MODE,
-    SET_QDCM_SOLID_FILL_INFO,
-    UNSET_QDCM_SOLID_FILL_INFO,
-  };
-
   static int Create(CoreInterface *core_intf, BufferAllocator *buffer_allocator,
                     hwc_procs_t const **hwc_procs, qService::QService *qservice,
                     HWCDisplay **hwc_display);
@@ -54,6 +46,7 @@
   virtual void SetFrameDumpConfig(uint32_t count, uint32_t bit_mask_layer_type);
   virtual int FrameCaptureAsync(const BufferInfo& output_buffer_info, bool post_processed);
   virtual int GetFrameCaptureStatus() { return frame_capture_status_; }
+  virtual DisplayError SetDetailEnhancerConfig(const DisplayDetailEnhancerData &de_data);
   virtual DisplayError ControlPartialUpdate(bool enable, uint32_t *pending);
 
  private:
diff --git a/sdm/libs/hwc/hwc_session.cpp b/sdm/libs/hwc/hwc_session.cpp
index 95da143..0f36c7e 100644
--- a/sdm/libs/hwc/hwc_session.cpp
+++ b/sdm/libs/hwc/hwc_session.cpp
@@ -278,7 +278,7 @@
 
     if (hwc_session->color_mgr_) {
       HWCDisplay *primary_display = hwc_session->hwc_display_[HWC_DISPLAY_PRIMARY];
-      if (primary_display) {
+      if (primary_display && !hwc_session->is_hdmi_primary_) {
         int ret = hwc_session->color_mgr_->SolidFillLayersPrepare(displays, primary_display);
         if (ret)
           return 0;
@@ -476,11 +476,6 @@
   if (hwc_session->hwc_display_[disp]) {
     status = hwc_session->hwc_display_[disp]->SetPowerMode(mode);
   }
-  if (disp == HWC_DISPLAY_PRIMARY && hwc_session->hwc_display_[HWC_DISPLAY_VIRTUAL]) {
-    // Set the power mode for virtual display while setting power mode for primary, as SF
-    // does not invoke SetPowerMode() for virtual display.
-    status = hwc_session->hwc_display_[HWC_DISPLAY_VIRTUAL]->SetPowerMode(mode);
-  }
 
   return status;
 }
@@ -940,6 +935,41 @@
   return error;
 }
 
+android::status_t HWCSession::SetDisplayPort(DisplayPort sdm_disp_port, int *hwc_disp_port) {
+  if (!hwc_disp_port) {
+    return -EINVAL;
+  }
+
+  switch (sdm_disp_port) {
+    case kPortDSI:
+      *hwc_disp_port = qdutils::DISPLAY_PORT_DSI;
+      break;
+    case kPortDTV:
+      *hwc_disp_port = qdutils::DISPLAY_PORT_DTV;
+      break;
+    case kPortLVDS:
+      *hwc_disp_port = qdutils::DISPLAY_PORT_LVDS;
+      break;
+    case kPortEDP:
+      *hwc_disp_port = qdutils::DISPLAY_PORT_EDP;
+      break;
+    case kPortWriteBack:
+      *hwc_disp_port = qdutils::DISPLAY_PORT_WRITEBACK;
+      break;
+    case kPortDP:
+      *hwc_disp_port = qdutils::DISPLAY_PORT_DP;
+      break;
+    case kPortDefault:
+      *hwc_disp_port = qdutils::DISPLAY_PORT_DEFAULT;
+      break;
+    default:
+      DLOGE("Invalid sdm display port %d", sdm_disp_port);
+      return -EINVAL;
+  }
+
+  return 0;
+}
+
 android::status_t HWCSession::HandleGetDisplayAttributesForConfig(const android::Parcel
                                                                   *input_parcel,
                                                                   android::Parcel *output_parcel) {
@@ -947,6 +977,8 @@
   int dpy = input_parcel->readInt32();
   int error = android::BAD_VALUE;
   DisplayConfigVariableInfo display_attributes;
+  DisplayPort sdm_disp_port = kPortDefault;
+  int hwc_disp_port = qdutils::DISPLAY_PORT_DEFAULT;
 
   if (dpy > HWC_DISPLAY_VIRTUAL) {
     return android::BAD_VALUE;
@@ -955,12 +987,16 @@
   if (hwc_display_[dpy]) {
     error = hwc_display_[dpy]->GetDisplayAttributesForConfig(config, &display_attributes);
     if (error == 0) {
+      hwc_display_[dpy]->GetDisplayPort(&sdm_disp_port);
+
+      SetDisplayPort(sdm_disp_port, &hwc_disp_port);
+
       output_parcel->writeInt32(INT(display_attributes.vsync_period_ns));
       output_parcel->writeInt32(INT(display_attributes.x_pixels));
       output_parcel->writeInt32(INT(display_attributes.y_pixels));
       output_parcel->writeFloat(display_attributes.x_dpi);
       output_parcel->writeFloat(display_attributes.y_dpi);
-      output_parcel->writeInt32(0);  // Panel type, unsupported.
+      output_parcel->writeInt32(hwc_disp_port);
       output_parcel->writeInt32(display_attributes.is_yuv);
     }
   }
@@ -1251,6 +1287,11 @@
       ret = color_mgr_->SetFrameCapture(pending_action.params,
                                         false, hwc_display_[HWC_DISPLAY_PRIMARY]);
       break;
+    case kConfigureDetailedEnhancer:
+      ret = color_mgr_->SetDetailedEnhancer(pending_action.params,
+                                            hwc_display_[HWC_DISPLAY_PRIMARY]);
+      hwc_procs_->invalidate(hwc_procs_);
+      break;
     case kNoAction:
       break;
     default:
@@ -1380,6 +1421,7 @@
 int HWCSession::HotPlugHandler(bool connected) {
   int status = 0;
   bool notify_hotplug = false;
+  bool refresh_screen = false;
 
   // To prevent sending events to client while a lock is held, acquire scope locks only within
   // below scope so that those get automatically unlocked after the scope ends.
@@ -1423,6 +1465,11 @@
           return -1;
         }
 
+        status = hwc_display_[HWC_DISPLAY_PRIMARY]->SetPowerMode(HWC_POWER_MODE_NORMAL);
+        if (status) {
+          DLOGE("power-on on primary failed with error = %d", status);
+        }
+
         is_hdmi_yuv_ = IsDisplayYUV(HWC_DISPLAY_PRIMARY);
 
         // Next, go ahead and enable vsync on external display. This is expliclity required
@@ -1435,6 +1482,7 @@
         }
         // Don't do hotplug notification for HDMI as primary case for now
         notify_hotplug = false;
+        refresh_screen = true;
       } else {
         if (hwc_display_[HWC_DISPLAY_EXTERNAL]) {
           DLOGE("HDMI is already connected");
@@ -1493,7 +1541,7 @@
     }
   }
 
-  if (connected && notify_hotplug) {
+  if (connected && (notify_hotplug || refresh_screen)) {
     // trigger screen refresh to ensure sufficient resources are available to process new
     // new display connection.
     hwc_procs_->invalidate(hwc_procs_);
diff --git a/sdm/libs/hwc/hwc_session.h b/sdm/libs/hwc/hwc_session.h
index 2a732b2..54b7260 100644
--- a/sdm/libs/hwc/hwc_session.h
+++ b/sdm/libs/hwc/hwc_session.h
@@ -124,6 +124,7 @@
   android::status_t GetBWTransactionStatus(const android::Parcel *input_parcel,
                                           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);
 
   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 9ab4952..a5cb821 100644
--- a/sdm/libs/hwc2/hwc_color_manager.cpp
+++ b/sdm/libs/hwc2/hwc_color_manager.cpp
@@ -200,14 +200,12 @@
 
   if (enable) {
     std::memset(&buffer_info, 0x00, sizeof(buffer_info));
-    hwc_display->GetFrameBufferResolution(&buffer_info.buffer_config.width,
-                                          &buffer_info.buffer_config.height);
+    hwc_display->GetPanelResolution(&buffer_info.buffer_config.width,
+                                    &buffer_info.buffer_config.height);
     if (frame_capture_data->input_params.out_pix_format == PP_PIXEL_FORMAT_RGB_888) {
       buffer_info.buffer_config.format = kFormatRGB888;
     } else if (frame_capture_data->input_params.out_pix_format == PP_PIXEL_FORMAT_RGB_2101010) {
-      // TODO(user): Complete the implementation
-      DLOGE("RGB 10-bit format NOT supported");
-      return -EFAULT;
+      buffer_info.buffer_config.format = kFormatRGBA1010102;
     } else {
       DLOGE("Pixel-format: %d NOT support.", frame_capture_data->input_params.out_pix_format);
       return -EFAULT;
@@ -227,7 +225,7 @@
     ret = buffer_allocator_->AllocateBuffer(&buffer_info);
     if (ret != 0) {
       DLOGE("Buffer allocation failed. ret: %d", ret);
-      delete[] buffer_allocator_;
+      delete buffer_allocator_;
       buffer_allocator_ = NULL;
       return -ENOMEM;
     } else {
@@ -238,7 +236,7 @@
         DLOGE("mmap failed. err = %d", errno);
         frame_capture_data->buffer = NULL;
         ret = buffer_allocator_->FreeBuffer(&buffer_info);
-        delete[] buffer_allocator_;
+        delete buffer_allocator_;
         buffer_allocator_ = NULL;
         return -EFAULT;
       } else {
@@ -246,27 +244,105 @@
         frame_capture_data->buffer_stride = buffer_info.alloc_buffer_info.stride;
         frame_capture_data->buffer_size = buffer_info.alloc_buffer_info.size;
       }
-      // TODO(user): Call HWC interface to provide the buffer and rectangle information
+      ret = hwc_display->FrameCaptureAsync(buffer_info, 1);
+      if (ret < 0) {
+        DLOGE("FrameCaptureAsync failed. ret = %d", ret);
+      }
     }
   } else {
-    if (frame_capture_data->buffer != NULL) {
-      if (munmap(frame_capture_data->buffer, buffer_info.alloc_buffer_info.size) != 0) {
-        DLOGE("munmap failed. err = %d", errno);
+    ret = hwc_display->GetFrameCaptureStatus();
+    if (!ret) {
+      if (frame_capture_data->buffer != NULL) {
+        if (munmap(frame_capture_data->buffer, buffer_info.alloc_buffer_info.size) != 0) {
+          DLOGE("munmap failed. err = %d", errno);
+        }
       }
-    }
-    if (buffer_allocator_ != NULL) {
-      std::memset(frame_capture_data, 0x00, sizeof(PPFrameCaptureData));
-      ret = buffer_allocator_->FreeBuffer(&buffer_info);
-      if (ret != 0) {
-        DLOGE("FreeBuffer failed. ret = %d", ret);
+      if (buffer_allocator_ != NULL) {
+        std::memset(frame_capture_data, 0x00, sizeof(PPFrameCaptureData));
+        ret = buffer_allocator_->FreeBuffer(&buffer_info);
+        if (ret != 0) {
+          DLOGE("FreeBuffer failed. ret = %d", ret);
+        }
+        delete buffer_allocator_;
+        buffer_allocator_ = NULL;
       }
-      delete[] buffer_allocator_;
-      buffer_allocator_ = NULL;
+    } else {
+      DLOGE("GetFrameCaptureStatus failed. ret = %d", ret);
     }
   }
   return ret;
 }
 
+int HWCColorManager::SetDetailedEnhancer(void *params, HWCDisplay *hwc_display) {
+  SCOPE_LOCK(locker_);
+  DisplayError err = kErrorNone;
+  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->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 & kDeTuningFlagClip) {
+      de_data.override_flags |= kOverrideDEEnable;
+      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 & kDeTuningFlagThrDieout) {
+      de_data.override_flags |= kOverrideDEEnable;
+      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 & kDeTuningFlagThrHigh) {
+      de_data.override_flags |= kOverrideDEEnable;
+      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;
+      }
+    }
+  }
+  err = hwc_display->SetDetailEnhancerConfig(de_data);
+  if (err) {
+    DLOGW("SetDetailEnhancerConfig failed. err = %d", err);
+  }
+
+  return err;
+}
+
 const HWCQDCMModeManager::ActiveFeatureCMD HWCQDCMModeManager::kActiveFeatureCMD[] = {
     HWCQDCMModeManager::ActiveFeatureCMD("cabl:on", "cabl:off", "cabl:status", "running"),
     HWCQDCMModeManager::ActiveFeatureCMD("ad:on", "ad:off", "ad:query:status", "running"),
diff --git a/sdm/libs/hwc2/hwc_color_manager.h b/sdm/libs/hwc2/hwc_color_manager.h
index 130dca9..62b6bce 100644
--- a/sdm/libs/hwc2/hwc_color_manager.h
+++ b/sdm/libs/hwc2/hwc_color_manager.h
@@ -116,6 +116,7 @@
   int EnableQDCMMode(bool enable, HWCDisplay *hwc_display);
   int SetSolidFill(const void *params, bool enable, HWCDisplay *hwc_display);
   int SetFrameCapture(void *params, bool enable, HWCDisplay *hwc_display);
+  int SetDetailedEnhancer(void *params, HWCDisplay *hwc_display);
 
  protected:
   int CreateSolidFillLayers(HWCDisplay *hwc_display);
diff --git a/sdm/libs/hwc2/hwc_display.cpp b/sdm/libs/hwc2/hwc_display.cpp
index b587050..9a8de43 100644
--- a/sdm/libs/hwc2/hwc_display.cpp
+++ b/sdm/libs/hwc2/hwc_display.cpp
@@ -367,7 +367,6 @@
       layer_stack_.flags.skip_present = true;
     }
 
-
     if (hwc_layer->GetClientRequestedCompositionType() == HWC2::Composition::Cursor) {
       // Currently we support only one HWCursor & only at top most z-order
       if ((*layer_set_.rbegin())->GetId() == hwc_layer->GetId()) {
diff --git a/sdm/libs/hwc2/hwc_display.h b/sdm/libs/hwc2/hwc_display.h
index cc90694..2221027 100644
--- a/sdm/libs/hwc2/hwc_display.h
+++ b/sdm/libs/hwc2/hwc_display.h
@@ -118,6 +118,10 @@
   // 0 : Success.
   virtual int GetFrameCaptureStatus() { return -EAGAIN; }
 
+  virtual DisplayError SetDetailEnhancerConfig(const DisplayDetailEnhancerData &de_data) {
+    return kErrorNotSupported;
+  }
+
   // Display Configurations
   virtual int SetActiveDisplayConfig(int config);
   virtual int GetActiveDisplayConfig(uint32_t *config);
diff --git a/sdm/libs/hwc2/hwc_display_primary.cpp b/sdm/libs/hwc2/hwc_display_primary.cpp
index 8b5e245..198eddb 100644
--- a/sdm/libs/hwc2/hwc_display_primary.cpp
+++ b/sdm/libs/hwc2/hwc_display_primary.cpp
@@ -532,6 +532,16 @@
   return 0;
 }
 
+DisplayError HWCDisplayPrimary::SetDetailEnhancerConfig
+                                   (const DisplayDetailEnhancerData &de_data) {
+  DisplayError error = kErrorNotSupported;
+
+  if (display_intf_) {
+    error = display_intf_->SetDetailEnhancerData(de_data);
+  }
+  return error;
+}
+
 DisplayError HWCDisplayPrimary::ControlPartialUpdate(bool enable, uint32_t *pending) {
   DisplayError error = kErrorNone;
 
diff --git a/sdm/libs/hwc2/hwc_display_primary.h b/sdm/libs/hwc2/hwc_display_primary.h
index ab46cde..43673ed 100644
--- a/sdm/libs/hwc2/hwc_display_primary.h
+++ b/sdm/libs/hwc2/hwc_display_primary.h
@@ -65,6 +65,7 @@
   virtual void SetFrameDumpConfig(uint32_t count, uint32_t bit_mask_layer_type);
   virtual int FrameCaptureAsync(const BufferInfo &output_buffer_info, bool post_processed);
   virtual int GetFrameCaptureStatus() { return frame_capture_status_; }
+  virtual DisplayError SetDetailEnhancerConfig(const DisplayDetailEnhancerData &de_data);
   virtual DisplayError ControlPartialUpdate(bool enable, uint32_t *pending);
 
  private:
diff --git a/sdm/libs/hwc2/hwc_session.cpp b/sdm/libs/hwc2/hwc_session.cpp
index 60db660..66ab568 100644
--- a/sdm/libs/hwc2/hwc_session.cpp
+++ b/sdm/libs/hwc2/hwc_session.cpp
@@ -1330,6 +1330,11 @@
       ret = color_mgr_->SetFrameCapture(pending_action.params, false,
                                         hwc_display_[HWC_DISPLAY_PRIMARY]);
       break;
+    case kConfigureDetailedEnhancer:
+      ret = color_mgr_->SetDetailedEnhancer(pending_action.params,
+                                            hwc_display_[HWC_DISPLAY_PRIMARY]);
+      callbacks_.Refresh(HWC_DISPLAY_PRIMARY);
+      break;
     case kNoAction:
       break;
     default:
diff --git a/sdm/libs/utils/Android.mk b/sdm/libs/utils/Android.mk
index f482a6d..928f3c4 100644
--- a/sdm/libs/utils/Android.mk
+++ b/sdm/libs/utils/Android.mk
@@ -5,10 +5,7 @@
 LOCAL_MODULE                  := libsdmutils
 LOCAL_MODULE_TAGS             := optional
 LOCAL_C_INCLUDES              := $(common_includes)
-LOCAL_CFLAGS                  := -Wno-missing-field-initializers \
-                                 -std=c++11 -fcolor-diagnostics\
-                                 -DLOG_TAG=\"SDM\" $(common_flags)
-LOCAL_CLANG                   := true
+LOCAL_CFLAGS                  := -DLOG_TAG=\"SDM\" $(common_flags)
 LOCAL_SRC_FILES               := debug.cpp \
                                  rect.cpp \
                                  sys.cpp \
diff --git a/sdm/libs/utils/Makefile.am b/sdm/libs/utils/Makefile.am
new file mode 100644
index 0000000..5b0eaab
--- /dev/null
+++ b/sdm/libs/utils/Makefile.am
@@ -0,0 +1,10 @@
+cpp_sources = debug.cpp \
+              rect.cpp \
+              sys.cpp \
+              formats.cpp
+
+lib_LTLIBRARIES = libsdmutils.la
+libsdmutils_la_CC = @CC@
+libsdmutils_la_SOURCES = $(cpp_sources)
+libsdmutils_la_CFLAGS = $(COMMON_CFLAGS) -DLOG_TAG=\"SDM\"
+libsdmutils_la_CPPFLAGS = $(AM_CPPFLAGS)
\ No newline at end of file
diff --git a/sdm/libs/utils/debug.cpp b/sdm/libs/utils/debug.cpp
index b91cdf4..cf60a37 100644
--- a/sdm/libs/utils/debug.cpp
+++ b/sdm/libs/utils/debug.cpp
@@ -99,6 +99,13 @@
   return value;
 }
 
+int Debug::GetMaxVideoUpscale() {
+  int value = 0;
+  debug_.debug_handler_->GetProperty("sdm.video_max_upscale", &value);
+
+  return value;
+}
+
 bool Debug::IsVideoModeEnabled() {
   int value = 0;
   debug_.debug_handler_->GetProperty("sdm.video_mode_panel", &value);
@@ -140,6 +147,20 @@
   return (ubwc_framebuffer == 1);
 }
 
+bool Debug::IsAVRDisabled() {
+  int value = 0;
+  debug_.debug_handler_->GetProperty("sdm.debug.disable_avr", &value);
+
+  return (value == 1);
+}
+
+bool Debug::IsExtAnimDisabled() {
+  int value = 0;
+  debug_.debug_handler_->GetProperty("sys.disable_ext_animation", &value);
+
+  return (value == 1);
+}
+
 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/sys.cpp b/sdm/libs/utils/sys.cpp
index 0ce524e..0d1ab0e 100644
--- a/sdm/libs/utils/sys.cpp
+++ b/sdm/libs/utils/sys.cpp
@@ -70,7 +70,7 @@
   Close();
   lib_ = ::dlopen(lib_name, RTLD_NOW);
 
-  return (*this);
+  return (lib_ != NULL);
 }
 
 bool DynLib::Sym(const char *func_name, void **func_ptr) {