Merge "hwc: Add padding round on virtual display"
diff --git a/Android.mk b/Android.mk
index 4a951c8..b3015af 100644
--- a/Android.mk
+++ b/Android.mk
@@ -1,14 +1,13 @@
 # This flag will be set to true during migration to Snapdragon Display Engine.
 TARGET_USES_SDE = false
 
-display-hals := libgralloc libcopybit liblight libmemtrack
+display-hals := libgralloc libcopybit liblight libmemtrack libqservice
 
 ifeq ($(TARGET_USES_SDE), true)
     sde-libs := displayengine/libs
     display-hals += $(sde-libs)/utils $(sde-libs)/core $(sde-libs)/hwc
 else
     display-hals += libgenlock libhwcomposer liboverlay libqdutils libhdmi
-    display-hals += libqservice
 endif
 
 ifeq ($(call is-vendor-board-platform,QCOM),true)
diff --git a/common.mk b/common.mk
index a2283c4..768696a 100644
--- a/common.mk
+++ b/common.mk
@@ -7,11 +7,6 @@
 common_includes += $(LOCAL_PATH)/../libhdmi
 common_includes += $(LOCAL_PATH)/../libqservice
 
-ifeq ($(TARGET_USES_POST_PROCESSING),true)
-    common_flags     += -DUSES_POST_PROCESSING
-    common_includes  += $(TARGET_OUT_HEADERS)/pp/inc
-endif
-
 common_header_export_path := qcom/display
 
 #Common libraries external to display HAL
@@ -21,21 +16,19 @@
 common_flags := -DDEBUG_CALC_FPS -Wno-missing-field-initializers
 common_flags += -Wconversion -Wall -Werror
 
+ifeq ($(TARGET_USES_POST_PROCESSING),true)
+    common_flags     += -DUSES_POST_PROCESSING
+    common_includes  += $(TARGET_OUT_HEADERS)/pp/inc
+endif
+
 ifeq ($(ARCH_ARM_HAVE_NEON),true)
     common_flags += -D__ARM_HAVE_NEON
 endif
 
 ifeq ($(call is-board-platform-in-list, $(MSM_VIDC_TARGET_LIST)), true)
     common_flags += -DVENUS_COLOR_FORMAT
-endif
-
-ifeq ($(call is-board-platform-in-list, msm8974 msm8226 msm8610 apq8084 \
-        mpq8092 msm_bronze msm8916 msm8994), true)
     common_flags += -DMDSS_TARGET
 endif
-ifeq ($(call is-board-platform-in-list, msm8909), true)
-    common_flags += -DVENUS_COLOR_FORMAT
-endif
 
 common_deps  :=
 kernel_includes :=
diff --git a/displayengine/include/core/core_interface.h b/displayengine/include/core/core_interface.h
old mode 100644
new mode 100755
index 45d9c8c..2229d1e
--- a/displayengine/include/core/core_interface.h
+++ b/displayengine/include/core/core_interface.h
@@ -35,20 +35,20 @@
 #include <stdint.h>
 
 #include "display_interface.h"
-#include "display_types.h"
+#include "sde_types.h"
 
-/*! @brief Display core interface version.
+/*! @brief Display engine interface version.
 
-  @details Display core interfaces are version tagged to maintain backward compatibility. This
+  @details Display engine interfaces are version tagged to maintain backward compatibility. This
   version is supplied as a default argument during display core initialization.
 
-  Client may use an older version of interfaces and link to a higher version of display core
+  Client may use an older version of interfaces and link to a higher version of display engine
   library, but vice versa is not allowed.
 
   A 32-bit client must use 32-bit display core library and a 64-bit client must use 64-bit display
   core library.
 
-  Display core interfaces follow default data structures alignment. Client must not override the
+  Display engine interfaces follow default data structures alignment. Client must not override the
   default padding rules while using these interfaces.
 
   @warning It is assumed that client upgrades or downgrades display core interface all at once
@@ -57,11 +57,11 @@
 
   @sa CoreInterface::CreateCore
 */
-#define CORE_REVISION_MAJOR (1)
-#define CORE_REVISION_MINOR (0)
+#define SDE_REVISION_MAJOR (1)
+#define SDE_REVISION_MINOR (0)
 
-#define CORE_VERSION_TAG ((uint32_t) ((CORE_REVISION_MAJOR << 24) | (CORE_REVISION_MINOR << 16) \
-                    | (sizeof(DisplayCompatibility) << 8) | sizeof(int *)))
+#define SDE_VERSION_TAG ((uint32_t) ((SDE_REVISION_MAJOR << 24) | (SDE_REVISION_MINOR << 16) | \
+                                    (sizeof(SDECompatibility) << 8) | sizeof(int *)))
 
 namespace sde {
 
@@ -120,15 +120,16 @@
     This interface shall be called only once.
 
     @param[in] event_handler \link CoreEventHandler \endlink
+    @param[in] log_handler \link LogHandler \endlink
     @param[out] interface \link CoreInterface \endlink
-    @param[in] version \link CORE_VERSION_TAG \endlink. Client must not override this argument.
+    @param[in] version \link SDE_VERSION_TAG \endlink. Client must not override this argument.
 
     @return \link DisplayError \endlink
 
     @sa DestroyCore
   */
-  static DisplayError CreateCore(CoreEventHandler *event_handler, CoreInterface **interface,
-                                 uint32_t version = CORE_VERSION_TAG);
+  static DisplayError CreateCore(CoreEventHandler *event_handler, LogHandler *log_handler,
+                                 CoreInterface **interface, uint32_t version = SDE_VERSION_TAG);
 
   /*! @brief Method to release handle to display core interface.
 
@@ -159,7 +160,7 @@
     @sa DestroyDisplay
   */
   virtual DisplayError CreateDisplay(DisplayType type, DisplayEventHandler *event_handler,
-                                    DisplayInterface **interface) = 0;
+                                     DisplayInterface **interface) = 0;
 
   /*! @brief Method to destroy a display device.
 
diff --git a/displayengine/include/core/display_interface.h b/displayengine/include/core/display_interface.h
old mode 100644
new mode 100755
index bb03921..bdeb8a3
--- a/displayengine/include/core/display_interface.h
+++ b/displayengine/include/core/display_interface.h
@@ -36,7 +36,7 @@
 #include <stdint.h>
 
 #include "layer_stack.h"
-#include "display_types.h"
+#include "sde_types.h"
 
 namespace sde {
 
@@ -94,6 +94,7 @@
   float y_dpi;                //!< Dots per inch in Y-direction.
   float fps;                  //!< Frame rate per second.
   uint32_t vsync_period_ns;   //!< VSync period in nanoseconds.
+  uint32_t v_total;           //!< Total lines in Y-direction (vActive + vFP + vBP + vPulseWidth).
 
   DisplayConfigVariableInfo() : x_pixels(0), y_pixels(0), x_dpi(0.0f), y_dpi(0.0f),
                                fps(0.0f), vsync_period_ns(0) { }
@@ -235,12 +236,20 @@
 
   /*! @brief Method to get configuration for variable properties of the display device.
 
-    @param[in] mode index of the mode
+    @param[in] index index of the mode
     @param[out] variable_info \link DisplayConfigVariableInfo \endlink
 
     @return \link DisplayError \endlink
   */
-  virtual DisplayError GetConfig(DisplayConfigVariableInfo *variable_info, uint32_t mode) = 0;
+  virtual DisplayError GetConfig(uint32_t index, DisplayConfigVariableInfo *variable_info) = 0;
+
+  /*! @brief Method to get index of active configuration of the display device.
+
+    @param[out] index index of the mode corresponding to variable properties.
+
+    @return \link DisplayError \endlink
+  */
+  virtual DisplayError GetActiveConfig(uint32_t *index) = 0;
 
   /*! @brief Method to get VSync event state. Default event state is disabled.
 
@@ -260,13 +269,13 @@
   */
   virtual DisplayError SetDisplayState(DisplayState state) = 0;
 
-  /*! @brief Method to set configuration for variable properties of the display device.
+  /*! @brief Method to set active configuration for variable properties of the display device.
 
-    @param[in] mode index of the mode corresponding to variable properties.
+    @param[in] index index of the mode corresponding to variable properties.
 
     @return \link DisplayError \endlink
   */
-  virtual DisplayError SetConfig(uint32_t mode) = 0;
+  virtual DisplayError SetActiveConfig(uint32_t index) = 0;
 
   /*! @brief Method to set VSync event state. Default event state is disabled.
 
diff --git a/displayengine/include/core/display_types.h b/displayengine/include/core/display_types.h
deleted file mode 100644
index 128e7d9..0000000
--- a/displayengine/include/core/display_types.h
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
-* Copyright (c) 2014, The Linux Foundation. All rights reserved.
-*
-* Redistribution and use in source and binary forms, with or without modification, are permitted
-* provided that the following conditions are met:
-*    * Redistributions of source code must retain the above copyright notice, this list of
-*      conditions and the following disclaimer.
-*    * Redistributions in binary form must reproduce the above copyright notice, this list of
-*      conditions and the following disclaimer in the documentation and/or other materials provided
-*      with the distribution.
-*    * Neither the name of The Linux Foundation nor the names of its contributors may be used to
-*      endorse or promote products derived from this software without specific prior written
-*      permission.
-*
-* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-* NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
-* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
-* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
-* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
-* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
-
-/*! @file display_types.h
-  @brief This file contains miscellaneous data types used across display interfaces.
-*/
-#ifndef __DISPLAY_TYPES_H__
-#define __DISPLAY_TYPES_H__
-
-namespace sde {
-
-/*! @brief This enum represents different error codes that display interfaces may return.
-*/
-enum DisplayError {
-  kErrorNone = 0,         //!< Call executed successfully.
-  kErrorUndefined,        //!< An unspecified error has occured.
-  kErrorNotSupported,     //!< Requested operation is not supported.
-  kErrorVersion,          //!< Client is using advanced version of interfaces and calling into an
-                          //!< older version of display library.
-  kErrorDataAlignment,    //!< Client data structures are not aligned on naturual boundaries.
-  kErrorInstructionSet,   //!< 32-bit client is calling into 64-bit library or vice versa.
-  kErrorParameters,       //!< Invalid parameters passed to a method.
-  kErrorFileDescriptor,   //!< Invalid file descriptor.
-  kErrorMemory,           //!< System is running low on memory.
-  kErrorResources,        //!< Not enough hardware resources available to execute call.
-  kErrorHardware,         //!< A hardware error has occured.
-  kErrorTimeOut,          //!< The operation has timed out to prevent client from waiting forever.
-};
-
-/*! @brief This structure is defined for client and library compatibility check purpose only. This
-  structure is used in CORE_VERSION_TAG definition only. Client should not refer it directly for
-  any purpose.
-*/
-struct DisplayCompatibility {
-  char c1;
-  int i1;
-  char c2;
-  int i2;
-};
-
-}  // namespace sde
-
-#endif  // __DISPLAY_TYPES_H__
-
diff --git a/displayengine/include/core/dump_interface.h b/displayengine/include/core/dump_interface.h
old mode 100644
new mode 100755
index acdc71f..20ab748
--- a/displayengine/include/core/dump_interface.h
+++ b/displayengine/include/core/dump_interface.h
@@ -31,7 +31,7 @@
 
 #include <stdint.h>
 
-#include "display_types.h"
+#include "sde_types.h"
 
 namespace sde {
 
diff --git a/displayengine/include/core/layer_buffer.h b/displayengine/include/core/layer_buffer.h
old mode 100644
new mode 100755
index 421ab87..c069c60
--- a/displayengine/include/core/layer_buffer.h
+++ b/displayengine/include/core/layer_buffer.h
@@ -31,7 +31,7 @@
 
 #include <stdint.h>
 
-#include "display_types.h"
+#include "sde_types.h"
 
 namespace sde {
 
@@ -76,6 +76,10 @@
                                       //!<    v(0), u(0), v(2), u(2) ... v(n-1), u(n-1)
                                       //!< aka NV21.
 
+  kFormatYCbCr420SemiPlanarVenus,     //!< Y-plane: y(0), y(1), y(2) ... y(n)
+                                      //!< 2x2 subsampled interleaved UV-plane:
+                                      //!<    u(0), v(0), u(2), v(2) ... u(n-1), v(n-1)
+
   /* All YUV-Packed formats, Any new format will be added towards end of this group to maintain
      backward compatibility.
   */
@@ -104,11 +108,13 @@
   @sa LayerBuffer
 */
 struct LayerBufferFlags {
-  uint64_t secure : 1;  //!< This flag shall be set by client to indicate that the buffer need
-                        //!< to be handled securely.
-  uint64_t video  : 1;  //!< This flag shall be set by client to indicate that the buffer is
-                        //!< video/ui buffer
-  LayerBufferFlags() : secure(0) { }
+  uint64_t secure : 1;      //!< This flag shall be set by client to indicate that the buffer need
+                            //!< to be handled securely.
+  uint64_t video  : 1;      //!< This flag shall be set by client to indicate that the buffer is
+                            //!< video/ui buffer
+  uint64_t macro_tile : 1;  //!< This flag shall be set by client to indicate that the buffer format
+                            //!< is macro tiled.
+  LayerBufferFlags() : secure(0), video(0), macro_tile(0) { }
 };
 
 /*! @brief This structure defines a layer buffer handle which contains raw buffer and its associated
diff --git a/displayengine/include/core/layer_stack.h b/displayengine/include/core/layer_stack.h
old mode 100644
new mode 100755
index 74c1960..67a812d
--- a/displayengine/include/core/layer_stack.h
+++ b/displayengine/include/core/layer_stack.h
@@ -34,7 +34,7 @@
 #include <stdint.h>
 
 #include "layer_buffer.h"
-#include "display_types.h"
+#include "sde_types.h"
 
 namespace sde {
 
@@ -43,7 +43,7 @@
   @sa Layer
 */
 enum LayerBlending {
-  kBlendingNone = 0,        //!< Blend operation is not specified.
+  kBlendingNone,            //!< Blend operation is not specified.
 
   kBlendingOpaque,          //!< Pixel color is expressed using straight alpha in color tuples. It
                             //!< is constant blend operation. The layer would appear opaque if plane
@@ -95,10 +95,12 @@
 struct LayerFlags {
   uint64_t skip : 1;      //!< This flag shall be set by client to indicate that this layer will be
                           //!< handled by GPU. Display Device will not consider it for composition.
+
   uint64_t updating : 1;  //!< This flag shall be set by client to indicate that this is updating/
                           //!< non-updating. so strategy manager will mark them for SDE/GPU
                           //!< composition respectively when the layer stack qualifies for cache
                           //!< based composition.
+
   LayerFlags() : skip(0), updating(0) { }
 };
 
@@ -111,12 +113,15 @@
   uint64_t geometry_changed : 1;  //!< This flag shall be set by client to indicate that the layer
                                   //!< set passed to Prepare() has changed by more than just the
                                   //!< buffer handles and acquire fences.
+
   uint64_t skip_present : 1;      //!< This flag will be set to true, if the current layer stack
-                                  //!< contains skip layers
+                                  //!< contains skip layers.
+
   uint64_t video_present : 1;     //!< This flag will be set to true, if current layer stack
-                                  //!< contains video
+                                  //!< contains video.
+
   uint64_t secure_present : 1;    //!< This flag will be set to true, if the current layer stack
-                                  //!< contains secure layers
+                                  //!< contains secure layers.
 
   LayerStackFlags() : geometry_changed(0), skip_present(0), video_present(0), secure_present(0) { }
 };
@@ -200,24 +205,24 @@
   @sa DisplayInterface::Commit
 */
 struct LayerStack {
-  union {
-    int retire_fence_fd;          //!< File descriptor referring to a sync fence object which will
-                                  //!< be signaled when this composited frame has been replaced on
-                                  //!< screen by a subsequent frame on a physical display. The fence
-                                  //!< object is created and returned during Commit(). Client shall
-                                  //!< Client shall close the returned file descriptor.
-                                  //!< NOTE: This field applies to a physical display only.
+  Layer *layers;                //!< Array of layers.
+  uint32_t layer_count;         //!< Total number of layers.
 
-    LayerBuffer *output_buffer;   //!< Pointer to the buffer where composed buffer would be rendered
-                                  //!< for virtual displays.
-                                  //!< NOTE: This field applies to a virtual display only.
-  };
+  int retire_fence_fd;          //!< File descriptor referring to a sync fence object which will
+                                //!< be signaled when this composited frame has been replaced on
+                                //!< screen by a subsequent frame on a physical display. The fence
+                                //!< object is created and returned during Commit(). Client shall
+                                //!< Client shall close the returned file descriptor.
+                                //!< NOTE: This field applies to a physical display only.
 
-  Layer *layers;          //!< Array of layers.
-  uint32_t layer_count;   //!< Total number of layers.
-  LayerStackFlags flags;  //!< Flags associated with this layer set.
+  LayerBuffer *output_buffer;   //!< Pointer to the buffer where composed buffer would be rendered
+                                //!< for virtual displays.
+                                //!< NOTE: This field applies to a virtual display only.
 
-  LayerStack() : output_buffer(NULL) { }
+
+  LayerStackFlags flags;        //!< Flags associated with this layer set.
+
+  LayerStack() : layers(NULL), layer_count(0), retire_fence_fd(-1), output_buffer(NULL) { }
 };
 
 }  // namespace sde
diff --git a/displayengine/include/core/sde_types.h b/displayengine/include/core/sde_types.h
new file mode 100755
index 0000000..6090889
--- /dev/null
+++ b/displayengine/include/core/sde_types.h
@@ -0,0 +1,118 @@
+/*
+* Copyright (c) 2014, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without modification, are permitted
+* provided that the following conditions are met:
+*    * Redistributions of source code must retain the above copyright notice, this list of
+*      conditions and the following disclaimer.
+*    * Redistributions in binary form must reproduce the above copyright notice, this list of
+*      conditions and the following disclaimer in the documentation and/or other materials provided
+*      with the distribution.
+*    * Neither the name of The Linux Foundation nor the names of its contributors may be used to
+*      endorse or promote products derived from this software without specific prior written
+*      permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/*! @file sde_types.h
+  @brief This file contains miscellaneous data types used across display interfaces.
+*/
+#ifndef __SDE_TYPES_H__
+#define __SDE_TYPES_H__
+
+namespace sde {
+
+/*! @brief This enum represents different error codes that display interfaces may return.
+*/
+enum DisplayError {
+  kErrorNone,             //!< Call executed successfully.
+  kErrorUndefined,        //!< An unspecified error has occured.
+  kErrorNotSupported,     //!< Requested operation is not supported.
+  kErrorVersion,          //!< Client is using advanced version of interfaces and calling into an
+                          //!< older version of display library.
+  kErrorDataAlignment,    //!< Client data structures are not aligned on naturual boundaries.
+  kErrorInstructionSet,   //!< 32-bit client is calling into 64-bit library or vice versa.
+  kErrorParameters,       //!< Invalid parameters passed to a method.
+  kErrorFileDescriptor,   //!< Invalid file descriptor.
+  kErrorMemory,           //!< System is running low on memory.
+  kErrorResources,        //!< Not enough hardware resources available to execute call.
+  kErrorHardware,         //!< A hardware error has occured.
+  kErrorTimeOut,          //!< The operation has timed out to prevent client from waiting forever.
+};
+
+/*! @brief This enum represents different modules/logical unit tags that a log message may be
+  associated with. Client may use this to filter messages for dynamic logging.
+
+  @sa DisplayLogHandler
+*/
+enum LogTag {
+  kTagNone,             //!< Log is not tagged. This type of logs should always be printed.
+  kTagResources,        //!< Log is tagged for resource management.
+  kTagStrategy,         //!< Log is tagged for strategy decisions.
+};
+
+/*! @brief Display log handler class.
+
+  @details This class defines display log handler. The handle contains methods which client should
+  implement to get different levels of logging from display engine. Display engine will call into
+  these methods at appropriate times to send logging information.
+
+  @sa CoreInterface::CreateCore
+*/
+class LogHandler {
+ public:
+  /*! @brief Method to handle error messages.
+
+    @param[in] tag \link LogTag \endlink
+    @param[in] format \link message format with variable argument list \endlink
+  */
+  virtual void Error(LogTag tag, const char *format, ...) = 0;
+
+  /*! @brief Method to handle warning messages.
+
+    @param[in] tag \link LogTag \endlink
+    @param[in] format \link message format with variable argument list \endlink
+  */
+  virtual void Warning(LogTag tag, const char *format, ...) = 0;
+
+  /*! @brief Method to handle informative messages.
+
+    @param[in] tag \link LogTag \endlink
+    @param[in] format \link message format with variable argument list \endlink
+  */
+  virtual void Info(LogTag tag, const char *format, ...) = 0;
+
+  /*! @brief Method to handle verbose messages.
+
+    @param[in] tag \link LogTag \endlink
+    @param[in] format \link message format with variable argument list \endlink
+  */
+  virtual void Verbose(LogTag tag, const char *format, ...) = 0;
+
+ protected:
+  virtual ~LogHandler() { }
+};
+
+/*! @brief This structure is defined for client and library compatibility check purpose only. This
+  structure is used in SDE_VERSION_TAG definition only. Client should not refer it directly for
+  any purpose.
+*/
+struct SDECompatibility {
+  char c1;
+  int i1;
+  char c2;
+  int i2;
+};
+
+}  // namespace sde
+
+#endif  // __SDE_TYPES_H__
+
diff --git a/displayengine/include/private/strategy_interface.h b/displayengine/include/private/strategy_interface.h
index 8a3b789..eac88cc 100644
--- a/displayengine/include/private/strategy_interface.h
+++ b/displayengine/include/private/strategy_interface.h
@@ -29,69 +29,106 @@
 #ifndef __STRATEGY_INTERFACE_H__
 #define __STRATEGY_INTERFACE_H__
 
-#include <core/display_types.h>
+#include <core/sde_types.h>
+#include <core/display_interface.h>
 
 namespace sde {
 
 /*! @brief Strategy library name
 
-    @details This macro defines name for the composition strategy library. This macro shall be used
-    to load library using dlopen().
+  @details This macro defines name for the composition strategy library. This macro shall be used
+  to load library using dlopen().
 
-    @sa GetStrategyInterface
+  @sa CreateStrategyInterface
+  @sa DestoryStrategyInterface
 */
 #define STRATEGY_LIBRARY_NAME "libsdestrategy.so"
 
-/*! @brief Function name to get composer strategy interface
+/*! @brief Function name to create composer strategy interface
 
-    @details This macro defines function name for GetStrategyInterface() which will be implemented
-    in the composition strategy library. This macro shall be used to specify name of the function
-    in dlsym().
+  @details This macro defines function name for CreateStrategyInterface() which is implemented in
+  the composition strategy library. This macro shall be used to specify name of the function in
+  dlsym().
 
-    @sa GetStrategyInterface
+  @sa CreateStrategyInterface
 */
-#define GET_STRATEGY_INTERFACE_NAME "GetStrategyInterface"
+#define CREATE_STRATEGY_INTERFACE_NAME "CreateStrategyInterface"
+
+/*! @brief Function name to destroy composer strategy interface
+
+  @details This macro defines function name for DestroyStrategyInterface() which is implemented in
+  the composition strategy library. This macro shall be used to specify name of the function in
+  dlsym().
+
+  @sa DestroyStrategyInterface
+*/
+#define DESTROY_STRATEGY_INTERFACE_NAME "DestroyStrategyInterface"
+
+/*! @brief Strategy interface version.
+
+  @details Strategy interface is version tagged to maintain backward compatibility. This version is
+  supplied as a default argument during strategy library initialization.
+
+  Client may use an older version of interfaces and link to a higher version of strategy library,
+  but vice versa is not allowed.
+
+  @sa CreateStrategyInterface
+*/
+#define STRATEGY_REVISION_MAJOR (1)
+#define STRATEGY_REVISION_MINOR (0)
+
+#define STRATEGY_VERSION_TAG ((uint16_t) ((STRATEGY_REVISION_MAJOR << 8) | STRATEGY_REVISION_MINOR))
 
 class StrategyInterface;
 
-/*! @brief Function to get composer strategy interface.
+/*! @brief Function to create composer strategy interface.
 
-    @details This function is used to get StrategyInterface object which resides in the composer
-    strategy library loaded at runtime.
+  @details This function is used to create StrategyInterface object which resides in the composer
+  strategy library loaded at runtime.
 
-    @param[out] interface \link StrategyInterface \endlink
+  @param[in] version \link STRATEGY_VERSION_TAG \endlink
+  @param[in] type \link DisplayType \endlink
+  @param[out] interface \link StrategyInterface \endlink
 
-    @return \link DisplayError \endlink
+  @return \link DisplayError \endlink
 */
-typedef DisplayError (*GetStrategyInterface)(StrategyInterface **interface);
+typedef DisplayError (*CreateStrategyInterface)(uint16_t version, DisplayType type,
+                      StrategyInterface **interface);
+
+/*! @brief Function to destroy composer strategy interface.
+
+  @details This function is used to destroy StrategyInterface object.
+
+  @param[in] interface \link StrategyInterface \endlink
+
+  @return \link DisplayError \endlink
+*/
+typedef DisplayError (*DestroyStrategyInterface)(StrategyInterface *interface);
 
 /*! @brief Maximum number of layers that can be handled by hardware in a given layer stack.
 */
 const int kMaxSDELayers = 16;
 
 /*! @brief This structure defines constraints and display properties that shall be considered for
-    deciding a composition strategy.
+  deciding a composition strategy.
 
-    @sa GetNextStrategy
+  @sa GetNextStrategy
 */
 struct StrategyConstraints {
   bool safe_mode;         //!< In this mode, strategy manager chooses the composition strategy
                           //!< that requires minimum number of pipe for the current frame. i.e.,
                           //!< video only composition, secure only composition or GPU composition
+
   uint32_t max_layers;    //!< Maximum number of layers that shall be programmed on hardware for the
                           //!< given layer stack.
 
   StrategyConstraints() : safe_mode(false), max_layers(kMaxSDELayers) { }
 };
 
-/*! @brief Flag to denote that GPU composition is performed for the given layer stack.
-*/
-const uint32_t kFlagGPU = 0x1;
-
 /*! @brief This structure encapsulates information about the input layer stack and the layers which
-    shall be programmed on hardware.
+  shall be programmed on hardware.
 
-    @sa GetNextStrategy
+  @sa Start
 */
 struct HWLayersInfo {
   LayerStack *stack;        //!< Input layer stack. Set by the caller.
@@ -99,36 +136,49 @@
   uint32_t index[kMaxSDELayers];
                             //!< Indexes of the layers from the layer stack which need to be
                             //!< programmed on hardware.
+
   uint32_t count;           //!< Total number of layers which need to be set on hardware.
-  uint32_t flags;           //!< Strategy flags. There is one flag set for each of the strategy
-                            //!< that has been selected for this layer stack. This flag is preserved
-                            //!< between multiple GetNextStrategy() calls. Composition manager
-                            //!< relies on the total flag count to check the number of strategies
-                            //!< that are attempted for this layer stack.
 
-  HWLayersInfo() {
-    Reset();
-  }
-
-  void Reset() {
-    stack = NULL;
-    count = 0;
-    flags = 0;
-  }
+  HWLayersInfo() : stack(NULL), count(0) { }
 };
 
+/*! @brief Strategy interface.
+
+  @details This class defines Strategy interface. It contains methods which client shall use to
+  determine which strategy to be used for layer composition. This interface is created during
+  display device creation and remains valid until destroyed.
+*/
+
 class StrategyInterface {
  public:
+  /*! @brief Method to indicate start of a new strategy selection iteration for a layer stack.
+
+    @details Client shall call this method at beginning of each draw cycle before iterating
+    through strategy selection. Strategy interface implementation uses this method to do
+    preprocessing for a given layer stack.
+
+    @param[in] layers_info \link HWLayersInfo \endlink
+    @param[out] max_attempts Maximum calls to \link GetNextStrategy \endlink
+
+    @return \link DisplayError \endlink
+  */
+  virtual DisplayError Start(HWLayersInfo *hw_layers_info, uint32_t *max_attempts) = 0;
+
+
   /*! @brief Method to get strategy for a layer stack. Caller can loop through this method to try
     get all applicable strategies.
 
     @param[in] constraints \link StrategyConstraints \endlink
-    @param[inout] layers_info \link HWLayersInfo \endlink
 
     @return \link DisplayError \endlink
   */
-  virtual DisplayError GetNextStrategy(StrategyConstraints *constraints,
-                                       HWLayersInfo *hw_layers_info) = 0;
+  virtual DisplayError GetNextStrategy(StrategyConstraints *constraints) = 0;
+
+  /*! @brief Method to indicate end of a strategy selection cycle.
+
+    @return \link DisplayError \endlink
+  */
+  virtual DisplayError Stop() = 0;
 
  protected:
   virtual ~StrategyInterface() { }
diff --git a/displayengine/include/utils/constants.h b/displayengine/include/utils/constants.h
index 7d7a39c..a7b9f0f 100644
--- a/displayengine/include/utils/constants.h
+++ b/displayengine/include/utils/constants.h
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2014, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014 - 2015, The Linux Foundation. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification, are permitted
 * provided that the following conditions are met:
@@ -30,6 +30,7 @@
 
 #define INT(exp) static_cast<int>(exp)
 #define FLOAT(exp) static_cast<float>(exp)
+#define UINT8(exp) static_cast<uint8_t>(exp)
 #define UINT32(exp) static_cast<uint32_t>(exp)
 #define INT32(exp) static_cast<int32_t>(exp)
 
@@ -43,12 +44,15 @@
 
 #define ROUND_UP(number, step) ((((number) + ((step) - 1)) / (step)) * (step))
 
-#define SET_BIT(value, bit) ((value) | (1 << (bit)))
-#define CLEAR_BIT(value, bit) ((value) & (~(1 << (bit))))
+#define SET_BIT(value, bit) (value |= (1 << (bit)))
+#define CLEAR_BIT(value, bit) (value &= (~(1 << (bit))))
+#define IS_BIT_SET(value, bit) (value & (1 << (bit)))
+#define MAX(a, b) (((a) > (b)) ? (a) : (b))
 
 namespace sde {
 
   const int kThreadPriorityUrgent = -9;
+  const int kMaxRotatePerLayer = 2;
 
   typedef void * Handle;
 
diff --git a/displayengine/include/utils/debug.h b/displayengine/include/utils/debug.h
old mode 100644
new mode 100755
index 0691dfc..99d3968
--- a/displayengine/include/utils/debug.h
+++ b/displayengine/include/utils/debug.h
@@ -25,45 +25,47 @@
 #ifndef __DEBUG_H__
 #define __DEBUG_H__
 
-#ifndef SDE_LOG_TAG
-#define SDE_LOG_TAG kLogTagNone
-#endif
+#include <stdint.h>
+#include <core/sde_types.h>
 
-#ifndef SDE_MODULE_NAME
-#define SDE_MODULE_NAME "SDE"
-#endif
+#define DLOG(tag, method, format, ...) Debug::GetLogHandler()->method(tag, \
+                                            __CLASS__ "::%s: " format, __FUNCTION__, ##__VA_ARGS__)
 
-#define DLOG(method, format, ...) Debug::method(SDE_LOG_TAG, SDE_MODULE_NAME ": " format, \
-                                                ##__VA_ARGS__)
+#define DLOGE_IF(tag, format, ...) DLOG(tag, Error, format, ##__VA_ARGS__)
+#define DLOGW_IF(tag, format, ...) DLOG(tag, Warning, format, ##__VA_ARGS__)
+#define DLOGI_IF(tag, format, ...) DLOG(tag, Info, format, ##__VA_ARGS__)
+#define DLOGV_IF(tag, format, ...) DLOG(tag, Verbose, format, ##__VA_ARGS__)
 
-// SDE_LOG_TAG and SDE_MODULE_NAME must be defined before #include this header file in
-// respective module, else default definitions are used.
-#define DLOGE(format, ...) DLOG(Error, format, ##__VA_ARGS__)
-#define DLOGW(format, ...) DLOG(Warning, format, ##__VA_ARGS__)
-#define DLOGI(format, ...) DLOG(Info, format, ##__VA_ARGS__)
-#define DLOGV(format, ...) DLOG(Verbose, format, ##__VA_ARGS__)
+#define DLOGE(format, ...) DLOGE_IF(kTagNone, format, ##__VA_ARGS__)
+#define DLOGW(format, ...) DLOGW_IF(kTagNone, format, ##__VA_ARGS__)
+#define DLOGI(format, ...) DLOGI_IF(kTagNone, format, ##__VA_ARGS__)
+#define DLOGV(format, ...) DLOGV_IF(kTagNone, format, ##__VA_ARGS__)
 
 namespace sde {
 
-enum LogTag {
-  kTagNone = 0,   // Log tag name is not specified.
-  kTagCore,       // Log is tagged for display core.
-  kTagStrategy,   // Log is tagged for composition strategy.
-};
-
 class Debug {
  public:
-  // Log handlers
-  static void Error(const LogTag &tag, const char *format, ...);
-  static void Warning(const LogTag &tag, const char *format, ...);
-  static void Info(const LogTag &tag, const char *format, ...);
-  static void Verbose(const LogTag &tag, const char *format, ...);
-
-  // Debug properties
-  static bool IsVirtualDriver() { return debug_.virtual_driver_; }
+  static inline void SetLogHandler(LogHandler *log_handler) { debug_.log_handler_ = log_handler; }
+  static inline LogHandler* GetLogHandler() { return debug_.log_handler_; }
+  static inline bool IsVirtualDriver() { return debug_.virtual_driver_; }
+  static uint32_t GetSimulationFlag();
+  static uint32_t GetHDMIResolution();
 
  private:
   Debug();
+
+  // By default, drop any log messages coming from Display Engine. It will be overriden by Display
+  // Engine client when core is successfully initialized.
+  class DefaultLogHandler : public LogHandler {
+   public:
+    virtual void Error(LogTag /*tag*/, const char */*format*/, ...) { }
+    virtual void Warning(LogTag /*tag*/, const char */*format*/, ...) { }
+    virtual void Info(LogTag /*tag*/, const char */*format*/, ...) { }
+    virtual void Verbose(LogTag /*tag*/, const char */*format*/, ...) { }
+  };
+
+  DefaultLogHandler default_log_handler_;
+  LogHandler *log_handler_;
   bool virtual_driver_;
   static Debug debug_;
 };
diff --git a/displayengine/libs/common.mk b/displayengine/libs/common.mk
deleted file mode 100644
index 79ba738..0000000
--- a/displayengine/libs/common.mk
+++ /dev/null
@@ -1,39 +0,0 @@
-#Common headers
-common_includes := hardware/qcom/display/displayengine/include/
-common_includes += hardware/qcom/display/libgralloc/
-common_includes += hardware/qcom/display/libcopybit/
-
-common_header_export_path := qcom/display
-
-#Common libraries external to display HAL
-common_libs := liblog libutils libcutils libhardware
-
-#Common C flags
-common_flags := -DDEBUG_CALC_FPS -Wno-missing-field-initializers
-common_flags += -Wconversion -Wall -Werror
-common_flags += -Wno-unused-parameter -Wno-unused-variable
-
-ifeq ($(ARCH_ARM_HAVE_NEON),true)
-    common_flags += -D__ARM_HAVE_NEON
-endif
-
-ifeq ($(call is-board-platform-in-list, $(MSM_VIDC_TARGET_LIST)), true)
-    common_flags += -DVENUS_COLOR_FORMAT
-endif
-
-ifeq ($(call is-board-platform-in-list, msm8994), true)
-    common_flags += -DMDSS_TARGET
-endif
-
-common_deps  :=
-kernel_includes :=
-
-ifeq ($(call is-vendor-board-platform,QCOM),true)
-# This check is to pick the kernel headers from the right location.
-# If the macro above is defined, we make the assumption that we have the kernel
-# available in the build tree.
-# If the macro is not present, the headers are picked from hardware/qcom/msmXXXX
-# failing which, they are picked from bionic.
-    common_deps += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr
-    kernel_includes += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr/include
-endif
diff --git a/displayengine/libs/core/Android.mk b/displayengine/libs/core/Android.mk
index 337cb73..92569a5 100644
--- a/displayengine/libs/core/Android.mk
+++ b/displayengine/libs/core/Android.mk
@@ -1,13 +1,15 @@
 LOCAL_PATH := $(call my-dir)
-include hardware/qcom/display/displayengine/libs/common.mk
 include $(CLEAR_VARS)
 
 LOCAL_MODULE                  := libsde
 LOCAL_MODULE_TAGS             := optional
-LOCAL_C_INCLUDES              := $(common_includes) $(kernel_includes)
-LOCAL_CFLAGS                  := $(common_flags) -DLOG_TAG=\"SDE\"
-LOCAL_SHARED_LIBRARIES        := $(common_libs) libdl libsdeutils
-LOCAL_ADDITIONAL_DEPENDENCIES := $(common_deps)
+LOCAL_C_INCLUDES              := hardware/qcom/display/displayengine/include/ \
+                                 $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr/include
+LOCAL_CFLAGS                  := -Wno-missing-field-initializers -Wno-unused-parameter \
+                                 -Wconversion -Wall -Werror \
+                                 -DLOG_TAG=\"SDE\"
+LOCAL_SHARED_LIBRARIES        := libdl libsdeutils
+LOCAL_ADDITIONAL_DEPENDENCIES := $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr
 LOCAL_SRC_FILES               := core_interface.cpp \
                                  core_impl.cpp \
                                  display_base.cpp \
diff --git a/displayengine/libs/core/comp_manager.cpp b/displayengine/libs/core/comp_manager.cpp
index 0d51bb0..40191e5 100644
--- a/displayengine/libs/core/comp_manager.cpp
+++ b/displayengine/libs/core/comp_manager.cpp
@@ -22,20 +22,20 @@
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
-// SDE_LOG_TAG definition must precede debug.h include.
-#define SDE_LOG_TAG kTagCore
-#define SDE_MODULE_NAME "CompManager"
-#include <utils/debug.h>
-
 #include <dlfcn.h>
 #include <utils/constants.h>
+#include <utils/debug.h>
 
 #include "comp_manager.h"
+#include "strategy_default.h"
+
+#define __CLASS__ "CompManager"
 
 namespace sde {
 
-CompManager::CompManager() : strategy_lib_(NULL), strategy_intf_(NULL), registered_displays_(0),
-                             configured_displays_(0), safe_mode_(false) {
+CompManager::CompManager()
+  : strategy_lib_(NULL), create_strategy_intf_(NULL), destroy_strategy_intf_(NULL),
+    registered_displays_(0), configured_displays_(0), safe_mode_(false) {
 }
 
 DisplayError CompManager::Init(const HWResourceInfo &hw_res_info) {
@@ -44,36 +44,41 @@
   DisplayError error = kErrorNone;
 
   error = res_mgr_.Init(hw_res_info);
-  if (UNLIKELY(error != kErrorNone)) {
+  if (error != kErrorNone) {
     return error;
   }
 
   // Try to load strategy library & get handle to its interface.
   // Default to GPU only composition on failure.
   strategy_lib_ = ::dlopen(STRATEGY_LIBRARY_NAME, RTLD_NOW);
-  if (UNLIKELY(!strategy_lib_)) {
-    DLOGW("Unable to load = %s", STRATEGY_LIBRARY_NAME);
-  } else {
-    GetStrategyInterface get_strategy_intf = NULL;
-    void **sym = reinterpret_cast<void **>(&get_strategy_intf);
-    *sym = ::dlsym(strategy_lib_, GET_STRATEGY_INTERFACE_NAME);
-    if (UNLIKELY(!get_strategy_intf)) {
-      DLOGW("Unable to find symbol for %s", GET_STRATEGY_INTERFACE_NAME);
-    } else if (UNLIKELY(get_strategy_intf(&strategy_intf_) != kErrorNone)) {
-      DLOGW("Unable to get handle to strategy interface");
-    }
-  }
+  if (strategy_lib_) {
+    void **create_sym = reinterpret_cast<void **>(&create_strategy_intf_);
+    void **destroy_sym = reinterpret_cast<void **>(&destroy_strategy_intf_);
 
-  if (UNLIKELY(!strategy_intf_)) {
-    DLOGI("Using GPU only composition");
-    if (strategy_lib_) {
+    *create_sym = ::dlsym(strategy_lib_, CREATE_STRATEGY_INTERFACE_NAME);
+    *destroy_sym = ::dlsym(strategy_lib_, DESTROY_STRATEGY_INTERFACE_NAME);
+
+    if (!create_strategy_intf_) {
+      DLOGE("Unable to find symbol for %s", CREATE_STRATEGY_INTERFACE_NAME);
+      error = kErrorUndefined;
+    }
+
+    if (!destroy_strategy_intf_) {
+      DLOGE("Unable to find symbol for %s", DESTROY_STRATEGY_INTERFACE_NAME);
+      error = kErrorUndefined;
+    }
+
+    if (error != kErrorNone) {
       ::dlclose(strategy_lib_);
-      strategy_lib_ = NULL;
+      res_mgr_.Deinit();
     }
-    strategy_intf_ = &strategy_default_;
+  } else {
+    DLOGW("Unable to load = %s, using GPU only (default) composition", STRATEGY_LIBRARY_NAME);
+    create_strategy_intf_ = StrategyDefault::CreateStrategyInterface;
+    destroy_strategy_intf_ = StrategyDefault::DestroyStrategyInterface;
   }
 
-  return kErrorNone;
+  return error;
 }
 
 DisplayError CompManager::Deinit() {
@@ -82,6 +87,7 @@
   if (strategy_lib_) {
     ::dlclose(strategy_lib_);
   }
+
   res_mgr_.Deinit();
 
   return kErrorNone;
@@ -98,11 +104,20 @@
     return kErrorMemory;
   }
 
+  if (create_strategy_intf_(STRATEGY_VERSION_TAG, type,
+                            &display_comp_ctx->strategy_intf) != kErrorNone) {
+    DLOGW("Unable to create strategy interface");
+    delete display_comp_ctx;
+    return kErrorUndefined;
+  }
+
   error = res_mgr_.RegisterDisplay(type, attributes, &display_comp_ctx->display_resource_ctx);
   if (error != kErrorNone) {
+    destroy_strategy_intf_(display_comp_ctx->strategy_intf);
     delete display_comp_ctx;
     return error;
   }
+
   SET_BIT(registered_displays_, type);
   display_comp_ctx->display_type = type;
   *display_ctx = display_comp_ctx;
@@ -120,8 +135,11 @@
                              reinterpret_cast<DisplayCompositionContext *>(comp_handle);
 
   res_mgr_.UnregisterDisplay(display_comp_ctx->display_resource_ctx);
+  destroy_strategy_intf_(display_comp_ctx->strategy_intf);
+
   CLEAR_BIT(registered_displays_, display_comp_ctx->display_type);
   CLEAR_BIT(configured_displays_, display_comp_ctx->display_type);
+
   delete display_comp_ctx;
 
   return kErrorNone;
@@ -133,12 +151,25 @@
   StrategyConstraints *constraints = &display_comp_ctx->constraints;
 
   constraints->safe_mode = safe_mode_;
-  // If validation for the best available composition strategy with driver has failed, just
-  // fallback to GPU composition.
-  if (UNLIKELY(hw_layers->info.flags)) {
-    constraints->safe_mode = true;
-    return;
+
+  // Limit 2 layer SDE Comp on HDMI
+  if (display_comp_ctx->display_type == kHDMI) {
+    constraints->max_layers = 2;
   }
+
+  // If a strategy fails after successfully allocating resources, then set safe mode
+  if (display_comp_ctx->remaining_strategies != display_comp_ctx->max_strategies) {
+    constraints->safe_mode = true;
+  }
+}
+
+void CompManager::PrePrepare(Handle display_ctx, HWLayers *hw_layers) {
+  SCOPE_LOCK(locker_);
+  DisplayCompositionContext *display_comp_ctx =
+                             reinterpret_cast<DisplayCompositionContext *>(display_ctx);
+  display_comp_ctx->strategy_intf->Start(&hw_layers->info,
+                                         &display_comp_ctx->max_strategies);
+  display_comp_ctx->remaining_strategies = display_comp_ctx->max_strategies;
 }
 
 DisplayError CompManager::Prepare(Handle display_ctx, HWLayers *hw_layers) {
@@ -148,37 +179,44 @@
                              reinterpret_cast<DisplayCompositionContext *>(display_ctx);
   Handle &display_resource_ctx = display_comp_ctx->display_resource_ctx;
 
-  DisplayError error = kErrorNone;
+  DisplayError error = kErrorUndefined;
 
   PrepareStrategyConstraints(display_ctx, hw_layers);
 
   // Select a composition strategy, and try to allocate resources for it.
   res_mgr_.Start(display_resource_ctx);
-  while (true) {
-    error = strategy_intf_->GetNextStrategy(&display_comp_ctx->constraints, &hw_layers->info);
-    if (UNLIKELY(error != kErrorNone)) {
+
+  bool exit = false;
+  uint32_t &count = display_comp_ctx->remaining_strategies;
+  for (; !exit && count > 0; count--) {
+    error = display_comp_ctx->strategy_intf->GetNextStrategy(&display_comp_ctx->constraints);
+    if (error != kErrorNone) {
       // Composition strategies exhausted. Resource Manager could not allocate resources even for
       // GPU composition. This will never happen.
-      DLOGE("Unexpected failure. Composition strategies exhausted.");
-      return error;
+      exit = true;
     }
 
-    error = res_mgr_.Acquire(display_resource_ctx, hw_layers);
-    if (error != kErrorNone) {
-      // Not enough resources, try next strategy.
-      continue;
-    } else {
-      // Successfully selected and configured a composition strategy.
-      break;
+    if (!exit) {
+      error = res_mgr_.Acquire(display_resource_ctx, hw_layers);
+      // Exit if successfully allocated resource, else try next strategy.
+      exit = (error == kErrorNone);
     }
   }
+
+  if (error != kErrorNone) {
+    DLOGE("Composition strategies exhausted for display = %d", display_comp_ctx->display_type);
+  }
+
   res_mgr_.Stop(display_resource_ctx);
 
-  return kErrorNone;
+  return error;
 }
 
 void CompManager::PostPrepare(Handle display_ctx, HWLayers *hw_layers) {
   SCOPE_LOCK(locker_);
+  DisplayCompositionContext *display_comp_ctx =
+                             reinterpret_cast<DisplayCompositionContext *>(display_ctx);
+  display_comp_ctx->strategy_intf->Stop();
 }
 
 void CompManager::PostCommit(Handle display_ctx, HWLayers *hw_layers) {
diff --git a/displayengine/libs/core/comp_manager.h b/displayengine/libs/core/comp_manager.h
index 492500a..aed357b 100644
--- a/displayengine/libs/core/comp_manager.h
+++ b/displayengine/libs/core/comp_manager.h
@@ -28,7 +28,6 @@
 #include <core/display_interface.h>
 
 #include "hw_interface.h"
-#include "strategy_default.h"
 #include "res_manager.h"
 #include "dump_impl.h"
 
@@ -42,6 +41,7 @@
   DisplayError RegisterDisplay(DisplayType type, const HWDisplayAttributes &attributes,
                                Handle *res_mgr_hnd);
   DisplayError UnregisterDisplay(Handle res_mgr_hnd);
+  void PrePrepare(Handle display_ctx, HWLayers *hw_layers);
   DisplayError Prepare(Handle display_ctx, HWLayers *hw_layers);
   void PostPrepare(Handle display_ctx, HWLayers *hw_layers);
   void PostCommit(Handle display_ctx, HWLayers *hw_layers);
@@ -52,16 +52,20 @@
 
  private:
   void PrepareStrategyConstraints(Handle display_ctx, HWLayers *hw_layers);
+
   struct DisplayCompositionContext {
+    StrategyInterface *strategy_intf;
     StrategyConstraints constraints;
     Handle display_resource_ctx;
     DisplayType display_type;
+    uint32_t max_strategies;
+    uint32_t remaining_strategies;
   };
 
   Locker locker_;
   void *strategy_lib_;
-  StrategyInterface *strategy_intf_;
-  StrategyDefault strategy_default_;
+  CreateStrategyInterface create_strategy_intf_;
+  DestroyStrategyInterface destroy_strategy_intf_;
   ResManager res_mgr_;
   uint64_t registered_displays_;        // Stores the bit mask of registered displays
   uint64_t configured_displays_;        // Stores the bit mask of sucessfully configured displays
diff --git a/displayengine/libs/core/core_impl.cpp b/displayengine/libs/core/core_impl.cpp
old mode 100644
new mode 100755
index a3dfde1..0669f9f
--- a/displayengine/libs/core/core_impl.cpp
+++ b/displayengine/libs/core/core_impl.cpp
@@ -22,19 +22,17 @@
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
-// SDE_LOG_TAG definition must precede debug.h include.
-#define SDE_LOG_TAG kTagCore
-#define SDE_MODULE_NAME "CoreImpl"
-#include <utils/debug.h>
-
 #include <utils/locker.h>
 #include <utils/constants.h>
+#include <utils/debug.h>
 
 #include "core_impl.h"
 #include "display_primary.h"
 #include "display_hdmi.h"
 #include "display_virtual.h"
 
+#define __CLASS__ "CoreImpl"
+
 namespace sde {
 
 CoreImpl::CoreImpl(CoreEventHandler *event_handler)
diff --git a/displayengine/libs/core/core_interface.cpp b/displayengine/libs/core/core_interface.cpp
old mode 100644
new mode 100755
index 7cd85b0..fb8700a
--- a/displayengine/libs/core/core_interface.cpp
+++ b/displayengine/libs/core/core_interface.cpp
@@ -22,16 +22,14 @@
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
-// SDE_LOG_TAG definition must precede debug.h include.
-#define SDE_LOG_TAG kTagCore
-#define SDE_MODULE_NAME "CoreInterface"
-#include <utils/debug.h>
-
 #include <utils/locker.h>
 #include <utils/constants.h>
+#include <utils/debug.h>
 
 #include "core_impl.h"
 
+#define __CLASS__ "CoreInterface"
+
 #define GET_REVISION(version) (version >> 16)
 #define GET_DATA_ALIGNMENT(version) ((version >> 8) & 0xFF)
 #define GET_INSTRUCTION_SET(version) (version & 0xFF)
@@ -47,19 +45,17 @@
   Locker locker;
 } g_core;
 
-DisplayError CoreInterface::CreateCore(CoreEventHandler *event_handler, CoreInterface **interface,
-                                 uint32_t client_version) {
+DisplayError CoreInterface::CreateCore(CoreEventHandler *event_handler, LogHandler *log_handler,
+                                       CoreInterface **interface, uint32_t client_version) {
   SCOPE_LOCK(g_core.locker);
 
-  if (UNLIKELY(!event_handler || !interface)) {
+  if (UNLIKELY(!event_handler || !log_handler || !interface)) {
     return kErrorParameters;
   }
 
   // Check compatibility of client and core.
-  uint32_t lib_version = CORE_VERSION_TAG;
-  if (UNLIKELY(!interface)) {
-    return kErrorParameters;
-  } else if (UNLIKELY(GET_REVISION(client_version) > GET_REVISION(lib_version))) {
+  uint32_t lib_version = SDE_VERSION_TAG;
+  if (UNLIKELY(GET_REVISION(client_version) > GET_REVISION(lib_version))) {
     return kErrorVersion;
   } else if (UNLIKELY(GET_DATA_ALIGNMENT(client_version) != GET_DATA_ALIGNMENT(lib_version))) {
     return kErrorDataAlignment;
@@ -69,10 +65,11 @@
 
   CoreImpl *&core_impl = g_core.core_impl;
   if (UNLIKELY(core_impl)) {
-    DLOGE("Only one display core session is supported at present.");
     return kErrorUndefined;
   }
 
+  Debug::SetLogHandler(log_handler);
+
   // Create appropriate CoreImpl object based on client version.
   if (GET_REVISION(client_version) == CoreImpl::kRevision) {
     core_impl = new CoreImpl(event_handler);
@@ -84,11 +81,11 @@
     return kErrorMemory;
   }
 
-  DisplayError displayError = core_impl->Init();
-  if (UNLIKELY(displayError != kErrorNone)) {
+  DisplayError error = core_impl->Init();
+  if (UNLIKELY(error != kErrorNone)) {
     delete core_impl;
     core_impl = NULL;
-    return displayError;
+    return error;
   }
 
   *interface = core_impl;
diff --git a/displayengine/libs/core/display_base.cpp b/displayengine/libs/core/display_base.cpp
index 5b2d0af..080deb7 100644
--- a/displayengine/libs/core/display_base.cpp
+++ b/displayengine/libs/core/display_base.cpp
@@ -22,20 +22,18 @@
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
-// SDE_LOG_TAG definition must precede debug.h include.
-#define SDE_LOG_TAG kTagCore
-#define SDE_MODULE_NAME "DisplayBase"
+#include <utils/constants.h>
 #include <utils/debug.h>
 
-#include <utils/constants.h>
-
 #include "display_base.h"
 
+#define __CLASS__ "DisplayBase"
+
 namespace sde {
 
 DisplayBase::DisplayBase(DisplayType display_type, DisplayEventHandler *event_handler,
-                       HWBlockType hw_block_type, HWInterface *hw_intf, CompManager *comp_manager)
-  : display_type_(display_type), event_handler_(event_handler), hw_block_type_(hw_block_type),
+             HWDeviceType hw_device_type, HWInterface *hw_intf, CompManager *comp_manager)
+  : display_type_(display_type), event_handler_(event_handler), hw_device_type_(hw_device_type),
     hw_intf_(hw_intf), comp_manager_(comp_manager), state_(kStateOff), hw_device_(0),
     display_comp_ctx_(0), display_attributes_(NULL), num_modes_(0), active_mode_index_(0),
     pending_commit_(false), vsync_enable_(false) {
@@ -46,13 +44,13 @@
 
   DisplayError error = kErrorNone;
 
-  error = hw_intf_->Open(hw_block_type_, &hw_device_, this);
-  if (UNLIKELY(error != kErrorNone)) {
+  error = hw_intf_->Open(hw_device_type_, &hw_device_, this);
+  if (error != kErrorNone) {
     return error;
   }
 
   error = hw_intf_->GetNumDisplayAttributes(hw_device_, &num_modes_);
-  if (UNLIKELY(error != kErrorNone)) {
+  if (error != kErrorNone) {
     goto CleanupOnError;
   }
 
@@ -64,16 +62,21 @@
 
   for (uint32_t i = 0; i < num_modes_; i++) {
     error = hw_intf_->GetDisplayAttributes(hw_device_, &display_attributes_[i], i);
-    if (UNLIKELY(error != kErrorNone)) {
+    if (error != kErrorNone) {
       goto CleanupOnError;
     }
   }
 
-  active_mode_index_ = 0;
+  active_mode_index_ = GetBestConfig();
+
+  error = hw_intf_->SetDisplayAttributes(hw_device_, active_mode_index_);
+  if (error != kErrorNone) {
+    goto CleanupOnError;
+  }
 
   error = comp_manager_->RegisterDisplay(display_type_, display_attributes_[active_mode_index_],
                                         &display_comp_ctx_);
-  if (UNLIKELY(error != kErrorNone)) {
+  if (error != kErrorNone) {
     goto CleanupOnError;
   }
 
@@ -106,31 +109,32 @@
 
   DisplayError error = kErrorNone;
 
-  if (UNLIKELY(!layer_stack)) {
+  if (!layer_stack) {
     return kErrorParameters;
   }
 
   pending_commit_ = false;
 
-  if (LIKELY(state_ == kStateOn)) {
+  if ((state_ == kStateOn)) {
     // Clean hw layers for reuse.
-    hw_layers_.info.Reset();
+    hw_layers_.info = HWLayersInfo();
     hw_layers_.info.stack = layer_stack;
 
+    comp_manager_->PrePrepare(display_comp_ctx_, &hw_layers_);
     while (true) {
       error = comp_manager_->Prepare(display_comp_ctx_, &hw_layers_);
-      if (UNLIKELY(error != kErrorNone)) {
+      if (error != kErrorNone) {
         break;
       }
 
       error = hw_intf_->Validate(hw_device_, &hw_layers_);
-      if (LIKELY(error == kErrorNone)) {
+      if (error == kErrorNone) {
         // Strategy is successful now, wait for Commit().
-        comp_manager_->PostPrepare(display_comp_ctx_, &hw_layers_);
         pending_commit_ = true;
         break;
       }
     }
+    comp_manager_->PostPrepare(display_comp_ctx_, &hw_layers_);
   }
 
   return error;
@@ -141,18 +145,18 @@
 
   DisplayError error = kErrorNone;
 
-  if (UNLIKELY(!layer_stack)) {
+  if (!layer_stack) {
     return kErrorParameters;
   }
 
-  if (UNLIKELY(!pending_commit_)) {
-    DLOGE("Commit: Corresponding Prepare() is not called.");
+  if (!pending_commit_) {
+    DLOGE("Commit: Corresponding Prepare() is not called for display = %d", display_type_);
     return kErrorUndefined;
   }
 
-  if (LIKELY(state_ == kStateOn)) {
+  if (state_ == kStateOn) {
     error = hw_intf_->Commit(hw_device_, &hw_layers_);
-    if (LIKELY(error == kErrorNone)) {
+    if (error == kErrorNone) {
       comp_manager_->PostCommit(display_comp_ctx_, &hw_layers_);
     } else {
       DLOGE("Unexpected error. Commit failed on driver.");
@@ -167,7 +171,7 @@
 DisplayError DisplayBase::GetDisplayState(DisplayState *state) {
   SCOPE_LOCK(locker_);
 
-  if (UNLIKELY(!state)) {
+  if (!state) {
     return kErrorParameters;
   }
 
@@ -178,7 +182,7 @@
 DisplayError DisplayBase::GetNumVariableInfoConfigs(uint32_t *count) {
   SCOPE_LOCK(locker_);
 
-  if (UNLIKELY(!count)) {
+  if (!count) {
     return kErrorParameters;
   }
 
@@ -190,21 +194,33 @@
 DisplayError DisplayBase::GetConfig(DisplayConfigFixedInfo *fixed_info) {
   SCOPE_LOCK(locker_);
 
-  if (UNLIKELY(!fixed_info)) {
+  if (!fixed_info) {
     return kErrorParameters;
   }
 
   return kErrorNone;
 }
 
-DisplayError DisplayBase::GetConfig(DisplayConfigVariableInfo *variable_info, uint32_t mode) {
+DisplayError DisplayBase::GetConfig(uint32_t index, DisplayConfigVariableInfo *variable_info) {
   SCOPE_LOCK(locker_);
 
-  if (UNLIKELY(!variable_info || mode >= num_modes_)) {
+  if (!variable_info || index >= num_modes_) {
     return kErrorParameters;
   }
 
-  *variable_info = display_attributes_[mode];
+  *variable_info = display_attributes_[index];
+
+  return kErrorNone;
+}
+
+DisplayError DisplayBase::GetActiveConfig(uint32_t *index) {
+  SCOPE_LOCK(locker_);
+
+  if (!index) {
+    return kErrorParameters;
+  }
+
+  *index = active_mode_index_;
 
   return kErrorNone;
 }
@@ -212,7 +228,7 @@
 DisplayError DisplayBase::GetVSyncState(bool *enabled) {
   SCOPE_LOCK(locker_);
 
-  if (UNLIKELY(!enabled)) {
+  if (!enabled) {
     return kErrorParameters;
   }
 
@@ -224,15 +240,16 @@
 
   DisplayError error = kErrorNone;
 
-  DLOGI("Set state: %d", state);
+  DLOGI("Set state = %d", state);
 
-  if (UNLIKELY(state == state_)) {
+  if (state == state_) {
     DLOGI("Same state transition is requested.");
     return kErrorNone;
   }
 
   switch (state) {
   case kStateOff:
+    hw_layers_.info.count = 0;
     comp_manager_->Purge(display_comp_ctx_);
     error = hw_intf_->PowerOff(hw_device_);
     break;
@@ -250,21 +267,31 @@
     break;
 
   default:
-    DLOGE("Spurious state %d transition requested.", state);
+    DLOGE("Spurious state = %d transition requested.", state);
     break;
   }
 
-  if (UNLIKELY(error == kErrorNone)) {
+  if (error == kErrorNone) {
     state_ = state;
   }
 
   return error;
 }
 
-DisplayError DisplayBase::SetConfig(uint32_t mode) {
+DisplayError DisplayBase::SetActiveConfig(uint32_t index) {
   SCOPE_LOCK(locker_);
+  DisplayError error = kErrorNone;
 
-  return kErrorNone;
+  if (index >= num_modes_) {
+    return kErrorParameters;
+  }
+
+  error = hw_intf_->SetDisplayAttributes(hw_device_, index);
+  if (error != kErrorNone) {
+    active_mode_index_ = index;
+  }
+
+  return error;
 }
 
 DisplayError DisplayBase::SetVSyncState(bool enable) {
@@ -318,7 +345,7 @@
                                 num_layers, num_hw_layers);
 
   for (uint32_t i = 0; i < num_hw_layers; i++) {
-    Layer &layer = hw_layers_.info.stack->layers[i];
+    Layer &layer = hw_layers_.info.stack->layers[hw_layers_.info.index[i]];
     LayerBuffer *input_buffer = layer.input_buffer;
     HWLayerConfig &layer_config = hw_layers_.config[i];
     HWPipeInfo &left_pipe = hw_layers_.config[i].left_pipe;
@@ -350,5 +377,9 @@
                                 rect_name, rect->left, rect->top, rect->right, rect->bottom);
 }
 
+int DisplayBase::GetBestConfig() {
+  return (num_modes_ == 1) ? 0 : -1;
+}
+
 }  // namespace sde
 
diff --git a/displayengine/libs/core/display_base.h b/displayengine/libs/core/display_base.h
index 5eaac37..3f0e24f 100644
--- a/displayengine/libs/core/display_base.h
+++ b/displayengine/libs/core/display_base.h
@@ -37,7 +37,7 @@
 class DisplayBase : public DisplayInterface, HWEventHandler, DumpImpl {
  public:
   DisplayBase(DisplayType display_type, DisplayEventHandler *event_handler,
-             HWBlockType hw_block_type, HWInterface *hw_intf, CompManager *comp_manager);
+              HWDeviceType hw_device_type, HWInterface *hw_intf, CompManager *comp_manager);
   virtual ~DisplayBase() { }
   virtual DisplayError Init();
   virtual DisplayError Deinit();
@@ -46,10 +46,11 @@
   virtual DisplayError GetDisplayState(DisplayState *state);
   virtual DisplayError GetNumVariableInfoConfigs(uint32_t *count);
   virtual DisplayError GetConfig(DisplayConfigFixedInfo *fixed_info);
-  virtual DisplayError GetConfig(DisplayConfigVariableInfo *variable_info, uint32_t mode);
+  virtual DisplayError GetConfig(uint32_t index, DisplayConfigVariableInfo *variable_info);
+  virtual DisplayError GetActiveConfig(uint32_t *index);
   virtual DisplayError GetVSyncState(bool *enabled);
   virtual DisplayError SetDisplayState(DisplayState state);
-  virtual DisplayError SetConfig(uint32_t mode);
+  virtual DisplayError SetActiveConfig(uint32_t index);
   virtual DisplayError SetVSyncState(bool enable);
 
   // Implement the HWEventHandlers
@@ -61,10 +62,12 @@
   void AppendRect(char *buffer, uint32_t length, const char *rect_name, LayerRect *rect);
 
  protected:
+  virtual int GetBestConfig();
+
   Locker locker_;
   DisplayType display_type_;
   DisplayEventHandler *event_handler_;
-  HWBlockType hw_block_type_;
+  HWDeviceType hw_device_type_;
   HWInterface *hw_intf_;
   CompManager *comp_manager_;
   DisplayState state_;
diff --git a/displayengine/libs/core/display_hdmi.cpp b/displayengine/libs/core/display_hdmi.cpp
index b44bc87..14a09f1 100644
--- a/displayengine/libs/core/display_hdmi.cpp
+++ b/displayengine/libs/core/display_hdmi.cpp
@@ -22,20 +22,59 @@
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
-// SDE_LOG_TAG definition must precede debug.h include.
-#define SDE_LOG_TAG kTagCore
-#define SDE_MODULE_NAME "DisplayHDMI"
+#include <utils/constants.h>
 #include <utils/debug.h>
 
-#include <utils/constants.h>
-
 #include "display_hdmi.h"
 
+#define __CLASS__ "DisplayHDMI"
+
 namespace sde {
 
 DisplayHDMI::DisplayHDMI(DisplayEventHandler *event_handler, HWInterface *hw_intf,
                          CompManager *comp_manager)
-  : DisplayBase(kHDMI, event_handler, kHWHDMI, hw_intf, comp_manager) {
+  : DisplayBase(kHDMI, event_handler, kDeviceHDMI, hw_intf, comp_manager) {
+}
+
+int DisplayHDMI::GetBestConfig() {
+  uint32_t best_config_mode = 0;
+  HWDisplayAttributes *best = &display_attributes_[0];
+  if (num_modes_ == 1) {
+    return best_config_mode;
+  }
+
+  // From the available configs, select the best
+  // Ex: 1920x1080@60Hz is better than 1920x1080@30 and 1920x1080@30 is better than 1280x720@60
+  for (uint32_t index = 1; index < num_modes_; index++) {
+    HWDisplayAttributes *current = &display_attributes_[index];
+    // compare the two modes: in the order of Resolution followed by refreshrate
+    if (current->y_pixels > best->y_pixels) {
+      best_config_mode = index;
+    } else if (current->y_pixels == best->y_pixels) {
+      if (current->x_pixels > best->x_pixels) {
+        best_config_mode = index;
+      } else if (current->x_pixels == best->x_pixels) {
+        if (current->vsync_period_ns < best->vsync_period_ns) {
+          best_config_mode = index;
+        }
+      }
+    }
+    if (best_config_mode == index) {
+      best = &display_attributes_[index];
+    }
+  }
+
+  // Used for changing HDMI Resolution - override the best with user set config
+  uint32_t user_config = Debug::GetHDMIResolution();
+  if (user_config) {
+    uint32_t config_index = -1;
+    // For the config, get the corresponding index
+    DisplayError error = hw_intf_->GetConfigIndex(hw_device_, user_config, &config_index);
+    if (error == kErrorNone)
+      return config_index;
+  }
+
+  return best_config_mode;
 }
 
 }  // namespace sde
diff --git a/displayengine/libs/core/display_hdmi.h b/displayengine/libs/core/display_hdmi.h
index 85f53fc..0bb9dc8 100644
--- a/displayengine/libs/core/display_hdmi.h
+++ b/displayengine/libs/core/display_hdmi.h
@@ -32,6 +32,7 @@
 class DisplayHDMI : public DisplayBase {
  public:
   DisplayHDMI(DisplayEventHandler *event_handler, HWInterface *hw_intf, CompManager *comp_manager);
+  virtual int GetBestConfig();
 };
 
 }  // namespace sde
diff --git a/displayengine/libs/core/display_primary.cpp b/displayengine/libs/core/display_primary.cpp
old mode 100644
new mode 100755
index 96ff08a..e4bd031
--- a/displayengine/libs/core/display_primary.cpp
+++ b/displayengine/libs/core/display_primary.cpp
@@ -22,20 +22,18 @@
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
-// SDE_LOG_TAG definition must precede debug.h include.
-#define SDE_LOG_TAG kTagCore
-#define SDE_MODULE_NAME "DisplayPrimary"
+#include <utils/constants.h>
 #include <utils/debug.h>
 
-#include <utils/constants.h>
-
 #include "display_primary.h"
 
+#define __CLASS__ "DisplayPrimary"
+
 namespace sde {
 
 DisplayPrimary::DisplayPrimary(DisplayEventHandler *event_handler, HWInterface *hw_intf,
                                CompManager *comp_manager)
-  : DisplayBase(kPrimary, event_handler, kHWPrimary, hw_intf, comp_manager) {
+  : DisplayBase(kPrimary, event_handler, kDevicePrimary, hw_intf, comp_manager) {
 }
 
 }  // namespace sde
diff --git a/displayengine/libs/core/display_virtual.cpp b/displayengine/libs/core/display_virtual.cpp
old mode 100644
new mode 100755
index dc18146..2fef178
--- a/displayengine/libs/core/display_virtual.cpp
+++ b/displayengine/libs/core/display_virtual.cpp
@@ -22,20 +22,18 @@
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
-// SDE_LOG_TAG definition must precede debug.h include.
-#define SDE_LOG_TAG kTagCore
-#define SDE_MODULE_NAME "DisplayVirtual"
+#include <utils/constants.h>
 #include <utils/debug.h>
 
-#include <utils/constants.h>
-
 #include "display_virtual.h"
 
+#define __CLASS__ "DisplayVirtual"
+
 namespace sde {
 
 DisplayVirtual::DisplayVirtual(DisplayEventHandler *event_handler, HWInterface *hw_intf,
                                CompManager *comp_manager)
-  : DisplayBase(kVirtual, event_handler, kHWBlockMax, hw_intf, comp_manager) {
+  : DisplayBase(kVirtual, event_handler, kDeviceVirtual, hw_intf, comp_manager) {
 }
 
 }  // namespace sde
diff --git a/displayengine/libs/core/dump_impl.cpp b/displayengine/libs/core/dump_impl.cpp
old mode 100644
new mode 100755
index b000ea7..a5aca81
--- a/displayengine/libs/core/dump_impl.cpp
+++ b/displayengine/libs/core/dump_impl.cpp
@@ -22,11 +22,6 @@
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
-// SDE_LOG_TAG definition must precede debug.h include.
-#define SDE_LOG_TAG kTagCore
-#define SDE_MODULE_NAME "DumpInterface"
-#include <utils/debug.h>
-
 #include <stdarg.h>
 #include <stdio.h>
 #include <string.h>
diff --git a/displayengine/libs/core/hw_framebuffer.cpp b/displayengine/libs/core/hw_framebuffer.cpp
index 63adf8c..0644e7d 100644
--- a/displayengine/libs/core/hw_framebuffer.cpp
+++ b/displayengine/libs/core/hw_framebuffer.cpp
@@ -22,12 +22,8 @@
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
-// SDE_LOG_TAG definition must precede debug.h include.
-#define SDE_LOG_TAG kTagCore
-#define SDE_MODULE_NAME "HWFrameBuffer"
 #define __STDC_FORMAT_MACROS
-#include <utils/debug.h>
-
+#include <ctype.h>
 #include <math.h>
 #include <fcntl.h>
 #include <inttypes.h>
@@ -39,10 +35,14 @@
 #include <sys/prctl.h>
 #include <pthread.h>
 #include <utils/constants.h>
+#include <utils/debug.h>
 
 #include "hw_framebuffer.h"
 
-#define IOCTL_LOGE(ioctl) DLOGE("ioctl %s, errno = %d, desc = %s", #ioctl, errno, strerror(errno))
+#define __CLASS__ "HWFrameBuffer"
+
+#define IOCTL_LOGE(ioctl, type) DLOGE("ioctl %s, display = %d errno = %d, desc = %s", #ioctl, \
+                                      type, errno, strerror(errno))
 
 #ifdef DISPLAY_CORE_VIRTUAL_DRIVER
 extern int virtual_ioctl(int fd, int cmd, ...);
@@ -53,14 +53,16 @@
 extern FILE* virtual_fopen(const char *fname, const char *mode);
 extern int virtual_fclose(FILE* fileptr);
 extern ssize_t virtual_getline(char **lineptr, size_t *linelen, FILE *stream);
-
+extern ssize_t virtual_read(int fd, void *buf, size_t count);
+extern ssize_t virtual_write(int fd, const void *buf, size_t count);
 
 #endif
 
 namespace sde {
 
 HWFrameBuffer::HWFrameBuffer() : event_thread_name_("SDE_EventThread"), fake_vsync_(false),
-                                 exit_threads_(false), fb_path_("/sys/class/graphics/fb") {
+                                 exit_threads_(false), fb_path_("/sys/devices/virtual/graphics/fb"),
+                                 hotplug_enabled_(false) {
   // Pointer to actual driver interfaces.
   ioctl_ = ::ioctl;
   open_ = ::open;
@@ -70,6 +72,8 @@
   fopen_ = ::fopen;
   fclose_ = ::fclose;
   getline_ = ::getline;
+  read_ = ::read;
+  write_ = ::write;
 
 #ifdef DISPLAY_CORE_VIRTUAL_DRIVER
   // If debug property to use virtual driver is set, point to virtual driver interfaces.
@@ -82,9 +86,11 @@
     fopen_ = virtual_fopen;
     fclose_ = virtual_fclose;
     getline_ = virtual_getline;
+    read_ = virtual_read;
+    write_ = virtual_write;
   }
 #endif
-  for (int i = 0; i < kHWBlockMax; i ++) {
+  for (int i = 0; i < kDeviceMax; i++) {
     fb_node_index_[i] = -1;
   }
 }
@@ -140,6 +146,16 @@
     }
   }
 
+  // Mode look-up table for HDMI
+  supported_video_modes_ = new msm_hdmi_mode_timing_info[HDMI_VFRMT_MAX];
+  if (!supported_video_modes_) {
+    error = kErrorMemory;
+    goto CleanupOnError;
+  }
+  // Populate the mode table for supported modes
+  MSM_HDMI_MODES_INIT_TIMINGS(supported_video_modes_);
+  MSM_HDMI_MODES_SET_SUPP_TIMINGS(supported_video_modes_, MSM_HDMI_MODES_ALL);
+
   // Start the Event thread
   if (pthread_create(&event_thread_, NULL, &DisplayEventThread, this) < 0) {
     DLOGE("Failed to start %s, error = %s", event_thread_name_);
@@ -159,6 +175,9 @@
       }
     }
   }
+  if (supported_video_modes_) {
+    delete supported_video_modes_;
+  }
 
   return error;
 }
@@ -172,6 +191,9 @@
       close(poll_fds_[display][event].fd);
     }
   }
+  if (supported_video_modes_) {
+    delete supported_video_modes_;
+  }
 
   return kErrorNone;
 }
@@ -182,46 +204,58 @@
   return kErrorNone;
 }
 
-DisplayError HWFrameBuffer::Open(HWBlockType type, Handle *device, HWEventHandler* eventhandler) {
+DisplayError HWFrameBuffer::Open(HWDeviceType type, Handle *device, HWEventHandler* eventhandler) {
   DisplayError error = kErrorNone;
 
   HWContext *hw_context = new HWContext();
-  if (UNLIKELY(!hw_context)) {
+  if (!hw_context) {
     return kErrorMemory;
   }
 
-  int device_id = 0;
+  char device_name[64] = {0};
+
   switch (type) {
-  case kHWPrimary:
-    device_id = 0;
+  case kDevicePrimary:
+  case kDeviceHDMI:
+    // Store EventHandlers for two Physical displays, i.e., Primary and HDMI
+    // TODO(user): Need to revisit for HDMI as Primary usecase
+    event_handler_[type] = eventhandler;
+  case kDeviceVirtual:
+    snprintf(device_name, sizeof(device_name), "%s%d", "/dev/graphics/fb", fb_node_index_[type]);
     break;
   default:
     break;
   }
 
-  char device_name[64] = {0};
-  snprintf(device_name, sizeof(device_name), "%s%d", "/dev/graphics/fb", device_id);
-
   hw_context->device_fd = open_(device_name, O_RDWR);
-  if (UNLIKELY(hw_context->device_fd < 0)) {
+  if (hw_context->device_fd < 0) {
     DLOGE("open %s failed.", device_name);
     error = kErrorResources;
     delete hw_context;
   }
+  hw_context->type = type;
 
   *device = hw_context;
 
-  // Store EventHandlers for two Physical displays
-  if (device_id < kNumPhysicalDisplays)
-    event_handler_[device_id] = eventhandler;
-
   return error;
 }
 
 DisplayError HWFrameBuffer::Close(Handle device) {
   HWContext *hw_context = reinterpret_cast<HWContext *>(device);
 
-  close_(hw_context->device_fd);
+  switch (hw_context->type) {
+  case kDevicePrimary:
+    break;
+  case kDeviceHDMI:
+    hdmi_mode_count_ = 0;
+    break;
+  default:
+    break;
+  }
+
+  if (hw_context->device_fd > 0) {
+    close_(hw_context->device_fd);
+  }
   delete hw_context;
 
   return kErrorNone;
@@ -230,72 +264,233 @@
 DisplayError HWFrameBuffer::GetNumDisplayAttributes(Handle device, uint32_t *count) {
   HWContext *hw_context = reinterpret_cast<HWContext *>(device);
 
-  // TODO(user): Query modes
-  *count = 1;
+  switch (hw_context->type) {
+  case kDevicePrimary:
+    *count = 1;
+    break;
+  case kDeviceHDMI:
+    *count = GetHDMIModeCount();
+    if (*count <= 0) {
+      return kErrorHardware;
+    }
+    break;
+  default:
+    return kErrorParameters;
+  }
 
   return kErrorNone;
 }
 
 DisplayError HWFrameBuffer::GetDisplayAttributes(Handle device,
                                                  HWDisplayAttributes *display_attributes,
-                                                 uint32_t mode) {
+                                                 uint32_t index) {
   HWContext *hw_context = reinterpret_cast<HWContext *>(device);
   int &device_fd = hw_context->device_fd;
-
-  // TODO(user): Query for respective mode index.
-
   // Variable screen info
   STRUCT_VAR(fb_var_screeninfo, var_screeninfo);
-  if (UNLIKELY(ioctl_(device_fd, FBIOGET_VSCREENINFO, &var_screeninfo) == -1)) {
-    IOCTL_LOGE(FBIOGET_VSCREENINFO);
-    return kErrorHardware;
+
+  switch (hw_context->type) {
+  case kDevicePrimary:
+    {
+      if (ioctl_(device_fd, FBIOGET_VSCREENINFO, &var_screeninfo) == -1) {
+        IOCTL_LOGE(FBIOGET_VSCREENINFO, hw_context->type);
+        return kErrorHardware;
+      }
+
+      // Frame rate
+      STRUCT_VAR(msmfb_metadata, meta_data);
+      meta_data.op = metadata_op_frame_rate;
+      if (ioctl_(device_fd, MSMFB_METADATA_GET, &meta_data) == -1) {
+        IOCTL_LOGE(MSMFB_METADATA_GET, hw_context->type);
+        return kErrorHardware;
+      }
+
+      // If driver doesn't return width/height information, default to 160 dpi
+      if (INT(var_screeninfo.width) <= 0 || INT(var_screeninfo.height) <= 0) {
+        var_screeninfo.width  = INT(((FLOAT(var_screeninfo.xres) * 25.4f)/160.0f) + 0.5f);
+        var_screeninfo.height = INT(((FLOAT(var_screeninfo.yres) * 25.4f)/160.0f) + 0.5f);
+      }
+
+      display_attributes->x_pixels = var_screeninfo.xres;
+      display_attributes->y_pixels = var_screeninfo.yres;
+      display_attributes->v_total = var_screeninfo.yres + var_screeninfo.lower_margin +
+          var_screeninfo.upper_margin + var_screeninfo.vsync_len;
+      display_attributes->x_dpi =
+          (FLOAT(var_screeninfo.xres) * 25.4f) / FLOAT(var_screeninfo.width);
+      display_attributes->y_dpi =
+          (FLOAT(var_screeninfo.yres) * 25.4f) / FLOAT(var_screeninfo.height);
+      display_attributes->fps = FLOAT(meta_data.data.panel_frame_rate);
+      display_attributes->vsync_period_ns = UINT32(1000000000L / display_attributes->fps);
+      display_attributes->is_device_split = (hw_resource_.split_info.left_split ||
+          (var_screeninfo.xres > hw_resource_.max_mixer_width)) ? true : false;
+      display_attributes->split_left = hw_resource_.split_info.left_split ?
+          hw_resource_.split_info.left_split : display_attributes->x_pixels / 2;
+    }
+    break;
+
+  case kDeviceHDMI:
+    {
+      // Get the resolution info from the look up table
+      msm_hdmi_mode_timing_info *timing_mode = &supported_video_modes_[0];
+      for (int i = 0; i < HDMI_VFRMT_MAX; i++) {
+        msm_hdmi_mode_timing_info *cur = &supported_video_modes_[i];
+        if (cur->video_format == hdmi_modes_[index]) {
+          timing_mode = cur;
+          break;
+        }
+      }
+      display_attributes->x_pixels = timing_mode->active_h;
+      display_attributes->y_pixels = timing_mode->active_v;
+      display_attributes->v_total = timing_mode->active_v + timing_mode->front_porch_v +
+          timing_mode->back_porch_v + timing_mode->pulse_width_v;
+      display_attributes->x_dpi = 0;
+      display_attributes->y_dpi = 0;
+      display_attributes->fps = FLOAT(timing_mode->refresh_rate) / 1000.0f;
+      display_attributes->vsync_period_ns = UINT32(1000000000L / display_attributes->fps);
+      display_attributes->split_left = display_attributes->x_pixels;
+      if (display_attributes->x_pixels > hw_resource_.max_mixer_width) {
+        display_attributes->is_device_split = true;
+        display_attributes->split_left = display_attributes->x_pixels / 2;
+      }
+    }
+    break;
+
+  default:
+    return kErrorParameters;
   }
 
-  // Frame rate
-  STRUCT_VAR(msmfb_metadata, meta_data);
-  meta_data.op = metadata_op_frame_rate;
-  if (UNLIKELY(ioctl_(device_fd, MSMFB_METADATA_GET, &meta_data) == -1)) {
-    IOCTL_LOGE(MSMFB_METADATA_GET);
-    return kErrorHardware;
-  }
-
-  // If driver doesn't return width/height information, default to 160 dpi
-  if (INT(var_screeninfo.width) <= 0 || INT(var_screeninfo.height) <= 0) {
-    var_screeninfo.width  = INT((FLOAT(var_screeninfo.xres) * 25.4f)/160.0f + 0.5f);
-    var_screeninfo.height = INT((FLOAT(var_screeninfo.yres) * 25.4f)/160.0f + 0.5f);
-  }
-
-  display_attributes->x_pixels = var_screeninfo.xres;
-  display_attributes->y_pixels = var_screeninfo.yres;
-  display_attributes->x_dpi = (FLOAT(var_screeninfo.xres) * 25.4f) / FLOAT(var_screeninfo.width);
-  display_attributes->y_dpi = (FLOAT(var_screeninfo.yres) * 25.4f) / FLOAT(var_screeninfo.height);
-  display_attributes->vsync_period_ns =
-                 UINT32(1000000000L / FLOAT(meta_data.data.panel_frame_rate));
-
-  // TODO(user): set panel information from sysfs
-  display_attributes->is_device_split = true;
-  display_attributes->split_left = display_attributes->x_pixels / 2;
-
   return kErrorNone;
 }
 
+DisplayError HWFrameBuffer::SetDisplayAttributes(Handle device, uint32_t index) {
+  HWContext *hw_context = reinterpret_cast<HWContext *>(device);
+  DisplayError error = kErrorNone;
+
+  switch (hw_context->type) {
+  case kDevicePrimary:
+    break;
+
+  case kDeviceHDMI:
+    {
+      // Variable screen info
+      STRUCT_VAR(fb_var_screeninfo, vscreeninfo);
+      if (ioctl_(hw_context->device_fd, FBIOGET_VSCREENINFO, &vscreeninfo) == -1) {
+        IOCTL_LOGE(FBIOGET_VSCREENINFO, hw_context->type);
+        return kErrorHardware;
+      }
+
+      DLOGI("GetInfo<Mode=%d %dx%d (%d,%d,%d),(%d,%d,%d) %dMHz>", vscreeninfo.reserved[3],
+            vscreeninfo.xres, vscreeninfo.yres, vscreeninfo.right_margin, vscreeninfo.hsync_len,
+            vscreeninfo.left_margin, vscreeninfo.lower_margin, vscreeninfo.vsync_len,
+            vscreeninfo.upper_margin, vscreeninfo.pixclock/1000000);
+
+      msm_hdmi_mode_timing_info *timing_mode = &supported_video_modes_[0];
+      for (int i = 0; i < HDMI_VFRMT_MAX; i++) {
+        msm_hdmi_mode_timing_info *cur = &supported_video_modes_[i];
+        if (cur->video_format == hdmi_modes_[index]) {
+          timing_mode = cur;
+          break;
+        }
+      }
+      if (MapHDMIDisplayTiming(timing_mode, &vscreeninfo) == false) {
+        return kErrorParameters;
+      }
+      STRUCT_VAR(msmfb_metadata, metadata);
+      memset(&metadata, 0 , sizeof(metadata));
+      metadata.op = metadata_op_vic;
+      metadata.data.video_info_code = timing_mode->video_format;
+      if (ioctl(hw_context->device_fd, MSMFB_METADATA_SET, &metadata) == -1) {
+        IOCTL_LOGE(MSMFB_METADATA_SET, hw_context->type);
+        return kErrorHardware;
+      }
+      DLOGI("SetInfo<Mode=%d %dx%d (%d,%d,%d),(%d,%d,%d) %dMHz>", vscreeninfo.reserved[3] & 0xFF00,
+            vscreeninfo.xres, vscreeninfo.yres, vscreeninfo.right_margin, vscreeninfo.hsync_len,
+            vscreeninfo.left_margin, vscreeninfo.lower_margin, vscreeninfo.vsync_len,
+            vscreeninfo.upper_margin, vscreeninfo.pixclock/1000000);
+
+      vscreeninfo.activate = FB_ACTIVATE_NOW | FB_ACTIVATE_ALL | FB_ACTIVATE_FORCE;
+      if (ioctl_(hw_context->device_fd, FBIOPUT_VSCREENINFO, &vscreeninfo) == -1) {
+        IOCTL_LOGE(FBIOGET_VSCREENINFO, hw_context->type);
+        return kErrorHardware;
+      }
+    }
+    break;
+
+  default:
+    return kErrorParameters;
+  }
+
+  return error;
+}
+
+DisplayError HWFrameBuffer::GetConfigIndex(Handle device, uint32_t mode, uint32_t *index) {
+  HWContext *hw_context = reinterpret_cast<HWContext *>(device);
+
+  switch (hw_context->type) {
+  case kDevicePrimary:
+  case kDeviceVirtual:
+    return kErrorNone;
+    break;
+  case kDeviceHDMI:
+    // Check if the mode is valid and return corresponding index
+    for (uint32_t i = 0; i < hdmi_mode_count_; i++) {
+      if (hdmi_modes_[i] == mode) {
+        *index = i;
+        DLOGI("Index = %d for config = %d", *index, mode);
+        return kErrorNone;
+      }
+    }
+    break;
+  default:
+    return kErrorParameters;
+  }
+
+  DLOGE("Config = %d not supported", mode);
+  return kErrorNotSupported;
+}
+
+
 DisplayError HWFrameBuffer::PowerOn(Handle device) {
   HWContext *hw_context = reinterpret_cast<HWContext *>(device);
 
-  if (UNLIKELY(ioctl_(hw_context->device_fd, FBIOBLANK, FB_BLANK_UNBLANK) == -1)) {
-    IOCTL_LOGE(FB_BLANK_UNBLANK);
+  if (ioctl_(hw_context->device_fd, FBIOBLANK, FB_BLANK_UNBLANK) == -1) {
+    IOCTL_LOGE(FB_BLANK_UNBLANK, hw_context->type);
     return kErrorHardware;
   }
 
+  // Need to turn on HPD
+  if (!hotplug_enabled_) {
+    hotplug_enabled_ = EnableHotPlugDetection(1);
+  }
+
   return kErrorNone;
 }
 
 DisplayError HWFrameBuffer::PowerOff(Handle device) {
   HWContext *hw_context = reinterpret_cast<HWContext *>(device);
 
-  if (UNLIKELY(ioctl_(hw_context->device_fd, FBIOBLANK, FB_BLANK_POWERDOWN) == -1)) {
-    IOCTL_LOGE(FB_BLANK_POWERDOWN);
-    return kErrorHardware;
+  switch (hw_context->type) {
+  case kDevicePrimary:
+    if (ioctl_(hw_context->device_fd, FBIOBLANK, FB_BLANK_POWERDOWN) == -1) {
+      IOCTL_LOGE(FB_BLANK_POWERDOWN, hw_context->type);
+      return kErrorHardware;
+    }
+    break;
+  case kDeviceHDMI:
+    {
+      hw_context->ResetMDPCommit();
+      mdp_layer_commit_v1 &mdp_commit = hw_context->mdp_commit.commit_v1;
+      mdp_commit.input_layer_cnt = 0;
+      mdp_commit.flags &= ~MDP_VALIDATE_LAYER;
+      if (ioctl_(hw_context->device_fd, MSMFB_ATOMIC_COMMIT, &hw_context->mdp_commit) == -1) {
+        IOCTL_LOGE(MSMFB_ATOMIC_COMMIT, hw_context->type);
+        return kErrorHardware;
+      }
+    }
+    break;
+  case kDeviceVirtual:
+  default:
+    break;
   }
 
   return kErrorNone;
@@ -317,7 +512,7 @@
   HWContext *hw_context = reinterpret_cast<HWContext *>(device);
   int vsync_on = enable ? 1 : 0;
   if (ioctl_(hw_context->device_fd, MSMFB_OVERLAY_VSYNC_CTRL, &vsync_on) == -1) {
-    IOCTL_LOGE(MSMFB_OVERLAY_VSYNC_CTRL);
+    IOCTL_LOGE(MSMFB_OVERLAY_VSYNC_CTRL, hw_context->type);
     return kErrorHardware;
   }
 
@@ -325,140 +520,152 @@
 }
 
 DisplayError HWFrameBuffer::Validate(Handle device, HWLayers *hw_layers) {
+  DisplayError error = kErrorNone;
   HWContext *hw_context = reinterpret_cast<HWContext *>(device);
 
+  hw_context->ResetMDPCommit();
+
+  HWLayersInfo &hw_layer_info = hw_layers->info;
+  LayerStack *stack = hw_layer_info.stack;
+
+  mdp_layer_commit_v1 &mdp_commit = hw_context->mdp_commit.commit_v1;
+  mdp_input_layer *mdp_layers = hw_context->mdp_layers;
+  uint32_t &mdp_layer_count = mdp_commit.input_layer_cnt;
+
+  for (uint32_t i = 0; i < hw_layer_info.count; i++) {
+    uint32_t layer_index = hw_layer_info.index[i];
+    Layer &layer = stack->layers[layer_index];
+    LayerBuffer *input_buffer = layer.input_buffer;
+    HWLayerConfig &config = hw_layers->config[i];
+
+    uint32_t split_count = hw_layers->config[i].is_right_pipe ? 2 : 1;
+    for (uint32_t j = 0; j < split_count; j++) {
+      HWPipeInfo &pipe = (j == 0) ? config.left_pipe : config.right_pipe;
+      mdp_input_layer &mdp_layer = mdp_layers[mdp_layer_count];
+      mdp_layer.alpha = layer.plane_alpha;
+      mdp_layer.z_order = static_cast<uint16_t>(i);
+      mdp_layer.transp_mask = 0xffffffff;
+      SetBlending(layer.blending, &mdp_layer.blend_op);
+      SetRect(pipe.src_roi, &mdp_layer.src_rect);
+      SetRect(pipe.dst_roi, &mdp_layer.dst_rect);
+
+      mdp_layer.pipe_ndx = pipe.pipe_id;
+
+      mdp_layer_buffer &mdp_buffer_left = mdp_layer.buffer;
+      mdp_buffer_left.width = input_buffer->width;
+      mdp_buffer_left.height = input_buffer->height;
+
+      error = SetFormat(layer.input_buffer->format, &mdp_buffer_left.format);
+      if (error != kErrorNone) {
+        return error;
+      }
+
+      if (layer.transform.flip_vertical) {
+        mdp_layer.flags |= MDP_LAYER_FLIP_UD;
+      }
+
+      if (layer.transform.flip_horizontal) {
+        mdp_layer.flags |= MDP_LAYER_FLIP_LR;
+      }
+
+      mdp_layer_count++;
+    }
+  }
+
+  mdp_commit.flags |= MDP_VALIDATE_LAYER;
+  if (ioctl_(hw_context->device_fd, MSMFB_ATOMIC_COMMIT, &hw_context->mdp_commit) == -1) {
+    IOCTL_LOGE(MSMFB_ATOMIC_COMMIT, hw_context->type);
+    return kErrorHardware;
+  }
+
   return kErrorNone;
 }
 
 DisplayError HWFrameBuffer::Commit(Handle device, HWLayers *hw_layers) {
   HWContext *hw_context = reinterpret_cast<HWContext *>(device);
-
   HWLayersInfo &hw_layer_info = hw_layers->info;
-
-  // Assuming left & right both pipe are required, maximum possible number of overlays.
-  uint32_t max_overlay_count = hw_layer_info.count * 2;
-
-  int acquire_fences[hw_layer_info.count];  // NOLINT
-  int release_fence = -1;
-  int retire_fence = -1;
-  uint32_t acquire_fence_count = 0;
-  STRUCT_VAR_ARRAY(mdp_overlay, overlay_array, max_overlay_count);
-  STRUCT_VAR_ARRAY(msmfb_overlay_data, data_array, max_overlay_count);
-
   LayerStack *stack = hw_layer_info.stack;
-  uint32_t num_overlays = 0;
+
+  mdp_layer_commit_v1 &mdp_commit = hw_context->mdp_commit.commit_v1;
+  mdp_input_layer *mdp_layers = hw_context->mdp_layers;
+  uint32_t mdp_layer_index = 0;
+
   for (uint32_t i = 0; i < hw_layer_info.count; i++) {
     uint32_t layer_index = hw_layer_info.index[i];
-    Layer &layer = stack->layers[layer_index];
-    LayerBuffer *input_buffer = layer.input_buffer;
-    HWLayerConfig &config = hw_layers->config[i];
-    HWPipeInfo &left_pipe = config.left_pipe;
+    LayerBuffer *input_buffer = stack->layers[layer_index].input_buffer;
 
-    // Configure left pipe
-    mdp_overlay &left_overlay = overlay_array[num_overlays];
-    msmfb_overlay_data &left_data = data_array[num_overlays];
+    uint32_t split_count = hw_layers->config[i].is_right_pipe ? 2 : 1;
+    for (uint32_t j = 0; j < split_count; j++) {
+      mdp_layer_buffer &mdp_buffer = mdp_layers[mdp_layer_index].buffer;
 
-    left_overlay.id = left_pipe.pipe_id;
-    left_overlay.flags |= MDP_BLEND_FG_PREMULT;
-    left_overlay.transp_mask = 0xffffffff;
-    left_overlay.z_order = i;
-    left_overlay.alpha = layer.plane_alpha;
-    left_overlay.src.width = input_buffer->planes[0].stride;
-    left_overlay.src.height = input_buffer->height;
-    SetBlending(&left_overlay.blend_op, layer.blending);
-    SetFormat(&left_overlay.src.format, layer.input_buffer->format);
-    SetRect(&left_overlay.src_rect, left_pipe.src_roi);
-    SetRect(&left_overlay.dst_rect, left_pipe.dst_roi);
-    left_data.id = left_pipe.pipe_id;
-    left_data.data.memory_id = input_buffer->planes[0].fd;
-    left_data.data.offset = input_buffer->planes[0].offset;
+      if (input_buffer->planes[0].fd >= 0) {
+        mdp_buffer.plane_count = 1;
+        mdp_buffer.planes[0].fd = input_buffer->planes[0].fd;
+        mdp_buffer.planes[0].offset = input_buffer->planes[0].offset;
+        mdp_buffer.planes[0].stride = input_buffer->planes[0].stride;
+      } else {
+        DLOGW("Invalid buffer fd, setting plane count to 0");
+        mdp_buffer.plane_count = 0;
+      }
 
-    num_overlays++;
-
-    // Configure right pipe
-    if (config.is_right_pipe) {
-      HWPipeInfo &right_pipe = config.right_pipe;
-      mdp_overlay &right_overlay = overlay_array[num_overlays];
-      msmfb_overlay_data &right_data = data_array[num_overlays];
-
-      right_overlay = left_overlay;
-      right_data = left_data;
-      right_overlay.id = right_pipe.pipe_id;
-      right_data.id = right_pipe.pipe_id;
-      SetRect(&right_overlay.src_rect, right_pipe.src_roi);
-      SetRect(&right_overlay.dst_rect, right_pipe.dst_roi);
-
-      num_overlays++;
-    }
-
-    if (input_buffer->acquire_fence_fd >= 0) {
-      acquire_fences[acquire_fence_count] = input_buffer->acquire_fence_fd;
-      acquire_fence_count++;
+      mdp_buffer.fence = input_buffer->acquire_fence_fd;
+      mdp_layer_index++;
     }
   }
 
-  mdp_overlay *overlay_list[num_overlays];
-  msmfb_overlay_data *data_list[num_overlays];
-  for (uint32_t i = 0; i < num_overlays; i++) {
-    overlay_list[i] = &overlay_array[i];
-    data_list[i] = &data_array[i];
-  }
-
-  // TODO(user): Replace with Atomic commit call.
-  STRUCT_VAR(mdp_atomic_commit, atomic_commit);
-  atomic_commit.overlay_list = overlay_list;
-  atomic_commit.data_list = data_list;
-  atomic_commit.num_overlays = num_overlays;
-  atomic_commit.buf_sync.acq_fen_fd = acquire_fences;
-  atomic_commit.buf_sync.acq_fen_fd_cnt = acquire_fence_count;
-  atomic_commit.buf_sync.rel_fen_fd = &release_fence;
-  atomic_commit.buf_sync.retire_fen_fd = &retire_fence;
-  atomic_commit.buf_sync.flags = MDP_BUF_SYNC_FLAG_RETIRE_FENCE;
-
-  if (UNLIKELY(ioctl_(hw_context->device_fd, MSMFB_ATOMIC_COMMIT, &atomic_commit) == -1)) {
-    IOCTL_LOGE(MSMFB_ATOMIC_COMMIT);
+  mdp_commit.flags |= MDP_COMMIT_RETIRE_FENCE;
+  mdp_commit.flags &= ~MDP_VALIDATE_LAYER;
+  if (ioctl_(hw_context->device_fd, MSMFB_ATOMIC_COMMIT, &hw_context->mdp_commit) == -1) {
+    IOCTL_LOGE(MSMFB_ATOMIC_COMMIT, hw_context->type);
     return kErrorHardware;
   }
 
   // MDP returns only one release fence for the entire layer stack. Duplicate this fence into all
   // layers being composed by MDP.
-  stack->retire_fence_fd = retire_fence;
+  stack->retire_fence_fd = mdp_commit.retire_fence;
   for (uint32_t i = 0; i < hw_layer_info.count; i++) {
     uint32_t layer_index = hw_layer_info.index[i];
-    Layer &layer = stack->layers[layer_index];
-    LayerBuffer *input_buffer = layer.input_buffer;
-    input_buffer->release_fence_fd = dup(release_fence);
+    LayerBuffer *input_buffer = stack->layers[layer_index].input_buffer;
+
+    input_buffer->release_fence_fd = dup(mdp_commit.release_fence);
   }
-  close(release_fence);
+  close(mdp_commit.release_fence);
 
   return kErrorNone;
 }
 
-void HWFrameBuffer::SetFormat(uint32_t *target, const LayerBufferFormat &source) {
+DisplayError HWFrameBuffer::SetFormat(const LayerBufferFormat &source, uint32_t *target) {
   switch (source) {
+  case kFormatARGB8888:                 *target = MDP_ARGB_8888;         break;
+  case kFormatRGBA8888:                 *target = MDP_RGBA_8888;         break;
+  case kFormatBGRA8888:                 *target = MDP_BGRA_8888;         break;
+  case kFormatRGBX8888:                 *target = MDP_RGBX_8888;         break;
+  case kFormatBGRX8888:                 *target = MDP_BGRX_8888;         break;
+  case kFormatRGB888:                   *target = MDP_RGB_888;           break;
+  case kFormatRGB565:                   *target = MDP_RGB_565;           break;
+  case kFormatYCbCr420Planar:           *target = MDP_Y_CB_CR_H2V2;      break;
+  case kFormatYCrCb420Planar:           *target = MDP_Y_CR_CB_H2V2;      break;
+  case kFormatYCbCr420SemiPlanar:       *target = MDP_Y_CBCR_H2V2;       break;
+  case kFormatYCrCb420SemiPlanar:       *target = MDP_Y_CRCB_H2V2;       break;
+  case kFormatYCbCr422Packed:           *target = MDP_YCBYCR_H2V1;       break;
+  case kFormatYCbCr420SemiPlanarVenus:  *target = MDP_Y_CBCR_H2V2_VENUS; break;
   default:
-    *target = MDP_RGBA_8888;
-    break;
+    DLOGE("Unsupported format type %d", source);
+    return kErrorParameters;
+  }
+
+  return kErrorNone;
+}
+
+void HWFrameBuffer::SetBlending(const LayerBlending &source, mdss_mdp_blend_op *target) {
+  switch (source) {
+  case kBlendingPremultiplied:  *target = BLEND_OP_PREMULTIPLIED;   break;
+  case kBlendingCoverage:       *target = BLEND_OP_COVERAGE;        break;
+  default:                      *target = BLEND_OP_NOT_DEFINED;     break;
   }
 }
 
-void HWFrameBuffer::SetBlending(uint32_t *target, const LayerBlending &source) {
-  switch (source) {
-  case kBlendingPremultiplied:
-    *target = BLEND_OP_PREMULTIPLIED;
-    break;
-
-  case kBlendingCoverage:
-    *target = BLEND_OP_COVERAGE;
-    break;
-
-  default:
-    *target = BLEND_OP_NOT_DEFINED;
-    break;
-  }
-}
-
-void HWFrameBuffer::SetRect(mdp_rect *target, const LayerRect &source) {
+void HWFrameBuffer::SetRect(const LayerRect &source, mdp_rect *target) {
   target->x = INT(ceilf(source.left));
   target->y = INT(ceilf(source.top));
   target->w = INT(floorf(source.right)) - target->x;
@@ -492,20 +699,20 @@
       uint64_t ts = uint64_t(time_now.tv_sec)*1000000000LL +uint64_t(time_now.tv_usec)*1000LL;
 
       // Send Vsync event for primary display(0)
-      event_handler_[0]->VSync(ts);
+      event_handler_[kDevicePrimary]->VSync(ts);
     }
 
     pthread_exit(0);
   }
 
-  typedef void (HWFrameBuffer::*EventHandler)(int, char*);
+  typedef void (HWFrameBuffer::*EventHandler)(int, char *);
   EventHandler event_handler[kNumDisplayEvents] = { &HWFrameBuffer::HandleVSync,
                                                     &HWFrameBuffer::HandleBlank };
 
   while (!exit_threads_) {
     int error = poll_(poll_fds_[0], kNumPhysicalDisplays * kNumDisplayEvents, -1);
     if (error < 0) {
-      DLOGE("poll failed errno: %s", strerror(errno));
+      DLOGW("poll failed. error = %s", strerror(errno));
       continue;
     }
 
@@ -517,7 +724,8 @@
           ssize_t length = pread_(poll_fd.fd, data, kMaxStringLength, 0);
           if (length < 0) {
             // If the read was interrupted - it is not a fatal error, just continue.
-            DLOGE("Failed to read event:%d for display=%d: %s", event, display, strerror(errno));
+            DLOGW("pread failed. event = %d, display = %d, error = %s",
+                                                      event, display, strerror(errno));
             continue;
           }
 
@@ -538,29 +746,25 @@
     timestamp = strtoull(data + strlen("VSYNC="), NULL, 0);
   }
   event_handler_[display_id]->VSync(timestamp);
-
-  return;
 }
 
-void HWFrameBuffer::HandleBlank(int display_id, char* data) {
+void HWFrameBuffer::HandleBlank(int display_id, char *data) {
   // TODO(user): Need to send blank Event
-  return;
 }
 
 void HWFrameBuffer::PopulateFBNodeIndex() {
   char stringbuffer[kMaxStringLength];
   DisplayError error = kErrorNone;
-  HWBlockType hwblock = kHWPrimary;
   char *line = stringbuffer;
   size_t len = kMaxStringLength;
   ssize_t read;
 
 
-  for (int i = 0; i < kHWBlockMax; i++) {
+  for (int i = 0; i < kDeviceMax; i++) {
     snprintf(stringbuffer, sizeof(stringbuffer), "%s%d/msm_fb_type", fb_path_, i);
     FILE* fileptr = fopen_(stringbuffer, "r");
     if (fileptr == NULL) {
-      DLOGE("File not found %s", stringbuffer);
+      DLOGW("File not found %s", stringbuffer);
       continue;
     }
     read = getline_(&line, &len, fileptr);
@@ -572,24 +776,23 @@
     // Need more concrete info from driver
     if ((strncmp(line, "mipi dsi cmd panel", strlen("mipi dsi cmd panel")) == 0)) {
       pri_panel_info_.type = kCommandModePanel;
-      hwblock = kHWPrimary;
+      fb_node_index_[kDevicePrimary] = i;
     } else if ((strncmp(line, "mipi dsi video panel", strlen("mipi dsi video panel")) == 0))  {
       pri_panel_info_.type = kVideoModePanel;
-      hwblock = kHWPrimary;
+      fb_node_index_[kDevicePrimary] = i;
     } else if ((strncmp(line, "lvds panel", strlen("lvds panel")) == 0)) {
       pri_panel_info_.type = kLVDSPanel;
-      hwblock = kHWPrimary;
+      fb_node_index_[kDevicePrimary] = i;
     } else if ((strncmp(line, "edp panel", strlen("edp panel")) == 0)) {
       pri_panel_info_.type = kEDPPanel;
-      hwblock = kHWPrimary;
+      fb_node_index_[kDevicePrimary] = i;
     } else if ((strncmp(line, "dtv panel", strlen("dtv panel")) == 0)) {
-      hwblock = kHWHDMI;
+      fb_node_index_[kDeviceHDMI] = i;
     } else if ((strncmp(line, "writeback panel", strlen("writeback panel")) == 0)) {
-      hwblock = kHWWriteback0;
+      fb_node_index_[kDeviceVirtual] = i;
     } else {
-      DLOGE("Unknown panel type = %s index = %d", line, i);
+      DLOGW("Unknown panel type = %s index = %d", line, i);
     }
-    fb_node_index_[hwblock] = i;
     fclose_(fileptr);
   }
 }
@@ -600,7 +803,7 @@
   snprintf(stringbuffer, sizeof(stringbuffer), "%s%d/msm_fb_panel_info", fb_path_, fb_index);
   fileptr = fopen_(stringbuffer, "r");
   if (fileptr == NULL) {
-    DLOGE("Failed to open msm_fb_panel_info node");
+    DLOGW("Failed to open msm_fb_panel_info node");
     return;
   }
 
@@ -608,8 +811,8 @@
   ssize_t read;
   char *line = stringbuffer;
   while ((read = getline_(&line, &len, fileptr)) != -1) {
-    int token_count = 0;
-    const int max_count = 10;
+    uint32_t token_count = 0;
+    const uint32_t max_count = 10;
     char *tokens[max_count] = { NULL };
     if (!ParseLine(line, tokens, max_count, &token_count)) {
       if (!strncmp(tokens[0], "pu_en", strlen("pu_en"))) {
@@ -645,8 +848,8 @@
   DisplayError error = kErrorNone;
   FILE *fileptr = NULL;
   char stringbuffer[kMaxStringLength];
-  int token_count = 0;
-  const int max_count = 10;
+  uint32_t token_count = 0;
+  const uint32_t max_count = 10;
   char *tokens[max_count] = { NULL };
   snprintf(stringbuffer , sizeof(stringbuffer), "%s%d/mdp/caps", fb_path_,
            fb_node_index_[kHWPrimary]);
@@ -686,8 +889,14 @@
         hw_resource_.max_bandwidth_high = atol(tokens[1]);
       } else if (!strncmp(tokens[0], "max_mixer_width", strlen("max_mixer_width"))) {
         hw_resource_.max_mixer_width = atoi(tokens[1]);
+      } else if (!strncmp(tokens[0], "max_pipe_bw", strlen("max_pipe_bw"))) {
+        hw_resource_.max_pipe_bw = atoi(tokens[1]);
+      } else if (!strncmp(tokens[0], "max_mdp_clk", strlen("max_mdp_clk"))) {
+        hw_resource_.max_sde_clk = atoi(tokens[1]);
+      } else if (!strncmp(tokens[0], "clk_fudge_factor", strlen("clk_fudge_factor"))) {
+        hw_resource_.clk_fudge_factor = FLOAT(atoi(tokens[1])) / FLOAT(atoi(tokens[2]));
       } else if (!strncmp(tokens[0], "features", strlen("features"))) {
-        for (int i = 0; i < token_count; i++) {
+        for (uint32_t i = 0; i < token_count; i++) {
           if (!strncmp(tokens[i], "bwc", strlen("bwc"))) {
             hw_resource_.has_bwc = true;
           } else if (!strncmp(tokens[i], "decimation", strlen("decimation"))) {
@@ -739,27 +948,30 @@
     }
   }
 
-  DLOGI("SDE Version: %d SDE Revision: %x RGB : %d, VIG: %d DMA: %d Cursor: %d",
+  DLOGI("SDE Version = %d, SDE Revision = %x, RGB = %d, VIG = %d, DMA = %d, Cursor = %d",
         hw_resource_.hw_version, hw_resource_.hw_revision, hw_resource_.num_rgb_pipe,
         hw_resource_.num_vig_pipe, hw_resource_.num_dma_pipe, hw_resource_.num_cursor_pipe);
-  DLOGI("Upscale Ratio: %d Downscale Ratio: %d Blending Stages: %d", hw_resource_.max_scale_up,
+  DLOGI("Upscale Ratio = %d, Downscale Ratio = %d, Blending Stages = %d", hw_resource_.max_scale_up,
         hw_resource_.max_scale_down, hw_resource_.num_blending_stages);
-  DLOGI("BWC: %d Decimation: %d Tile Format: %d: Rotator Downscale: %d",  hw_resource_.has_bwc,
+  DLOGI("BWC = %d, Decimation = %d, Tile Format = %d, Rotator Downscale = %d", hw_resource_.has_bwc,
         hw_resource_.has_decimation, hw_resource_.has_macrotile,
         hw_resource_.has_rotator_downscale);
-  DLOGI("Left Split: %d Right Split: %d", hw_resource_.split_info.left_split,
+  DLOGI("Left Split = %d, Right Split = %d", hw_resource_.split_info.left_split,
         hw_resource_.split_info.right_split);
-  DLOGI("SourceSplit: %d Always: %d", hw_resource_.is_src_split, hw_resource_.always_src_split);
-  DLOGI("MaxLowBw: %"PRIu64" MaxHighBw: %"PRIu64"", hw_resource_.max_bandwidth_low,
+  DLOGI("SourceSplit = %d, Always = %d", hw_resource_.is_src_split, hw_resource_.always_src_split);
+  DLOGI("MaxLowBw = %"PRIu64", MaxHighBw = %"PRIu64"", hw_resource_.max_bandwidth_low,
         hw_resource_.max_bandwidth_high);
+  DLOGI("MaxPipeBw = %"PRIu64" KBps, MaxSDEClock = %"PRIu64" Hz, ClockFudgeFactor = %f",
+        hw_resource_.max_pipe_bw, hw_resource_.max_sde_clk, hw_resource_.clk_fudge_factor);
 
   return error;
 }
 
-int HWFrameBuffer::ParseLine(char *input, char *tokens[], int max_token, int *count) {
+int HWFrameBuffer::ParseLine(char *input, char *tokens[], const uint32_t max_token,
+                             uint32_t *count) {
   char *tmp_token = NULL;
   char *temp_ptr;
-  int index = 0;
+  uint32_t index = 0;
   const char *delim = ", =\n";
   if (!input) {
     return -1;
@@ -774,4 +986,87 @@
   return 0;
 }
 
+bool HWFrameBuffer::EnableHotPlugDetection(int enable) {
+  bool ret_value = true;
+  char hpdpath[kMaxStringLength];
+  snprintf(hpdpath , sizeof(hpdpath), "%s%d/hpd", fb_path_, fb_node_index_[kDeviceHDMI]);
+  int hpdfd = open_(hpdpath, O_RDWR, 0);
+  if (hpdfd < 0) {
+    DLOGE("Open failed = %s", hpdpath);
+    return kErrorHardware;
+  }
+  char value = enable ? '1' : '0';
+  ssize_t length = write_(hpdfd, &value, 1);
+  if (length <= 0) {
+    DLOGE("Write failed 'hpd' = %d", enable);
+    ret_value = false;
+  }
+  close_(hpdfd);
+
+  return ret_value;
+}
+
+int HWFrameBuffer::GetHDMIModeCount() {
+  ssize_t length = -1;
+  char edid_str[256] = {'\0'};
+  char edid_path[kMaxStringLength] = {'\0'};
+  snprintf(edid_path, sizeof(edid_path), "%s%d/edid_modes", fb_path_, fb_node_index_[kHWHDMI]);
+  int edid_file = open_(edid_path, O_RDONLY);
+  if (edid_file < 0) {
+    DLOGE("EDID file open failed.");
+    return -1;
+  }
+
+  length = read_(edid_file, edid_str, sizeof(edid_str)-1);
+  if (length <= 0) {
+    DLOGE("%s: edid_modes file empty");
+    edid_str[0] = '\0';
+  } else {
+    DLOGI("EDID mode string: %s", edid_str);
+    while (length > 1 && isspace(edid_str[length-1])) {
+      --length;
+    }
+    edid_str[length] = '\0';
+  }
+  close_(edid_file);
+
+  if (length > 0) {
+    // Get EDID modes from the EDID string
+    char *ptr = edid_str;
+    const uint32_t edid_count_max = 128;
+    char *tokens[edid_count_max] = { NULL };
+    ParseLine(ptr, tokens, edid_count_max, &hdmi_mode_count_);
+    for (uint32_t i = 0; i < hdmi_mode_count_; i++) {
+      hdmi_modes_[i] = atoi(tokens[i]);
+    }
+  }
+  return (hdmi_mode_count_ > 0) ? hdmi_mode_count_ : 0;
+}
+
+bool HWFrameBuffer::MapHDMIDisplayTiming(const msm_hdmi_mode_timing_info *mode,
+                                         fb_var_screeninfo *info) {
+  if (!mode || !info) {
+    return false;
+  }
+
+  info->reserved[0] = 0;
+  info->reserved[1] = 0;
+  info->reserved[2] = 0;
+  info->reserved[3] = (info->reserved[3] & 0xFFFF) | (mode->video_format << 16);
+  info->xoffset = 0;
+  info->yoffset = 0;
+  info->xres = mode->active_h;
+  info->yres = mode->active_v;
+  info->pixclock = (mode->pixel_freq) * 1000;
+  info->vmode = mode->interlaced ? FB_VMODE_INTERLACED : FB_VMODE_NONINTERLACED;
+  info->right_margin = mode->front_porch_h;
+  info->hsync_len = mode->pulse_width_h;
+  info->left_margin = mode->back_porch_h;
+  info->lower_margin = mode->front_porch_v;
+  info->vsync_len = mode->pulse_width_v;
+  info->upper_margin = mode->back_porch_v;
+
+  return true;
+}
+
 }  // namespace sde
diff --git a/displayengine/libs/core/hw_framebuffer.h b/displayengine/libs/core/hw_framebuffer.h
index d74d03e..2fe5078 100644
--- a/displayengine/libs/core/hw_framebuffer.h
+++ b/displayengine/libs/core/hw_framebuffer.h
@@ -25,9 +25,12 @@
 #ifndef __HW_FRAMEBUFFER_H__
 #define __HW_FRAMEBUFFER_H__
 
+#include <errno.h>
 #include <stdio.h>
 #include <stdlib.h>
-#include <linux/msm_mdp.h>
+#include <linux/msm_mdp_ext.h>
+#include <video/msm_hdmi_modes.h>
+
 #include <poll.h>
 #include <pthread.h>
 
@@ -41,11 +44,13 @@
   DisplayError Init();
   DisplayError Deinit();
   virtual DisplayError GetHWCapabilities(HWResourceInfo *hw_res_info);
-  virtual DisplayError Open(HWBlockType type, Handle *device, HWEventHandler *eventhandler);
+  virtual DisplayError Open(HWDeviceType type, Handle *device, HWEventHandler *eventhandler);
   virtual DisplayError Close(Handle device);
   virtual DisplayError GetNumDisplayAttributes(Handle device, uint32_t *count);
   virtual DisplayError GetDisplayAttributes(Handle device, HWDisplayAttributes *display_attributes,
-                                            uint32_t mode);
+                                            uint32_t index);
+  virtual DisplayError SetDisplayAttributes(Handle device, uint32_t index);
+  virtual DisplayError GetConfigIndex(Handle device, uint32_t mode, uint32_t *index);
   virtual DisplayError PowerOn(Handle device);
   virtual DisplayError PowerOff(Handle device);
   virtual DisplayError Doze(Handle device);
@@ -56,8 +61,21 @@
 
  private:
   struct HWContext {
-    HWBlockType type;
+    HWDeviceType type;
     int device_fd;
+    mdp_layer_commit mdp_commit;
+    mdp_input_layer mdp_layers[kMaxSDELayers * 2];   // split panel (left + right) for worst case
+
+    HWContext() : type(kDeviceMax), device_fd(-1) {
+      ResetMDPCommit();
+    }
+
+    void ResetMDPCommit() {
+      memset(&mdp_commit, 0, sizeof(mdp_commit));
+      memset(&mdp_layers, 0, sizeof(mdp_layers));
+      mdp_commit.version = MDP_COMMIT_VERSION_1_0;
+      mdp_commit.commit_v1.input_layers = mdp_layers;
+    }
   };
 
   enum PanelType {
@@ -100,9 +118,9 @@
   static const int kNumDisplayEvents = 2;
   static const int kHWMdssVersion5 = 500;  // MDSS_V5
 
-  inline void SetFormat(uint32_t *target, const LayerBufferFormat &source);
-  inline void SetBlending(uint32_t *target, const LayerBlending &source);
-  inline void SetRect(mdp_rect *target, const LayerRect &source);
+  inline DisplayError SetFormat(const LayerBufferFormat &source, uint32_t *target);
+  inline void SetBlending(const LayerBlending &source, mdss_mdp_blend_op *target);
+  inline void SetRect(const LayerRect &source, mdp_rect *target);
 
   // Event Thread to receive vsync/blank events
   static void* DisplayEventThread(void *context);
@@ -117,7 +135,13 @@
   void PopulatePanelInfo(int fb_index);
   // Populates HW Capabilities
   DisplayError PopulateHWCapabilities();
-  int ParseLine(char *input, char *token[], int max_token, int *count);
+  int ParseLine(char *input, char *token[], const uint32_t max_token, uint32_t *count);
+
+  // HDMI Related Functions
+  bool EnableHotPlugDetection(int enable);
+  int GetHDMIModeCount();
+  bool MapHDMIDisplayTiming(const msm_hdmi_mode_timing_info *mode, fb_var_screeninfo *info);
+  void ResetHDMIModes();
 
   // Pointers to system calls which are either mapped to actual system call or virtual driver.
   int (*ioctl_)(int, int, ...);
@@ -125,9 +149,12 @@
   int (*close_)(int);
   int (*poll_)(struct pollfd *, nfds_t, int);
   ssize_t (*pread_)(int, void *, size_t, off_t);
-  FILE* (*fopen_)( const char *fname, const char *mode );;
+  FILE* (*fopen_)( const char *fname, const char *mode);
   int (*fclose_)(FILE* fileptr);
   ssize_t (*getline_)(char **lineptr, size_t *linelen, FILE *stream);
+  ssize_t (*read_)(int fd, void *buf, size_t count);
+  ssize_t (*write_)(int fd, const void *buf, size_t count);
+
 
   // Store the Device EventHandlers - used for callback
   HWEventHandler *event_handler_[kNumPhysicalDisplays];
@@ -137,9 +164,14 @@
   bool fake_vsync_;
   bool exit_threads_;
   HWResourceInfo hw_resource_;
-  int fb_node_index_[kHWBlockMax];
+  int fb_node_index_[kDeviceMax];
   const char* fb_path_;
   PanelInfo pri_panel_info_;
+  bool hotplug_enabled_;
+  uint32_t hdmi_mode_count_;
+  uint32_t hdmi_modes_[256];
+  // Holds the hdmi timing information. Ex: resolution, fps etc.,
+  msm_hdmi_mode_timing_info *supported_video_modes_;
 };
 
 }  // namespace sde
diff --git a/displayengine/libs/core/hw_interface.cpp b/displayengine/libs/core/hw_interface.cpp
old mode 100644
new mode 100755
index f39cc21..3ab0c7e
--- a/displayengine/libs/core/hw_interface.cpp
+++ b/displayengine/libs/core/hw_interface.cpp
@@ -22,11 +22,6 @@
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
-// SDE_LOG_TAG definition must precede debug.h include.
-#define SDE_LOG_TAG kTagCore
-#define SDE_MODULE_NAME "HWInterface"
-#include <utils/debug.h>
-
 #include <utils/constants.h>
 
 #include "hw_interface.h"
diff --git a/displayengine/libs/core/hw_interface.h b/displayengine/libs/core/hw_interface.h
index a9bdb96..f4f33f9 100644
--- a/displayengine/libs/core/hw_interface.h
+++ b/displayengine/libs/core/hw_interface.h
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2014, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014 - 2015, The Linux Foundation. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification, are permitted
 * provided that the following conditions are met:
@@ -40,6 +40,13 @@
   kHWBlockMax
 };
 
+enum HWDeviceType {
+  kDevicePrimary,
+  kDeviceHDMI,
+  kDeviceVirtual,
+  kDeviceMax
+};
+
 struct HWResourceInfo {
   uint32_t hw_version;
   uint32_t hw_revision;
@@ -59,6 +66,9 @@
   uint64_t max_bandwidth_low;
   uint64_t max_bandwidth_high;
   uint32_t max_mixer_width;
+  uint32_t max_pipe_bw;
+  uint32_t max_sde_clk;
+  float clk_fudge_factor;
   struct SplitInfo {
     uint32_t left_split;
     uint32_t right_split;
@@ -77,25 +87,45 @@
       num_cursor_pipe(0), num_blending_stages(0), num_rotator(0), num_control(0),
       num_mixer_to_disp(0), smp_total(0), smp_size(0), num_smp_per_pipe(0), max_scale_up(0),
       max_scale_down(0), max_bandwidth_low(0), max_bandwidth_high(0), max_mixer_width(2048),
-      has_bwc(false), has_decimation(false), has_macrotile(false), has_rotator_downscale(false),
+      max_pipe_bw(0), max_sde_clk(0), clk_fudge_factor(1.0f), has_bwc(false),
+      has_decimation(false), has_macrotile(false), has_rotator_downscale(false),
       has_non_scalar_rgb(false), is_src_split(false), always_src_split(false) { }
 };
 
+struct HWRotateInfo {
+  uint32_t pipe_id;
+  LayerRect src_roi;
+  LayerRect dst_roi;
+  HWBlockType writeback_id;
+  float downscale_ratio_x;
+  float downscale_ratio_y;
+
+  HWRotateInfo() : pipe_id(0), writeback_id(kHWWriteback0), downscale_ratio_x(1.0f),
+      downscale_ratio_y(1.0f) { }
+
+  inline void Reset() { *this = HWRotateInfo(); }
+};
+
 struct HWPipeInfo {
   uint32_t pipe_id;
   LayerRect src_roi;
   LayerRect dst_roi;
+  uint8_t decimation;
 
-  HWPipeInfo() : pipe_id(0) { }
+  HWPipeInfo() : pipe_id(0), decimation(1) { }
+
+  inline void Reset() { *this = HWPipeInfo(); }
 };
 
 struct HWLayerConfig {
-  bool use_non_dma_pipe;
-  bool is_right_pipe;
-  HWPipeInfo left_pipe;
-  HWPipeInfo right_pipe;
+  bool use_non_dma_pipe;  // set by client
+  bool is_right_pipe;  // indicate if right pipe is valid
+  HWPipeInfo left_pipe;  // pipe for left side of the buffer
+  HWPipeInfo right_pipe;  // pipe for right side of the buffer
+  uint32_t num_rotate;  // number of rotate
+  HWRotateInfo rotates[kMaxRotatePerLayer];  // rotation for the buffer
 
-  HWLayerConfig() : use_non_dma_pipe(false), is_right_pipe(true) { }
+  HWLayerConfig() : use_non_dma_pipe(false), is_right_pipe(false), num_rotate(0) { }
 };
 
 struct HWLayers {
@@ -124,11 +154,13 @@
   static DisplayError Create(HWInterface **intf);
   static DisplayError Destroy(HWInterface *intf);
   virtual DisplayError GetHWCapabilities(HWResourceInfo *hw_res_info) = 0;
-  virtual DisplayError Open(HWBlockType type, Handle *device, HWEventHandler *eventhandler) = 0;
+  virtual DisplayError Open(HWDeviceType type, Handle *device, HWEventHandler *eventhandler) = 0;
   virtual DisplayError Close(Handle device) = 0;
   virtual DisplayError GetNumDisplayAttributes(Handle device, uint32_t *count) = 0;
   virtual DisplayError GetDisplayAttributes(Handle device,
-                            HWDisplayAttributes *display_attributes, uint32_t mode) = 0;
+                            HWDisplayAttributes *display_attributes, uint32_t index) = 0;
+  virtual DisplayError SetDisplayAttributes(Handle device, uint32_t index) = 0;
+  virtual DisplayError GetConfigIndex(Handle device, uint32_t mode, uint32_t *index) = 0;
   virtual DisplayError PowerOn(Handle device) = 0;
   virtual DisplayError PowerOff(Handle device) = 0;
   virtual DisplayError Doze(Handle device) = 0;
diff --git a/displayengine/libs/core/offline_ctrl.cpp b/displayengine/libs/core/offline_ctrl.cpp
old mode 100644
new mode 100755
index be01cef..c380d52
--- a/displayengine/libs/core/offline_ctrl.cpp
+++ b/displayengine/libs/core/offline_ctrl.cpp
@@ -22,15 +22,13 @@
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
-// SDE_LOG_TAG definition must precede debug.h include.
-#define SDE_LOG_TAG kTagCore
-#define SDE_MODULE_NAME "OfflineCtrl"
+#include <utils/constants.h>
 #include <utils/debug.h>
 
-#include <utils/constants.h>
-
 #include "offline_ctrl.h"
 
+#define __CLASS__ "OfflineCtrl"
+
 namespace sde {
 
 OfflineCtrl::OfflineCtrl() : hw_intf_(NULL) {
diff --git a/displayengine/libs/core/res_config.cpp b/displayengine/libs/core/res_config.cpp
index 6e642ed..d093ab2 100644
--- a/displayengine/libs/core/res_config.cpp
+++ b/displayengine/libs/core/res_config.cpp
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2014, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014 - 2015, The Linux Foundation. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification, are permitted
 * provided that the following conditions are met:
@@ -22,127 +22,294 @@
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
-// SDE_LOG_TAG definition must precede debug.h include.
-#define SDE_LOG_TAG kTagCore
-#define SDE_MODULE_NAME "ResConfig"
-#include <utils/debug.h>
-
-#include <utils/constants.h>
 #include <math.h>
+#include <utils/constants.h>
+#include <utils/debug.h>
 
 #include "res_manager.h"
 
+#define __CLASS__ "ResManager"
+
 namespace sde {
 
-DisplayError ResManager::Config(DisplayResourceContext *display_resource_ctx, HWLayers *hw_layers) {
-  HWBlockType hw_block_id = display_resource_ctx->hw_block_id;
+void ResManager::RotationConfig(const LayerTransform &transform, const float &scale_x,
+                                const float &scale_y, LayerRect *src_rect,
+                                struct HWLayerConfig *layer_config, uint32_t *rotate_count) {
+  HWRotateInfo *rotate = &layer_config->rotates[0];
+  float src_width = src_rect->right - src_rect->left;
+  float src_height = src_rect->bottom - src_rect->top;
+  LayerRect dst_rect;
+  // Rotate output is a temp buffer, always output to the top left corner for saving memory
+  dst_rect.top = 0.0f;
+  dst_rect.left = 0.0f;
+
+  rotate->downscale_ratio_x = scale_x;
+  rotate->downscale_ratio_y = scale_y;
+
+  // downscale when doing rotation
+  dst_rect.right = src_height / rotate->downscale_ratio_x;
+  dst_rect.bottom = src_width / rotate->downscale_ratio_y;
+
+  rotate->src_roi = *src_rect;
+  rotate->pipe_id = kPipeIdNeedsAssignment;
+  rotate->dst_roi = dst_rect;
+
+  *src_rect = dst_rect;
+  layer_config->num_rotate = 1;
+  (*rotate_count)++;
+}
+
+DisplayError ResManager::SrcSplitConfig(DisplayResourceContext *display_resource_ctx,
+                                        const LayerTransform &transform, const LayerRect &src_rect,
+                                        const LayerRect &dst_rect, HWLayerConfig *layer_config) {
   HWDisplayAttributes &display_attributes = display_resource_ctx->display_attributes;
-  HWLayersInfo &layer_info = hw_layers->info;
+  HWPipeInfo *left_pipe = &layer_config->left_pipe;
+  HWPipeInfo *right_pipe = &layer_config->right_pipe;
+  layer_config->is_right_pipe = false;
 
-  for (uint32_t i = 0; i < layer_info.count; i++) {
-    Layer& layer = layer_info.stack->layers[layer_info.index[i]];
-    float w_scale, h_scale;
-    if (!IsValidDimension(layer, &w_scale, &h_scale)) {
-      DLOGV("Invalid dimension");
+  if ((src_rect.right - src_rect.left) >= kMaxSourcePipeWidth ||
+      (dst_rect.right - dst_rect.left) >= kMaxInterfaceWidth || hw_res_info_.always_src_split) {
+    SplitRect(transform.flip_horizontal, src_rect, dst_rect, &left_pipe->src_roi,
+              &left_pipe->dst_roi, &right_pipe->src_roi, &right_pipe->dst_roi);
+    left_pipe->pipe_id = kPipeIdNeedsAssignment;
+    right_pipe->pipe_id = kPipeIdNeedsAssignment;
+    layer_config->is_right_pipe = true;
+  } else {
+    left_pipe->src_roi = src_rect;
+    left_pipe->dst_roi = dst_rect;
+    left_pipe->pipe_id = kPipeIdNeedsAssignment;
+    right_pipe->Reset();
+  }
+  return kErrorNone;
+}
+
+DisplayError ResManager::DisplaySplitConfig(DisplayResourceContext *display_resource_ctx,
+                                            const LayerTransform &transform,
+                                            const LayerRect &src_rect, const LayerRect &dst_rect,
+                                            HWLayerConfig *layer_config) {
+  HWDisplayAttributes &display_attributes = display_resource_ctx->display_attributes;
+  // for display split case
+  HWPipeInfo *left_pipe = &layer_config->left_pipe;
+  HWPipeInfo *right_pipe = &layer_config->right_pipe;
+  LayerRect scissor, dst_left, crop_left, crop_right, dst_right;
+  layer_config->is_right_pipe = false;
+  scissor.right = FLOAT(display_attributes.split_left);
+  scissor.bottom = FLOAT(display_attributes.y_pixels);
+
+  crop_left = src_rect;
+  dst_left = dst_rect;
+  crop_right = crop_left;
+  dst_right = dst_left;
+  CalculateCropRects(scissor, transform, &crop_left, &dst_left);
+
+  scissor.left = FLOAT(display_attributes.split_left);
+  scissor.top = 0.0f;
+  scissor.right = FLOAT(display_attributes.x_pixels);
+  scissor.bottom = FLOAT(display_attributes.y_pixels);
+  CalculateCropRects(scissor, transform, &crop_right, &dst_right);
+  if ((crop_left.right - crop_left.left) >= kMaxSourcePipeWidth) {
+    if (crop_right.right != crop_right.left)
       return kErrorNotSupported;
-    }
+    // 2 pipes both are on the left
+    SplitRect(transform.flip_horizontal, crop_left, dst_left, &left_pipe->src_roi,
+              &left_pipe->dst_roi, &right_pipe->src_roi, &right_pipe->dst_roi);
+    left_pipe->pipe_id = kPipeIdNeedsAssignment;
+    right_pipe->pipe_id = kPipeIdNeedsAssignment;
+    layer_config->is_right_pipe = true;
+  } else if ((crop_right.right - crop_right.left) >= kMaxSourcePipeWidth) {
+    if (crop_left.right != crop_left.left)
+      return kErrorNotSupported;
+    // 2 pipes both are on the right
+    SplitRect(transform.flip_horizontal, crop_right, dst_right, &left_pipe->src_roi,
+              &left_pipe->dst_roi, &right_pipe->src_roi, &right_pipe->dst_roi);
+    left_pipe->pipe_id = kPipeIdNeedsAssignment;
+    right_pipe->pipe_id = kPipeIdNeedsAssignment;
+    layer_config->is_right_pipe = true;
+  } else if (UINT32(dst_left.right) > UINT32(dst_left.left)) {
+    // assign left pipe
+    left_pipe->src_roi = crop_left;
+    left_pipe->dst_roi = dst_left;
+    left_pipe->pipe_id = kPipeIdNeedsAssignment;
+  } else {
+    // Set default value, left_pipe is not needed.
+    left_pipe->Reset();
+  }
 
-    LayerRect scissor;
-    scissor.right = FLOAT(display_attributes.split_left);
-    scissor.bottom = FLOAT(display_attributes.y_pixels);
-    LayerRect crop = layer.src_rect;
-    LayerRect dst = layer.dst_rect;
-    LayerRect cropRight = crop;
-    LayerRect dstRight = dst;
-    CalculateCropRects(&crop, &dst, scissor, layer.transform);
-    HWPipeInfo *pipe_info = &hw_layers->config[i].left_pipe;
-
-    pipe_info->src_roi = crop;
-    pipe_info->dst_roi = dst;
-
-    float crop_width = cropRight.right - cropRight.left;
-    pipe_info = &hw_layers->config[i].right_pipe;
-    if ((dstRight.right - dstRight.left) > kMaxInterfaceWidth ||
-         crop_width > kMaxInterfaceWidth ||
-        ((hw_block_id == kHWPrimary) && hw_res_info_.is_src_split &&
-         (crop_width > display_attributes.split_left))) {
-      scissor.left = FLOAT(display_attributes.split_left);
-      scissor.top = 0.0f;
-      scissor.right = FLOAT(display_attributes.x_pixels);
-      scissor.bottom = FLOAT(display_attributes.y_pixels);
-      CalculateCropRects(&cropRight, &dstRight, scissor, layer.transform);
-      pipe_info->src_roi = cropRight;
-      pipe_info->dst_roi = dstRight;
-      pipe_info->pipe_id = -1;
+  // assign right pipe if needed
+  if (UINT32(dst_right.right) > UINT32(dst_right.left)) {
+    if (left_pipe->pipe_id) {
+      right_pipe->src_roi = crop_right;
+      right_pipe->dst_roi = dst_right;
+      right_pipe->pipe_id = kPipeIdNeedsAssignment;
+      layer_config->is_right_pipe = true;
     } else {
-      // need not right pipe
-      pipe_info->pipe_id = 0;
+      // If left pipe is not used, use left pipe first.
+      left_pipe->src_roi = crop_right;
+      left_pipe->dst_roi = dst_right;
+      left_pipe->pipe_id = kPipeIdNeedsAssignment;
+      right_pipe->Reset();
     }
+  } else {
+    // need not right pipe
+    right_pipe->Reset();
   }
 
   return kErrorNone;
 }
 
-bool ResManager::IsValidDimension(const Layer& layer, float *width_scale, float *height_scale) {
-  if (IsNonIntegralSrcCrop(layer.src_rect)) {
-    return false;
-  }
+DisplayError ResManager::Config(DisplayResourceContext *display_resource_ctx, HWLayers *hw_layers,
+                                uint32_t *rotate_count) {
+  HWBlockType hw_block_id = display_resource_ctx->hw_block_id;
+  HWDisplayAttributes &display_attributes = display_resource_ctx->display_attributes;
+  HWLayersInfo &layer_info = hw_layers->info;
+  DisplayError error = kErrorNone;
 
-  LayerRect crop;
-  LayerRect dst;
-  IntegerizeRect(&crop, layer.src_rect);
-  IntegerizeRect(&dst, layer.dst_rect);
+  for (uint32_t i = 0; i < layer_info.count; i++) {
+    Layer& layer = layer_info.stack->layers[layer_info.index[i]];
+    float rot_scale_x = 1.0f, rot_scale_y = 1.0f;
+    if (!IsValidDimension(layer.src_rect, layer.dst_rect)) {
+      DLOGE_IF(kTagResources, "Input is invalid");
+      LogRectVerbose("input layer src_rect", layer.src_rect);
+      LogRectVerbose("input layer dst_rect", layer.dst_rect);
+      return kErrorNotSupported;
+    }
 
-  bool rotated90 = (static_cast<int>(layer.transform.rotation) == 90);
-  float crop_w = rotated90 ? crop.bottom - crop.top : crop.right - crop.left;
-  float crop_h = rotated90 ? crop.right - crop.left : crop.bottom - crop.top;
-  float dst_w = dst.right - dst.left;
-  float dst_h = dst.bottom - dst.top;
+    LayerRect scissor, src_rect, dst_rect;
+    src_rect = layer.src_rect;
+    dst_rect = layer.dst_rect;
+    scissor.right = FLOAT(display_attributes.x_pixels);
+    scissor.bottom = FLOAT(display_attributes.y_pixels);
+    CalculateCropRects(scissor, layer.transform, &src_rect, &dst_rect);
 
-  if ((dst_w < 1) || (dst_h < 1)) {
-    return false;
-  }
+    if (ValidateScaling(layer, src_rect, dst_rect, &rot_scale_x, &rot_scale_y))
+      return kErrorNotSupported;
 
-  float w_scale = crop_w / dst_w;
-  float h_scale = crop_h / dst_h;
+    struct HWLayerConfig *layer_config = &hw_layers->config[i];
+    // config rotator first
+    for (uint32_t j = 0; j < kMaxRotatePerLayer; j++) {
+      layer_config->rotates[j].Reset();
+    }
+    layer_config->num_rotate = 0;
 
-  if ((crop_w < kMaxCropWidth) ||(crop_h < kMaxCropHeight)) {
-    return false;
-  }
+    LayerTransform transform = layer.transform;
+    if (IsRotationNeeded(transform.rotation) ||
+        UINT32(rot_scale_x) != 1 || UINT32(rot_scale_y) != 1) {
+      RotationConfig(layer.transform, rot_scale_x, rot_scale_y, &src_rect, layer_config,
+                     rotate_count);
+      // rotator will take care of flipping, reset tranform
+      transform = LayerTransform();
+    }
 
-  if ((w_scale > 1.0f) || (h_scale > 1.0f)) {
-    const uint32_t max_scale_down = hw_res_info_.max_scale_down;
-
-    if (!hw_res_info_.has_decimation) {
-      if (crop_w > kMaxSourcePipeWidth || w_scale > max_scale_down || h_scale > max_scale_down) {
-        return false;
-      }
+    if (hw_res_info_.is_src_split) {
+      error = SrcSplitConfig(display_resource_ctx, transform, src_rect,
+                             dst_rect, layer_config);
     } else {
-      if (w_scale > max_scale_down || h_scale > max_scale_down) {
-        return false;
-      }
+      error = DisplaySplitConfig(display_resource_ctx, transform, src_rect,
+                                 dst_rect, layer_config);
+    }
+
+    if (error != kErrorNone)
+      break;
+
+    DLOGV_IF(kTagResources, "layer = %d, left pipe_id = %x",
+             i, layer_config->left_pipe.pipe_id);
+    LogRectVerbose("input layer src_rect", layer.src_rect);
+    LogRectVerbose("input layer dst_rect", layer.dst_rect);
+    LogRectVerbose("cropped src_rect", src_rect);
+    LogRectVerbose("cropped dst_rect", dst_rect);
+    LogRectVerbose("left pipe src", layer_config->left_pipe.src_roi);
+    LogRectVerbose("left pipe dst", layer_config->left_pipe.dst_roi);
+    if (hw_layers->config[i].right_pipe.pipe_id) {
+      LogRectVerbose("right pipe src", layer_config->right_pipe.src_roi);
+      LogRectVerbose("right pipe dst", layer_config->right_pipe.dst_roi);
     }
   }
 
-  if (((w_scale < 1.0f) || (h_scale < 1.0f)) && (w_scale > 0.0f) && (h_scale > 0.0f)) {
-    const uint32_t max_scale_up = hw_res_info_.max_scale_up;
-    const float w_uscale = 1.0f / w_scale;
-    const float h_uscale = 1.0f / h_scale;
-
-    if (w_uscale > max_scale_up || h_uscale > max_scale_up) {
-      return false;
-    }
-  }
-
-  *width_scale = w_scale;
-  *height_scale = h_scale;
-
-  return true;
+  return error;
 }
 
-void ResManager::CalculateCut(float *left_cut_ratio,
-    float *top_cut_ratio, float *right_cut_ratio, float *bottom_cut_ratio,
-    const LayerTransform& transform) {
+DisplayError ResManager::ValidateScaling(const Layer &layer, const LayerRect &crop,
+                                         const LayerRect &dst, float *rot_scale_x,
+                                         float *rot_scale_y) {
+  bool rotated90 = IsRotationNeeded(layer.transform.rotation);
+  float crop_width = rotated90 ? crop.bottom - crop.top : crop.right - crop.left;
+  float crop_height = rotated90 ? crop.right - crop.left : crop.bottom - crop.top;
+  float dst_width = dst.right - dst.left;
+  float dst_height = dst.bottom - dst.top;
+
+  if ((dst_width < 1.0f) || (dst_height < 1.0f)) {
+    DLOGV_IF(kTagResources, "Destination region is too small w = %d, h = %d",
+    dst_width, dst_height);
+    return kErrorNotSupported;
+  }
+
+  if ((crop_width < 1.0f) || (crop_height < 1.0f)) {
+    DLOGV_IF(kTagResources, "source region is too small w = %d, h = %d", crop_width, crop_height);
+    return kErrorNotSupported;
+  }
+
+  float scale_x = crop_width / dst_width;
+  float scale_y = crop_height / dst_height;
+
+  if ((UINT32(scale_x) > 1) || (UINT32(scale_y) > 1)) {
+    const uint32_t max_scale_down = hw_res_info_.max_scale_down;
+    uint32_t max_downscale_with_rotator;
+
+    if (hw_res_info_.has_rotator_downscale)
+      max_downscale_with_rotator = max_scale_down * kMaxRotateDownScaleRatio;
+    else
+      max_downscale_with_rotator = max_scale_down;
+
+    if (((!hw_res_info_.has_decimation) || (IsMacroTileFormat(layer.input_buffer))) &&
+        (scale_x > max_scale_down || scale_y > max_scale_down)) {
+      DLOGV_IF(kTagResources,
+               "Scaling down is over the limit is_tile = %d, scale_x = %d, scale_y = %d",
+               IsMacroTileFormat(layer.input_buffer), scale_x, scale_y);
+      return kErrorNotSupported;
+    } else if (scale_x > max_downscale_with_rotator || scale_y > max_downscale_with_rotator) {
+      DLOGV_IF(kTagResources, "Scaling down is over the limit scale_x = %d, scale_y = %d",
+               scale_x, scale_y);
+      return kErrorNotSupported;
+    }
+  }
+
+  const uint32_t max_scale_up = hw_res_info_.max_scale_up;
+  if (UINT32(scale_x) < 1 && scale_x > 0.0f) {
+    if ((1.0f / scale_x) > max_scale_up) {
+      DLOGV_IF(kTagResources, "Scaling up is over limit scale_x = %d", 1.0f / scale_x);
+      return kErrorNotSupported;
+    }
+  }
+
+  if (UINT32(scale_y) < 1 && scale_y > 0.0f) {
+    if ((1.0f / scale_y) > max_scale_up) {
+      DLOGV_IF(kTagResources, "Scaling up is over limit scale_y = %d", 1.0f / scale_y);
+      return kErrorNotSupported;
+    }
+  }
+
+  // Calculate rotator downscale ratio
+  float rot_scale = 1.0f;
+  while (scale_x > hw_res_info_.max_scale_down) {
+    scale_x /= 2;
+    rot_scale *= 2;
+  }
+  *rot_scale_x = rot_scale;
+
+  rot_scale = 1.0f;
+  while (scale_y > hw_res_info_.max_scale_down) {
+    scale_y /= 2;
+    rot_scale *= 2;
+  }
+  *rot_scale_y = rot_scale;
+  DLOGV_IF(kTagResources, "rotator scaling hor = %.0f, ver = %.0f", *rot_scale_x, *rot_scale_y);
+
+  return kErrorNone;
+}
+
+void ResManager::CalculateCut(const LayerTransform &transform, float *left_cut_ratio,
+                              float *top_cut_ratio, float *right_cut_ratio,
+                              float *bottom_cut_ratio) {
   if (transform.flip_horizontal) {
     Swap(*left_cut_ratio, *right_cut_ratio);
   }
@@ -151,7 +318,7 @@
     Swap(*top_cut_ratio, *bottom_cut_ratio);
   }
 
-  if (UINT32(transform.rotation) == 90) {
+  if (IsRotationNeeded(transform.rotation)) {
     // Anti clock swapping
     float tmp_cut_ratio = *left_cut_ratio;
     *left_cut_ratio = *top_cut_ratio;
@@ -161,76 +328,152 @@
   }
 }
 
-void ResManager::CalculateCropRects(LayerRect *crop, LayerRect *dst,
-    const LayerRect& scissor, const LayerTransform& transform) {
-  float& crop_l = crop->left;
-  float& crop_t = crop->top;
-  float& crop_r = crop->right;
-  float& crop_b = crop->bottom;
-  float crop_w = crop->right - crop->left;
-  float crop_h = crop->bottom - crop->top;
+void ResManager::CalculateCropRects(const LayerRect &scissor, const LayerTransform &transform,
+                                    LayerRect *crop, LayerRect *dst) {
+  float &crop_left = crop->left;
+  float &crop_top = crop->top;
+  float &crop_right = crop->right;
+  float &crop_bottom = crop->bottom;
+  float crop_width = crop->right - crop->left;
+  float crop_height = crop->bottom - crop->top;
 
-  float& dst_l = dst->left;
-  float& dst_t = dst->top;
-  float& dst_r = dst->right;
-  float& dst_b = dst->bottom;
-  float dst_w = (dst->right > dst->left) ? dst->right - dst->left :
-    dst->left - dst->right;
-  float dst_h = (dst->bottom > dst->top) ? dst->bottom > dst->top :
-    dst->top > dst->bottom;
+  float &dst_left = dst->left;
+  float &dst_top = dst->top;
+  float &dst_right = dst->right;
+  float &dst_bottom = dst->bottom;
+  float dst_width = dst->right - dst->left;
+  float dst_height = dst->bottom - dst->top;
 
-  const float& sci_l = scissor.left;
-  const float& sci_t = scissor.top;
-  const float& sci_r = scissor.right;
-  const float& sci_b = scissor.bottom;
+  const float &sci_left = scissor.left;
+  const float &sci_top = scissor.top;
+  const float &sci_right = scissor.right;
+  const float &sci_bottom = scissor.bottom;
 
-  float left_cut_ratio = 0.0, right_cut_ratio = 0.0, top_cut_ratio = 0.0,
-    bottom_cut_ratio = 0.0;
+  float left_cut_ratio = 0.0, right_cut_ratio = 0.0, top_cut_ratio = 0.0, bottom_cut_ratio = 0.0;
+  bool need_cut = false;
 
-  if (dst_l < sci_l) {
-    left_cut_ratio = (sci_l - dst_l) / dst_w;
-    dst_l = sci_l;
+  if (dst_left < sci_left) {
+    left_cut_ratio = (sci_left - dst_left) / dst_width;
+    dst_left = sci_left;
+    need_cut = true;
   }
 
-  if (dst_r > sci_r) {
-    right_cut_ratio = (dst_r - sci_r) / dst_w;
-    dst_r = sci_r;
+  if (dst_right > sci_right) {
+    right_cut_ratio = (dst_right - sci_right) / dst_width;
+    dst_right = sci_right;
+    need_cut = true;
   }
 
-  if (dst_t < sci_t) {
-    top_cut_ratio = (sci_t - dst_t) / (dst_h);
-    dst_t = sci_t;
+  if (dst_top < sci_top) {
+    top_cut_ratio = (sci_top - dst_top) / (dst_height);
+    dst_top = sci_top;
+    need_cut = true;
   }
 
-  if (dst_b > sci_b) {
-    bottom_cut_ratio = (dst_b - sci_b) / (dst_h);
-    dst_b = sci_b;
+  if (dst_bottom > sci_bottom) {
+    bottom_cut_ratio = (dst_bottom - sci_bottom) / (dst_height);
+    dst_bottom = sci_bottom;
+    need_cut = true;
   }
 
-  CalculateCut(&left_cut_ratio, &top_cut_ratio, &right_cut_ratio, &bottom_cut_ratio, transform);
-  crop_l += crop_w * left_cut_ratio;
-  crop_t += crop_h * top_cut_ratio;
-  crop_r -= crop_w * right_cut_ratio;
-  crop_b -= crop_h * bottom_cut_ratio;
+  if (!need_cut)
+    return;
+
+  CalculateCut(transform, &left_cut_ratio, &top_cut_ratio, &right_cut_ratio, &bottom_cut_ratio);
+  crop_left += crop_width * left_cut_ratio;
+  crop_top += crop_height * top_cut_ratio;
+  crop_right -= crop_width * right_cut_ratio;
+  crop_bottom -= crop_height * bottom_cut_ratio;
 }
 
-bool ResManager::IsNonIntegralSrcCrop(const LayerRect& crop) {
-  if (crop.left - roundf(crop.left)     ||
-      crop.top - roundf(crop.top)       ||
-      crop.right - roundf(crop.right)   ||
-      crop.bottom - roundf(crop.bottom)) {
-    return true;
-  } else {
+bool ResManager::IsValidDimension(const LayerRect &src, const LayerRect &dst) {
+  // Make sure source in integral
+  if (src.left - roundf(src.left)     ||
+      src.top - roundf(src.top)       ||
+      src.right - roundf(src.right)   ||
+      src.bottom - roundf(src.bottom)) {
+    DLOGE_IF(kTagResources, "Input ROI is not integral");
     return false;
   }
+
+  if (src.left > src.right || src.top > src.bottom || dst.left > dst.right ||
+      dst.top > dst.bottom) {
+    return false;
+  } else {
+    return true;
+  }
 }
 
-void ResManager::IntegerizeRect(LayerRect *dst_rect, const LayerRect &src_rect) {
-  dst_rect->left = ceilf(src_rect.left);
-  dst_rect->top = ceilf(src_rect.top);
-  dst_rect->right = floorf(src_rect.right);
-  dst_rect->bottom = floorf(src_rect.bottom);
+void ResManager::SetDecimationFactor(HWPipeInfo *pipe) {
+  float max_down_scale = FLOAT(hw_res_info_.max_scale_down);
+  float src_h = pipe->src_roi.bottom - pipe->src_roi.top;
+  float dst_h = pipe->dst_roi.bottom - pipe->dst_roi.top;
+  float down_scale = src_h / dst_h;
+  pipe->decimation = 1;
+
+  if (!hw_res_info_.has_decimation || (down_scale <= max_down_scale))
+    return;
+
+  // Decimation is the remaining downscale factor after doing max SDE downscale.
+  // In SDE, decimation is supported in powers of 2.
+  // For ex: If a pipe needs downscale of 8 but max_down_scale is 4
+  // So decimation = powf(2.0, ceilf(log2f(8) - log2f(4))) = powf(2.0, 1.0) = 2
+  float decimation_factor = ceilf(log2f(down_scale) - log2f(max_down_scale));
+  pipe->decimation = UINT8(powf(2.0f, decimation_factor));
+}
+
+void ResManager::SplitRect(bool flip_horizontal, const LayerRect &src_rect,
+                           const LayerRect &dst_rect, LayerRect *src_left, LayerRect *dst_left,
+                           LayerRect *src_right, LayerRect *dst_right) {
+  // Split rectangle horizontally and evenly into two.
+  float src_width = src_rect.right - src_rect.left;
+  float dst_width = dst_rect.right - dst_rect.left;
+  if (flip_horizontal) {
+    src_left->top = src_rect.top;
+    src_left->left = src_rect.left;
+    src_left->right = src_rect.left + (src_width / 2);
+    src_left->bottom = src_rect.bottom;
+
+    dst_left->top = dst_rect.top;
+    dst_left->left = dst_rect.left + (dst_width / 2);
+    dst_left->right = dst_rect.right;
+    dst_left->bottom = dst_rect.bottom;
+
+    src_right->top = src_rect.top;
+    src_right->left = src_left->right;
+    src_right->right = src_rect.right;
+    src_right->bottom = src_rect.bottom;
+
+    dst_right->top = dst_rect.top;
+    dst_right->left = dst_rect.left;
+    dst_right->right = dst_left->left;
+    dst_right->bottom = dst_rect.bottom;
+  } else {
+    src_left->top = src_rect.top;
+    src_left->left = src_rect.left;
+    src_left->right = src_rect.left + (src_width / 2);
+    src_left->bottom = src_rect.bottom;
+
+    dst_left->top = dst_rect.top;
+    dst_left->left = dst_rect.left;
+    dst_left->right = dst_rect.left + (dst_width / 2);
+    dst_left->bottom = dst_rect.bottom;
+
+    src_right->top = src_rect.top;
+    src_right->left = src_left->right;
+    src_right->right = src_rect.right;
+    src_right->bottom = src_rect.bottom;
+
+    dst_right->top = dst_rect.top;
+    dst_right->left = dst_left->right;
+    dst_right->right = dst_rect.right;
+    dst_right->bottom = dst_rect.bottom;
+  }
+}
+
+void ResManager::LogRectVerbose(const char *prefix, const LayerRect &roi) {
+  DLOGV_IF(kTagResources, "%s: left = %.0f, top = %.0f, right = %.0f, bottom = %.0f",
+           prefix, roi.left, roi.top, roi.right, roi.bottom);
 }
 
 }  // namespace sde
-
diff --git a/displayengine/libs/core/res_manager.cpp b/displayengine/libs/core/res_manager.cpp
index 3f5bd32..7b36563 100644
--- a/displayengine/libs/core/res_manager.cpp
+++ b/displayengine/libs/core/res_manager.cpp
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2014, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014 - 2015, The Linux Foundation. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification, are permitted
 * provided that the following conditions are met:
@@ -22,31 +22,29 @@
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
-// SDE_LOG_TAG definition must precede debug.h include.
-#define SDE_LOG_TAG kTagCore
-#define SDE_MODULE_NAME "ResManager"
+#include <utils/constants.h>
 #include <utils/debug.h>
 
-#include <utils/constants.h>
-
 #include "res_manager.h"
 
+#define __CLASS__ "ResManager"
+
 namespace sde {
 
 ResManager::ResManager()
-  : num_pipe_(0), vig_pipes_(NULL), rgb_pipes_(NULL), dma_pipes_(NULL), frame_start_(false) {
+  : num_pipe_(0), vig_pipes_(NULL), rgb_pipes_(NULL), dma_pipes_(NULL), virtual_count_(0) {
 }
 
 DisplayError ResManager::Init(const HWResourceInfo &hw_res_info) {
-  DLOGV("Init");
-
   hw_res_info_ = hw_res_info;
 
   DisplayError error = kErrorNone;
 
+  // TODO(user): Remove this. Disable src_split as kernel not supported yet
+  hw_res_info_.is_src_split = false;
   num_pipe_ = hw_res_info_.num_vig_pipe + hw_res_info_.num_rgb_pipe + hw_res_info_.num_dma_pipe;
 
-  if (UNLIKELY(num_pipe_ > kPipeIdMax)) {
+  if (num_pipe_ > kPipeIdMax) {
     DLOGE("Number of pipe is over the limit! %d", num_pipe_);
     return kErrorParameters;
   }
@@ -81,6 +79,20 @@
   DLOGI("hw_rev=%x, DMA=%d RGB=%d VIG=%d", hw_res_info_.hw_revision, hw_res_info_.num_dma_pipe,
     hw_res_info_.num_rgb_pipe, hw_res_info_.num_vig_pipe);
 
+  if (hw_res_info_.num_rotator > kMaxNumRotator) {
+    DLOGE("Number of rotator is over the limit! %d", hw_res_info_.num_rotator);
+    return kErrorParameters;
+  }
+
+  if (hw_res_info_.num_rotator > 0) {
+    rotators_[0].pipe_index = dma_pipes_[0].index;
+    rotators_[0].writeback_id = kHWWriteback0;
+  }
+  if (hw_res_info_.num_rotator > 1) {
+    rotators_[1].pipe_index = dma_pipes_[1].index;
+    rotators_[1].writeback_id = kHWWriteback1;
+  }
+
   // Used by splash screen
   rgb_pipes_[0].state = kPipeStateOwnedByKernel;
   rgb_pipes_[1].state = kPipeStateOwnedByKernel;
@@ -93,28 +105,27 @@
 }
 
 DisplayError ResManager::RegisterDisplay(DisplayType type, const HWDisplayAttributes &attributes,
-                                        Handle *display_ctx) {
+                                         Handle *display_ctx) {
   DisplayError error = kErrorNone;
 
   HWBlockType hw_block_id = kHWBlockMax;
   switch (type) {
   case kPrimary:
-    if (UNLIKELY(!hw_block_ctx_[kHWPrimary].is_in_use)) {
+    if (!hw_block_ctx_[kHWPrimary].is_in_use) {
       hw_block_id = kHWPrimary;
     }
     break;
 
   case kHDMI:
-    if (UNLIKELY(!hw_block_ctx_[kHWHDMI].is_in_use)) {
+    if (!hw_block_ctx_[kHWHDMI].is_in_use) {
       hw_block_id = kHWHDMI;
     }
     break;
 
   case kVirtual:
-    // assume only WB2 can be used for vitrual display
-    if (UNLIKELY(!hw_block_ctx_[kHWWriteback2].is_in_use)) {
-      hw_block_id = kHWWriteback2;
-    }
+    // TODO(user): read this block id from kernel
+    virtual_count_++;
+    hw_block_id = kHWWriteback2;
     break;
 
   default:
@@ -122,12 +133,12 @@
     return kErrorParameters;
   }
 
-  if (UNLIKELY(hw_block_id == kHWBlockMax)) {
+  if (hw_block_id == kHWBlockMax) {
     return kErrorResources;
   }
 
   DisplayResourceContext *display_resource_ctx = new DisplayResourceContext();
-  if (UNLIKELY(!display_resource_ctx)) {
+  if (!display_resource_ctx) {
     return kErrorMemory;
   }
 
@@ -136,36 +147,46 @@
   display_resource_ctx->display_attributes = attributes;
   display_resource_ctx->display_type = type;
   display_resource_ctx->hw_block_id = hw_block_id;
+  if (!display_resource_ctx->display_attributes.is_device_split)
+    display_resource_ctx->display_attributes.split_left =
+      display_resource_ctx->display_attributes.x_pixels;
 
   *display_ctx = display_resource_ctx;
-
-  return kErrorNone;
+  return error;
 }
 
 DisplayError ResManager::UnregisterDisplay(Handle display_ctx) {
   DisplayResourceContext *display_resource_ctx =
                           reinterpret_cast<DisplayResourceContext *>(display_ctx);
 
-  Purge(display_ctx);
-  hw_block_ctx_[display_resource_ctx->hw_block_id].is_in_use = false;
+  if (display_resource_ctx->hw_block_id == kHWWriteback2) {
+    virtual_count_--;
+    if (!virtual_count_)
+      hw_block_ctx_[display_resource_ctx->hw_block_id].is_in_use = false;
+  } else {
+    hw_block_ctx_[display_resource_ctx->hw_block_id].is_in_use = false;
+  }
+
+  if (!hw_block_ctx_[display_resource_ctx->hw_block_id].is_in_use)
+    Purge(display_ctx);
+
   delete display_resource_ctx;
 
   return kErrorNone;
 }
 
-
 DisplayError ResManager::Start(Handle display_ctx) {
   locker_.Lock();
 
   DisplayResourceContext *display_resource_ctx =
                           reinterpret_cast<DisplayResourceContext *>(display_ctx);
 
-  if (frame_start_) {
+  if (display_resource_ctx->frame_start) {
     return kErrorNone;  // keep context locked.
   }
 
   // First call in the cycle
-  frame_start_ = true;
+  display_resource_ctx->frame_start = true;
   display_resource_ctx->frame_count++;
 
   // Release the pipes not used in the previous cycle
@@ -176,6 +197,20 @@
       src_pipes_[i].state = kPipeStateIdle;
     }
   }
+
+  // Clear rotator usage
+  for (uint32_t i = 0; i < hw_res_info_.num_rotator; i++) {
+    uint32_t pipe_index;
+    pipe_index = rotators_[i].pipe_index;
+    rotators_[i].ClearState(display_resource_ctx->hw_block_id);
+    if (rotators_[i].client_bit_mask == 0 &&
+        src_pipes_[pipe_index].state == kPipeStateToRelease &&
+        src_pipes_[pipe_index].hw_block_id == rotators_[i].writeback_id) {
+      src_pipes_[pipe_index].dedicated_hw_block = kHWBlockMax;
+      src_pipes_[pipe_index].state = kPipeStateIdle;
+    }
+  }
+
   return kErrorNone;
 }
 
@@ -195,56 +230,71 @@
   DisplayError error = kErrorNone;
   const struct HWLayersInfo &layer_info = hw_layers->info;
 
-  if (UNLIKELY(!layer_info.count)) {
-    return kErrorNone;
-  }
-
-  if (UNLIKELY(layer_info.count > num_pipe_)) {
+  if (layer_info.count > num_pipe_) {
     return kErrorResources;
   }
 
-  error = Config(display_resource_ctx, hw_layers);
-  if (UNLIKELY(error != kErrorNone)) {
+  uint32_t rotate_count = 0;
+  error = Config(display_resource_ctx, hw_layers, &rotate_count);
+  if (error != kErrorNone) {
     return error;
   }
 
-  uint32_t left_index = 0;
+  uint32_t left_index = kPipeIdMax;
   bool need_scale = false;
   HWBlockType hw_block_id = display_resource_ctx->hw_block_id;
+  HWBlockType rotator_block = kHWBlockMax;
 
   // Clear reserved marking
   for (uint32_t i = 0; i < num_pipe_; i++) {
-    src_pipes_[i].reserved = false;
+    if (src_pipes_[i].reserved_hw_block == hw_block_id)
+      src_pipes_[i].reserved_hw_block = kHWBlockMax;
   }
 
+  // allocate rotator
+  error = AcquireRotator(display_resource_ctx, rotate_count);
+  if (error != kErrorNone)
+    return error;
+
+  rotate_count = 0;
   for (uint32_t i = 0; i < layer_info.count; i++) {
     Layer &layer = layer_info.stack->layers[layer_info.index[i]];
-    bool use_non_dma_pipe = hw_layers->config[i].use_non_dma_pipe;
+    struct HWLayerConfig &layer_config = hw_layers->config[i];
+    bool use_non_dma_pipe = layer_config.use_non_dma_pipe;
 
-    // Temp setting, this should be set by comp_manager
+    // TODO(user): set this from comp_manager
     if (hw_block_id == kHWPrimary) {
       use_non_dma_pipe = true;
     }
 
-    HWPipeInfo *pipe_info = &hw_layers->config[i].left_pipe;
-
-    need_scale = IsScalingNeeded(pipe_info);
-
-    // Should have a generic macro
-    bool is_yuv = (layer.input_buffer->format >= kFormatYCbCr420Planar);
-
-    left_index = GetPipe(hw_block_id, is_yuv, need_scale, false, use_non_dma_pipe);
-    if (left_index >= num_pipe_) {
-      goto Acquire_failed;
+    for (uint32_t j = 0; j < layer_config.num_rotate; j++) {
+      AssignRotator(&layer_config.rotates[j], &rotate_count);
     }
 
-    src_pipes_[left_index].reserved = true;
+    HWPipeInfo *pipe_info = &layer_config.left_pipe;
 
-    pipe_info =  &hw_layers->config[i].right_pipe;
+    // Should have a generic macro
+    bool is_yuv = IsYuvFormat(layer.input_buffer->format);
+
+    // left pipe is needed
+    if (pipe_info->pipe_id) {
+      need_scale = IsScalingNeeded(pipe_info);
+      left_index = GetPipe(hw_block_id, is_yuv, need_scale, false, use_non_dma_pipe);
+      if (left_index >= num_pipe_) {
+        goto CleanupOnError;
+      }
+      src_pipes_[left_index].reserved_hw_block = hw_block_id;
+    }
+
+    SetDecimationFactor(pipe_info);
+
+    pipe_info =  &layer_config.right_pipe;
     if (pipe_info->pipe_id == 0) {
       // assign single pipe
-      hw_layers->config[i].left_pipe.pipe_id = src_pipes_[left_index].mdss_pipe_id;
-      src_pipes_[left_index].at_right = false;
+      if (left_index < num_pipe_) {
+        layer_config.left_pipe.pipe_id = src_pipes_[left_index].mdss_pipe_id;
+        src_pipes_[left_index].at_right = false;
+      }
       continue;
     }
 
@@ -253,7 +303,7 @@
     uint32_t right_index;
     right_index = GetPipe(hw_block_id, is_yuv, need_scale, true, use_non_dma_pipe);
     if (right_index >= num_pipe_) {
-      goto Acquire_failed;
+      goto CleanupOnError;
     }
 
     if (src_pipes_[right_index].priority < src_pipes_[left_index].priority) {
@@ -262,48 +312,267 @@
     }
 
     // assign dual pipes
-    hw_layers->config[i].right_pipe.pipe_id = src_pipes_[right_index].mdss_pipe_id;
-    src_pipes_[right_index].reserved = true;
+    pipe_info->pipe_id = src_pipes_[right_index].mdss_pipe_id;
+    src_pipes_[right_index].reserved_hw_block = hw_block_id;
     src_pipes_[right_index].at_right = true;
-    src_pipes_[left_index].reserved = true;
+    src_pipes_[left_index].reserved_hw_block = hw_block_id;
     src_pipes_[left_index].at_right = false;
-    hw_layers->config[i].left_pipe.pipe_id = src_pipes_[left_index].mdss_pipe_id;
+    layer_config.left_pipe.pipe_id = src_pipes_[left_index].mdss_pipe_id;
+    SetDecimationFactor(pipe_info);
+
+    DLOGV_IF(kTagResources, "Pipe acquired, layer index = %d, left_pipe = %x, right_pipe = %x",
+            i, layer_config.left_pipe.pipe_id,  pipe_info->pipe_id);
+  }
+
+  if (!CheckBandwidth(display_resource_ctx, hw_layers)) {
+    DLOGV_IF(kTagResources, "Bandwidth check failed!");
+    goto CleanupOnError;
   }
 
   return kErrorNone;
 
-Acquire_failed:
-  for (uint32_t i = 0; i < num_pipe_; i++)
-    src_pipes_[i].reserved = false;
+CleanupOnError:
+  DLOGV_IF(kTagResources, "Resource reserving failed! hw_block = %d", hw_block_id);
+  for (uint32_t i = 0; i < num_pipe_; i++) {
+    if (src_pipes_[i].reserved_hw_block == hw_block_id)
+      src_pipes_[i].reserved_hw_block = kHWBlockMax;
+  }
   return kErrorResources;
 }
 
+bool ResManager::CheckBandwidth(DisplayResourceContext *display_ctx, HWLayers *hw_layers) {
+  float max_pipe_bw = FLOAT(hw_res_info_.max_pipe_bw) / 1000000;  // KBps to GBps
+  float max_sde_clk = FLOAT(hw_res_info_.max_sde_clk) / 1000000;  // Hz to MHz
+  const struct HWLayersInfo &layer_info = hw_layers->info;
+
+  float left_pipe_bw[kMaxSDELayers] = {0};
+  float right_pipe_bw[kMaxSDELayers] = {0};
+  float left_max_clk = 0;
+  float right_max_clk = 0;
+
+  for (uint32_t i = 0; i < layer_info.count; i++) {
+    Layer &layer = layer_info.stack->layers[layer_info.index[i]];
+    float bpp = GetBpp(layer.input_buffer->format);
+    uint32_t left_id = hw_layers->config[i].left_pipe.pipe_id;
+    uint32_t right_id = hw_layers->config[i].right_pipe.pipe_id;
+
+    left_pipe_bw[i] = left_id ? GetPipeBw(display_ctx, &hw_layers->config[i].left_pipe, bpp) : 0;
+    right_pipe_bw[i] = right_id ? GetPipeBw(display_ctx, &hw_layers->config[i].right_pipe, bpp) : 0;
+
+    if ((left_pipe_bw[i] > max_pipe_bw) || (right_pipe_bw[i] > max_pipe_bw)) {
+      DLOGV_IF(kTagResources, "Pipe bandwidth exceeds limit for layer index = %d", i);
+      return false;
+    }
+
+    float left_clk = left_id ? GetClockForPipe(display_ctx, &hw_layers->config[i].left_pipe) : 0;
+    float right_clk = right_id ? GetClockForPipe(display_ctx, &hw_layers->config[i].right_pipe) : 0;
+
+    left_max_clk = MAX(left_clk, left_max_clk);
+    right_max_clk = MAX(right_clk, right_max_clk);
+  }
+
+  float left_mixer_bw = GetOverlapBw(hw_layers, left_pipe_bw, true);
+  float right_mixer_bw = GetOverlapBw(hw_layers, right_pipe_bw, false);
+  float display_bw = left_mixer_bw + right_mixer_bw;
+
+  // Check system bandwidth (nth External + max(nth, n-1th) Primary)
+  if (display_ctx->hw_block_id == kHWPrimary) {
+    display_bw = MAX(display_bw, last_primary_bw_);
+    last_primary_bw_ = left_mixer_bw + right_mixer_bw;
+  }
+
+  // If system has Video mode panel, use max_bandwidth_low, else use max_bandwidth_high
+  if ((display_bw + bw_claimed_) > (hw_res_info_.max_bandwidth_low / 1000000)) {
+    DLOGV_IF(kTagResources, "Overlap bandwidth exceeds limit!");
+    return false;
+  }
+
+  // Max clock requirement of display
+  float display_clk = MAX(left_max_clk, right_max_clk);
+
+  // Check max clock requirement of system
+  float system_clk = MAX(display_clk, clk_claimed_);
+
+  // Apply fudge factor to consider in-efficieny
+  if ((system_clk * hw_res_info_.clk_fudge_factor) > max_sde_clk) {
+    DLOGV_IF(kTagResources, "Clock requirement exceeds limit!");
+    return false;
+  }
+
+  // If Primary display, reset claimed bw & clk for next cycle
+  if (display_ctx->hw_block_id == kHWPrimary) {
+    bw_claimed_ = 0.0f;
+    clk_claimed_ = 0.0f;
+  } else {
+    bw_claimed_ = display_bw;
+    clk_claimed_ = display_clk;
+  }
+
+  return true;
+}
+
+float ResManager::GetPipeBw(DisplayResourceContext *display_ctx, HWPipeInfo *pipe, float bpp) {
+  HWDisplayAttributes &display_attributes = display_ctx->display_attributes;
+  float src_w = pipe->src_roi.right - pipe->src_roi.left;
+  float src_h = pipe->src_roi.bottom - pipe->src_roi.top;
+  float dst_h = pipe->dst_roi.bottom - pipe->dst_roi.top;
+
+  // Adjust src_h with pipe decimation
+  src_h /= FLOAT(pipe->decimation);
+
+  float bw = src_w * src_h * bpp * display_attributes.fps;
+
+  // Consider panel dimension
+  // (v_total / v_active) * (v_active / dst_h)
+  bw *= FLOAT(display_attributes.v_total) / dst_h;
+
+  // Bandwidth in GBps
+  return (bw / 1000000000.0f);
+}
+
+float ResManager::GetClockForPipe(DisplayResourceContext *display_ctx, HWPipeInfo *pipe) {
+  HWDisplayAttributes &display_attributes = display_ctx->display_attributes;
+  float v_total = FLOAT(display_attributes.v_total);
+  float fps = display_attributes.fps;
+
+  float src_h = pipe->src_roi.bottom - pipe->src_roi.top;
+  float dst_h = pipe->dst_roi.bottom - pipe->dst_roi.top;
+  float dst_w = pipe->dst_roi.right - pipe->dst_roi.left;
+
+  // Adjust src_h with pipe decimation
+  src_h /= FLOAT(pipe->decimation);
+
+  // SDE Clock requirement in MHz
+  float clk = (dst_w * v_total * fps) / 1000000.0f;
+
+  // Consider down-scaling
+  if (src_h > dst_h)
+    clk *= (src_h / dst_h);
+
+  return clk;
+}
+
+float ResManager::GetOverlapBw(HWLayers *hw_layers, float *pipe_bw, bool left_mixer) {
+  uint32_t count = hw_layers->info.count;
+  float overlap_bw[count][count];
+  float overall_max = 0;
+
+  memset(overlap_bw, 0, sizeof(overlap_bw));
+
+  // Algorithm:
+  // 1.Create an 'n' by 'n' sized 2D array, overlap_bw[n][n] (n = # of layers).
+  // 2.Get overlap_bw between two layers, i and j, and account for other overlaps (prev_max) if any.
+  //   This will fill the bottom-left half of the array including diagonal (0 <= i < n, 0 <= j <= i)
+  //                      {1. pipe_bw[i],                         where i == j
+  //   overlap_bw[i][j] = {2. 0,                                  where i != j && !Overlap(i, j)
+  //                      {3. pipe_bw[i] + pipe_bw[j] + prev_max, where i != j && Overlap(i, j)
+  //
+  //   Overlap(i, j) = !(bottom_i <= top_j || top_i >= bottom_j)
+  //   prev_max = max(prev_max, overlap_bw[j, k]), where 0 <= k < j and prev_max initially 0
+  //   prev_max = prev_max ? (prev_max - pipe_bw[j]) : 0; (to account for "double counting")
+  // 3.Get the max value in 2D array, overlap_bw[n][n], for the final overall_max bandwidth.
+  //   overall_max = max(overlap_bw[i, j]), where 0 <= i < n, 0 <= j <= i
+
+  for (uint32_t i = 0; i < count; i++) {
+    HWPipeInfo &pipe1 = left_mixer ? hw_layers->config[i].left_pipe :
+                        hw_layers->config[i].right_pipe;
+
+    // Non existing pipe never overlaps
+    if (pipe_bw[i] == 0)
+      continue;
+
+    float top1 = pipe1.dst_roi.top;
+    float bottom1 = pipe1.dst_roi.bottom;
+    float row_max = 0;
+
+    for (uint32_t j = 0; j <= i; j++) {
+      HWPipeInfo &pipe2 = left_mixer ? hw_layers->config[j].left_pipe :
+                          hw_layers->config[j].right_pipe;
+
+      if ((pipe_bw[j] == 0) || (i == j)) {
+        overlap_bw[i][j] = pipe_bw[j];
+        row_max = MAX(pipe_bw[j], row_max);
+        continue;
+      }
+
+      float top2 = pipe2.dst_roi.top;
+      float bottom2 = pipe2.dst_roi.bottom;
+
+      if ((bottom1 <= top2) || (top1 >= bottom2)) {
+        overlap_bw[i][j] = 0;
+        continue;
+      }
+
+      overlap_bw[i][j] = pipe_bw[i] + pipe_bw[j];
+
+      float prev_max = 0;
+      for (uint32_t k = 0; k < j; k++) {
+        if (overlap_bw[j][k])
+          prev_max = MAX(overlap_bw[j][k], prev_max);
+      }
+      overlap_bw[i][j] += (prev_max > 0) ? (prev_max - pipe_bw[j]) : 0;
+      row_max = MAX(overlap_bw[i][j], row_max);
+    }
+
+    overall_max = MAX(row_max, overall_max);
+  }
+
+  return overall_max;
+}
+
+float ResManager::GetBpp(LayerBufferFormat format) {
+  switch (format) {
+    case kFormatARGB8888:
+    case kFormatRGBA8888:
+    case kFormatBGRA8888:
+    case kFormatXRGB8888:
+    case kFormatRGBX8888:
+    case kFormatBGRX8888:
+      return 4.0f;
+    case kFormatRGB888:
+      return 3.0f;
+    case kFormatRGB565:
+    case kFormatYCbCr422Packed:
+      return 2.0f;
+    case kFormatYCbCr420Planar:
+    case kFormatYCrCb420Planar:
+    case kFormatYCbCr420SemiPlanar:
+    case kFormatYCrCb420SemiPlanar:
+    case kFormatYCbCr420SemiPlanarVenus:
+      return 1.5f;
+    default:
+      DLOGE("GetBpp: Invalid buffer format: %x", format);
+      return 0.0f;
+  }
+}
+
 void ResManager::PostCommit(Handle display_ctx, HWLayers *hw_layers) {
+  SCOPE_LOCK(locker_);
   DisplayResourceContext *display_resource_ctx =
                           reinterpret_cast<DisplayResourceContext *>(display_ctx);
   HWBlockType hw_block_id = display_resource_ctx->hw_block_id;
   uint64_t frame_count = display_resource_ctx->frame_count;
 
-  DLOGV("Resource for hw_block=%d frame_count=%d", hw_block_id, frame_count);
+  DLOGV_IF(kTagResources, "Resource for hw_block = %d, frame_count = %d", hw_block_id, frame_count);
 
   for (uint32_t i = 0; i < num_pipe_; i++) {
-    if (src_pipes_[i].reserved) {
+    if (src_pipes_[i].reserved_hw_block == hw_block_id) {
       src_pipes_[i].hw_block_id = hw_block_id;
       src_pipes_[i].state = kPipeStateAcquired;
       src_pipes_[i].state_frame_count = frame_count;
-      DLOGV("Pipe acquired index=%d type=%d pipe_id=%x", i, src_pipes_[i].type,
-            src_pipes_[i].mdss_pipe_id);
+      DLOGV_IF(kTagResources, "Pipe acquired index = %d, type = %d, pipe_id = %x", i,
+               src_pipes_[i].type, src_pipes_[i].mdss_pipe_id);
     } else if ((src_pipes_[i].hw_block_id == hw_block_id) &&
                (src_pipes_[i].state == kPipeStateAcquired)) {
       src_pipes_[i].state = kPipeStateToRelease;
       src_pipes_[i].state_frame_count = frame_count;
-      DLOGV("Pipe to release index=%d type=%d pipe_id=%x", i, src_pipes_[i].type,
-            src_pipes_[i].mdss_pipe_id);
+      DLOGV_IF(kTagResources, "Pipe to release index = %d, type = %d, pipe_id = %x", i,
+               src_pipes_[i].type, src_pipes_[i].mdss_pipe_id);
     }
   }
 
   // handoff pipes which are used by splash screen
-  if (UNLIKELY((frame_count == 1) && (hw_block_id == kHWPrimary))) {
+  if ((frame_count == 1) && (hw_block_id == kHWPrimary)) {
     for (uint32_t i = 0; i < num_pipe_; i++) {
       if ((src_pipes_[i].state == kPipeStateOwnedByKernel)) {
         src_pipes_[i].state = kPipeStateToRelease;
@@ -311,8 +580,25 @@
       }
     }
   }
+  // set rotator pipes
+  for (uint32_t i = 0; i < hw_res_info_.num_rotator; i++) {
+    uint32_t pipe_index = rotators_[i].pipe_index;
 
-  frame_start_ = false;
+    if (IS_BIT_SET(rotators_[i].client_bit_mask, hw_block_id)) {
+      src_pipes_[pipe_index].hw_block_id = rotators_[i].writeback_id;
+      src_pipes_[pipe_index].state = kPipeStateAcquired;
+    } else if (!rotators_[i].client_bit_mask &&
+               src_pipes_[pipe_index].hw_block_id == rotators_[i].writeback_id &&
+               src_pipes_[pipe_index].state == kPipeStateAcquired) {
+      src_pipes_[pipe_index].state = kPipeStateToRelease;
+      src_pipes_[pipe_index].state_frame_count = frame_count;
+    }
+    // If no request on the rotation, release the pipe.
+    if (!rotators_[i].request_bit_mask) {
+      src_pipes_[pipe_index].dedicated_hw_block = kHWBlockMax;
+    }
+  }
+  display_resource_ctx->frame_start = false;
 }
 
 void ResManager::Purge(Handle display_ctx) {
@@ -324,11 +610,11 @@
 
   for (uint32_t i = 0; i < num_pipe_; i++) {
     if (src_pipes_[i].hw_block_id == hw_block_id)
-      src_pipes_[i].state = kPipeStateIdle;
+      src_pipes_[i].ResetState();
   }
+  ClearRotator(display_resource_ctx);
 }
 
-
 uint32_t ResManager::GetMdssPipeId(PipeType type, uint32_t index) {
   uint32_t mdss_id = kPipeIdMax;
   switch (type) {
@@ -365,34 +651,19 @@
   return (1 << mdss_id);
 }
 
-uint32_t ResManager::NextPipe(PipeType type, HWBlockType hw_block_id, bool at_right) {
-  uint32_t num_pipe = 0;
+uint32_t ResManager::SearchPipe(HWBlockType hw_block_id, SourcePipe *src_pipes,
+                                uint32_t num_pipe, bool at_right) {
   uint32_t index = kPipeIdMax;
-  SourcePipe *src_pipe = NULL;
+  SourcePipe *src_pipe;
+  HWBlockType dedicated_block;
 
-  switch (type) {
-  case kPipeTypeVIG:
-    src_pipe = vig_pipes_;
-    num_pipe = hw_res_info_.num_vig_pipe;
-    break;
-  case kPipeTypeRGB:
-    src_pipe = rgb_pipes_;
-    num_pipe = hw_res_info_.num_rgb_pipe;
-    break;
-  case kPipeTypeDMA:
-  default:
-    src_pipe = dma_pipes_;
-    num_pipe = hw_res_info_.num_dma_pipe;
-    break;
-  }
-
-  // search the pipe being used
+  // search dedicated idle pipes
   for (uint32_t i = 0; i < num_pipe; i++) {
-    if (!src_pipe[i].reserved &&
-        (src_pipe[i].state == kPipeStateAcquired) &&
-        (src_pipe[i].hw_block_id == hw_block_id) &&
-        (src_pipe[i].at_right == at_right)) {
-      index = src_pipe[i].index;
+    src_pipe = &src_pipes[i];
+    if (src_pipe->reserved_hw_block == kHWBlockMax &&
+        src_pipe->state == kPipeStateIdle &&
+        src_pipe->dedicated_hw_block == hw_block_id) {
+      index = src_pipe->index;
       break;
     }
   }
@@ -402,19 +673,63 @@
     return index;
   }
 
+  // search the pipe being used
   for (uint32_t i = 0; i < num_pipe; i++) {
-    if (!src_pipe[i].reserved &&
-        ((src_pipe[i].state == kPipeStateIdle) ||
-         ((src_pipe[i].state == kPipeStateAcquired) &&
-         (src_pipe[i].hw_block_id == hw_block_id)))) {
-      index = src_pipe[i].index;
+    src_pipe = &src_pipes[i];
+    dedicated_block = src_pipe->dedicated_hw_block;
+    if (src_pipe->reserved_hw_block == kHWBlockMax &&
+        (src_pipe->state == kPipeStateAcquired) &&
+        (src_pipe->hw_block_id == hw_block_id) &&
+        (src_pipe->at_right == at_right) &&
+        (dedicated_block == hw_block_id || dedicated_block == kHWBlockMax)) {
+      index = src_pipe->index;
       break;
     }
   }
 
+  // found
+  if (index < num_pipe_) {
+    return index;
+  }
+
+  // search the pipes idle or being used but not at the same side
+  for (uint32_t i = 0; i < num_pipe; i++) {
+    src_pipe = &src_pipes[i];
+    dedicated_block = src_pipe->dedicated_hw_block;
+    if (src_pipe->reserved_hw_block == kHWBlockMax &&
+        ((src_pipe->state == kPipeStateIdle) ||
+         (src_pipe->state == kPipeStateAcquired && src_pipe->hw_block_id == hw_block_id)) &&
+         (dedicated_block == hw_block_id || dedicated_block == kHWBlockMax)) {
+      index = src_pipe->index;
+      break;
+    }
+  }
   return index;
 }
 
+uint32_t ResManager::NextPipe(PipeType type, HWBlockType hw_block_id, bool at_right) {
+  uint32_t num_pipe = 0;
+  SourcePipe *src_pipes = NULL;
+
+  switch (type) {
+  case kPipeTypeVIG:
+    src_pipes = vig_pipes_;
+    num_pipe = hw_res_info_.num_vig_pipe;
+    break;
+  case kPipeTypeRGB:
+    src_pipes = rgb_pipes_;
+    num_pipe = hw_res_info_.num_rgb_pipe;
+    break;
+  case kPipeTypeDMA:
+  default:
+    src_pipes = dma_pipes_;
+    num_pipe = hw_res_info_.num_dma_pipe;
+    break;
+  }
+
+  return SearchPipe(hw_block_id, src_pipes, num_pipe, at_right);
+}
+
 uint32_t ResManager::GetPipe(HWBlockType hw_block_id, bool is_yuv, bool need_scale, bool at_right,
                              bool use_non_dma_pipe) {
   uint32_t index = kPipeIdMax;
@@ -427,7 +742,7 @@
       index = NextPipe(kPipeTypeDMA, hw_block_id, at_right);
     }
 
-    if ((index >= num_pipe_) && (!need_scale || hw_res_info_.has_non_scalar_rgb)) {
+    if ((index >= num_pipe_) && (!need_scale || !hw_res_info_.has_non_scalar_rgb)) {
       index = NextPipe(kPipeTypeRGB, hw_block_id, at_right);
     }
 
@@ -449,6 +764,89 @@
 
 void ResManager::AppendDump(char *buffer, uint32_t length) {
   SCOPE_LOCK(locker_);
+  AppendString(buffer, length, "\nresource manager pipe state");
+  for (uint32_t i = 0; i < num_pipe_; i++) {
+    SourcePipe *src_pipe = &src_pipes_[i];
+    AppendString(buffer, length,
+                 "\nindex = %d, id = %x, reserved = %d, state = %d, hw_block = %d, dedicated = %d",
+                 src_pipe->index, src_pipe->mdss_pipe_id, src_pipe->reserved_hw_block,
+                 src_pipe->state, src_pipe->hw_block_id, src_pipe->dedicated_hw_block);
+  }
+}
+
+DisplayError ResManager::AcquireRotator(DisplayResourceContext *display_resource_ctx,
+                                        const uint32_t rotate_count) {
+  if (rotate_count == 0)
+    return kErrorNone;
+  if (hw_res_info_.num_rotator == 0)
+    return kErrorResources;
+
+  uint32_t i, j, pipe_index, num_rotator;
+  if (rotate_count > hw_res_info_.num_rotator)
+    num_rotator = hw_res_info_.num_rotator;
+  else
+    num_rotator = rotate_count;
+
+  for (i = 0; i < num_rotator; i++) {
+    uint32_t rotate_pipe_index = rotators_[i].pipe_index;
+    SourcePipe *src_pipe = &src_pipes_[rotate_pipe_index];
+
+    if (src_pipe->dedicated_hw_block != kHWBlockMax)
+      DLOGV_IF(kTagResources, "Overwrite dedicated block %d", src_pipe->dedicated_hw_block);
+    src_pipe->dedicated_hw_block = rotators_[i].writeback_id;
+    SET_BIT(rotators_[i].request_bit_mask, display_resource_ctx->hw_block_id);
+  }
+
+  for (i = 0; i < num_rotator; i++) {
+    uint32_t rotate_pipe_index = rotators_[i].pipe_index;
+    if (src_pipes_[rotate_pipe_index].reserved_hw_block != kHWBlockMax) {
+      DLOGV_IF(kTagResources, "pipe %x is reserved by block:%d",
+               src_pipes_[rotate_pipe_index].mdss_pipe_id,
+               src_pipes_[rotate_pipe_index].reserved_hw_block);
+      return kErrorResources;
+    }
+    pipe_index = SearchPipe(rotators_[i].writeback_id, &src_pipes_[rotate_pipe_index], 1, false);
+    if (pipe_index >= num_pipe_) {
+      DLOGV_IF(kTagResources, "pipe %x is not ready for rotator",
+               src_pipes_[rotate_pipe_index].mdss_pipe_id);
+      return kErrorResources;
+    }
+  }
+
+  for (i = 0; i < num_rotator; i++)
+    SET_BIT(rotators_[i].client_bit_mask, display_resource_ctx->hw_block_id);
+
+  return kErrorNone;
+}
+
+void ResManager::AssignRotator(HWRotateInfo *rotate, uint32_t *rotate_count) {
+  if (!rotate->pipe_id)
+    return;
+  // Interleave rotator assignment
+  if ((*rotate_count & 0x1) && (hw_res_info_.num_rotator > 1)) {
+    rotate->pipe_id = src_pipes_[rotators_[1].pipe_index].mdss_pipe_id;
+    rotate->writeback_id = rotators_[1].writeback_id;
+  } else {
+    rotate->pipe_id = src_pipes_[rotators_[0].pipe_index].mdss_pipe_id;
+    rotate->writeback_id = rotators_[0].writeback_id;
+  }
+  (*rotate_count)++;
+}
+
+void ResManager::ClearRotator(DisplayResourceContext *display_resource_ctx) {
+  for (uint32_t i = 0; i < hw_res_info_.num_rotator; i++) {
+    uint32_t pipe_index;
+    pipe_index = rotators_[i].pipe_index;
+    rotators_[i].ClearState(display_resource_ctx->hw_block_id);
+    if (rotators_[i].client_bit_mask)
+      continue;
+
+    if (src_pipes_[pipe_index].hw_block_id == rotators_[i].writeback_id) {
+      src_pipes_[pipe_index].ResetState();
+    } else if (src_pipes_[pipe_index].dedicated_hw_block == rotators_[i].writeback_id) {
+      src_pipes_[pipe_index].dedicated_hw_block = kHWBlockMax;
+    }
+  }
 }
 
 }  // namespace sde
diff --git a/displayengine/libs/core/res_manager.h b/displayengine/libs/core/res_manager.h
index c4d425b..5b63299 100644
--- a/displayengine/libs/core/res_manager.h
+++ b/displayengine/libs/core/res_manager.h
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2014, The Linux Foundation. All rights reserved.
+* Copyright (c) 2014 - 2015, The Linux Foundation. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification, are permitted
 * provided that the following conditions are met:
@@ -39,7 +39,7 @@
   DisplayError Init(const HWResourceInfo &hw_res_info);
   DisplayError Deinit();
   DisplayError RegisterDisplay(DisplayType type, const HWDisplayAttributes &attributes,
-                              Handle *display_ctx);
+                               Handle *display_ctx);
   DisplayError UnregisterDisplay(Handle display_ctx);
   DisplayError Start(Handle display_ctx);
   DisplayError Stop(Handle display_ctx);
@@ -80,11 +80,12 @@
     kPipeStateOwnedByKernel,  // Pipe state when pipe is owned by kernel
   };
 
+  // todo: retrieve all these from kernel
   enum {
     kMaxSourcePipeWidth = 2048,
     kMaxInterfaceWidth = 2048,
-    kMaxCropWidth = 5,
-    kMaxCropHeight = 5,
+    kMaxRotateDownScaleRatio = 8,
+    kMaxNumRotator = 2,
   };
 
   struct SourcePipe {
@@ -96,11 +97,16 @@
     bool at_right;
     uint64_t state_frame_count;
     int priority;
-    bool reserved;
+    HWBlockType reserved_hw_block;
+    HWBlockType dedicated_hw_block;
 
-    SourcePipe() : type(kPipeTypeUnused), mdss_pipe_id(kPipeIdMax), index(0), state(kPipeStateIdle),
-                   hw_block_id(kHWBlockMax), at_right(false), state_frame_count(0), priority(0),
-                   reserved(false) { }
+    SourcePipe() : type(kPipeTypeUnused), mdss_pipe_id(kPipeIdMax), index(0),
+                   state(kPipeStateIdle), hw_block_id(kHWBlockMax), at_right(false),
+                   state_frame_count(0), priority(0), reserved_hw_block(kHWBlockMax),
+                   dedicated_hw_block(kHWBlockMax) { }
+
+    inline void ResetState() { state = kPipeStateIdle; hw_block_id = kHWBlockMax;
+        at_right = false; reserved_hw_block = kHWBlockMax; dedicated_hw_block = kHWBlockMax; }
   };
 
   struct DisplayResourceContext {
@@ -109,8 +115,10 @@
     HWBlockType hw_block_id;
     uint64_t frame_count;
     int32_t session_id;  // applicable for virtual display sessions only
-
-    DisplayResourceContext() : hw_block_id(kHWBlockMax), frame_count(0), session_id(-1) { }
+    uint32_t rotate_count;
+    bool frame_start;
+    DisplayResourceContext() : hw_block_id(kHWBlockMax), frame_count(0), session_id(-1),
+                    rotate_count(0), frame_start(false) { }
   };
 
   struct HWBlockContext {
@@ -118,19 +126,63 @@
     HWBlockContext() : is_in_use(false) { }
   };
 
+  struct HWRotator {
+    uint32_t pipe_index;
+    HWBlockType writeback_id;
+    uint32_t client_bit_mask;
+    uint32_t request_bit_mask;
+    HWRotator() : pipe_index(0), writeback_id(kHWBlockMax), client_bit_mask(0),
+                     request_bit_mask(0) { }
+
+    inline void ClearState(HWBlockType block) { CLEAR_BIT(client_bit_mask, block);
+        CLEAR_BIT(request_bit_mask, block); }
+  };
+
+  static const int kPipeIdNeedsAssignment = -1;
+
   uint32_t GetMdssPipeId(PipeType pipe_type, uint32_t index);
   uint32_t NextPipe(PipeType pipe_type, HWBlockType hw_block_id, bool at_right);
+  uint32_t SearchPipe(HWBlockType hw_block_id, SourcePipe *src_pipes, uint32_t num_pipe,
+                      bool at_right);
   uint32_t GetPipe(HWBlockType hw_block_id, bool is_yuv, bool need_scale, bool at_right,
                    bool use_non_dma_pipe);
   bool IsScalingNeeded(const HWPipeInfo *pipe_info);
-  DisplayError Config(DisplayResourceContext *display_resource_ctx, HWLayers *hw_layers);
-  bool IsValidDimension(const Layer &layer, float *width_scale, float *height_scale);
-  void CalculateCut(float *left_cut_ratio, float *top_cut_ratio, float *right_cut_ratio,
-                    float *bottom_cut_ratio, const LayerTransform &transform);
-  void CalculateCropRects(LayerRect *crop, LayerRect *dst,
-                          const LayerRect &scissor, const LayerTransform &transform);
-  bool IsNonIntegralSrcCrop(const LayerRect &crop);
-  void IntegerizeRect(LayerRect *dst_rect, const LayerRect &src_rect);
+  DisplayError Config(DisplayResourceContext *display_resource_ctx, HWLayers *hw_layers,
+                      uint32_t *rotate_count);
+  DisplayError DisplaySplitConfig(DisplayResourceContext *display_resource_ctx,
+                                  const LayerTransform &transform, const LayerRect &src_rect,
+                                  const LayerRect &dst_rect, HWLayerConfig *layer_config);
+  DisplayError ValidateScaling(const Layer &layer, const LayerRect &crop,
+                               const LayerRect &dst, float *rot_scale_x, float *rot_scale_y);
+  DisplayError SrcSplitConfig(DisplayResourceContext *display_resource_ctx,
+                              const LayerTransform &transform, const LayerRect &src_rect,
+                              const LayerRect &dst_rect, HWLayerConfig *layer_config);
+  void CalculateCut(const LayerTransform &transform, float *left_cut_ratio, float *top_cut_ratio,
+                    float *right_cut_ratio, float *bottom_cut_ratio);
+  void CalculateCropRects(const LayerRect &scissor, const LayerTransform &transform,
+                          LayerRect *crop, LayerRect *dst);
+  bool IsValidDimension(const LayerRect &src, const LayerRect &dst);
+  bool CheckBandwidth(DisplayResourceContext *display_ctx, HWLayers *hw_layers);
+  float GetPipeBw(DisplayResourceContext *display_ctx, HWPipeInfo *pipe, float bpp);
+  float GetClockForPipe(DisplayResourceContext *display_ctx, HWPipeInfo *pipe);
+  float GetOverlapBw(HWLayers *hw_layers, float *pipe_bw, bool left_mixer);
+  void SetDecimationFactor(HWPipeInfo *pipe);
+  float GetBpp(LayerBufferFormat format);
+  void SplitRect(bool flip_horizontal, const LayerRect &src_rect, const LayerRect &dst_rect,
+                 LayerRect *src_left, LayerRect *dst_left, LayerRect *src_right,
+                 LayerRect *dst_right);
+  bool IsMacroTileFormat(const LayerBuffer *buffer) { return buffer->flags.macro_tile; }
+  bool IsYuvFormat(LayerBufferFormat format) { return (format >= kFormatYCbCr420Planar); }
+  bool IsRotationNeeded(float rotation)
+         { return (UINT32(rotation) == 90 || UINT32(rotation) == 270); }
+  void LogRectVerbose(const char *prefix, const LayerRect &roi);
+  void RotationConfig(const LayerTransform &transform, const float &scale_x,
+                      const float &scale_y,LayerRect *src_rect,
+                      struct HWLayerConfig *layer_config, uint32_t *rotate_count);
+  DisplayError AcquireRotator(DisplayResourceContext *display_resource_ctx,
+                              const uint32_t roate_cnt);
+  void AssignRotator(HWRotateInfo *rotate, uint32_t *rotate_cnt);
+  void ClearRotator(DisplayResourceContext *display_resource_ctx);
 
   template <class T>
   inline void Swap(T &a, T &b) {
@@ -148,6 +200,11 @@
   SourcePipe *rgb_pipes_;
   SourcePipe *dma_pipes_;
   bool frame_start_;
+  float bw_claimed_;  // Bandwidth claimed by other display
+  float clk_claimed_;  // Clock claimed by other display
+  float last_primary_bw_;
+  uint32_t virtual_count_;
+  struct HWRotator rotators_[kMaxNumRotator];
 };
 
 }  // namespace sde
diff --git a/displayengine/libs/core/strategy_default.cpp b/displayengine/libs/core/strategy_default.cpp
index d05b9b8..e3270b7 100644
--- a/displayengine/libs/core/strategy_default.cpp
+++ b/displayengine/libs/core/strategy_default.cpp
@@ -22,23 +22,63 @@
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
-// SDE_LOG_TAG definition must precede debug.h include.
-#define SDE_LOG_TAG kTagCore
-#define SDE_MODULE_NAME "StrategyDefault"
-#include <utils/debug.h>
-
 #include <utils/constants.h>
+#include <utils/debug.h>
 
 #include "strategy_default.h"
 
+#define __CLASS__ "StrategyDefault"
+
 namespace sde {
 
-DisplayError StrategyDefault::GetNextStrategy(StrategyConstraints *constraints,
-                                              HWLayersInfo *hw_layers_info) {
+StrategyDefault::StrategyDefault() : hw_layers_info_(NULL) {
+}
+
+DisplayError StrategyDefault::CreateStrategyInterface(uint16_t version, DisplayType type,
+                                                      StrategyInterface **interface) {
+  StrategyDefault *strategy_default  = new StrategyDefault();
+
+  if (!strategy_default) {
+    return kErrorMemory;
+  }
+
+  *interface = strategy_default;
+
+  return kErrorNone;
+}
+
+DisplayError StrategyDefault::DestroyStrategyInterface(StrategyInterface *interface) {
+  StrategyDefault *strategy_default = static_cast<StrategyDefault *>(interface);
+
+  if (!strategy_default) {
+    return kErrorParameters;
+  }
+
+  delete strategy_default;
+
+  return kErrorNone;
+}
+
+DisplayError StrategyDefault::Start(HWLayersInfo *hw_layers_info, uint32_t *max_attempts) {
+  if (!hw_layers_info) {
+    return kErrorParameters;
+  }
+
+  hw_layers_info_ = hw_layers_info;
+  *max_attempts = 1;
+
+  return kErrorNone;
+}
+
+DisplayError StrategyDefault::Stop() {
+  return kErrorNone;
+}
+
+DisplayError StrategyDefault::GetNextStrategy(StrategyConstraints *constraints) {
   // Mark all layers for GPU composition. Find GPU target buffer and store its index for programming
   // the hardware.
-  LayerStack *layer_stack = hw_layers_info->stack;
-  uint32_t &hw_layer_count = hw_layers_info->count;
+  LayerStack *layer_stack = hw_layers_info_->stack;
+  uint32_t &hw_layer_count = hw_layers_info_->count;
 
   hw_layer_count = 0;
   for (uint32_t i = 0; i < layer_stack->layer_count; i++) {
@@ -46,7 +86,7 @@
     if (composition != kCompositionGPUTarget) {
       composition = kCompositionGPU;
     } else {
-      hw_layers_info->index[hw_layer_count++] = i;
+      hw_layers_info_->index[hw_layer_count++] = i;
     }
   }
 
@@ -55,8 +95,6 @@
     return kErrorParameters;
   }
 
-  hw_layers_info->flags |= kFlagGPU;
-
   return kErrorNone;
 }
 
diff --git a/displayengine/libs/core/strategy_default.h b/displayengine/libs/core/strategy_default.h
index c4e10f4..2ba19f8 100644
--- a/displayengine/libs/core/strategy_default.h
+++ b/displayengine/libs/core/strategy_default.h
@@ -32,10 +32,18 @@
 
 class StrategyDefault : public StrategyInterface {
  public:
-  virtual DisplayError GetNextStrategy(StrategyConstraints *constraints,
-                                       HWLayersInfo *hw_layers_info);
+  StrategyDefault();
+
+  static DisplayError CreateStrategyInterface(uint16_t version, DisplayType type,
+                                              StrategyInterface **interface);
+  static DisplayError DestroyStrategyInterface(StrategyInterface *interface);
+
+  virtual DisplayError Start(HWLayersInfo *hw_layers_info, uint32_t *max_attempts);
+  virtual DisplayError GetNextStrategy(StrategyConstraints *constraints);
+  virtual DisplayError Stop();
 
  private:
+  HWLayersInfo *hw_layers_info_;
 };
 
 }  // namespace sde
diff --git a/displayengine/libs/hwc/Android.mk b/displayengine/libs/hwc/Android.mk
old mode 100644
new mode 100755
index c32337a..1271e00
--- a/displayengine/libs/hwc/Android.mk
+++ b/displayengine/libs/hwc/Android.mk
@@ -1,20 +1,22 @@
 LOCAL_PATH := $(call my-dir)
-include hardware/qcom/display/displayengine/libs/common.mk
 include $(CLEAR_VARS)
 
 LOCAL_MODULE                  := hwcomposer.$(TARGET_BOARD_PLATFORM)
 LOCAL_MODULE_RELATIVE_PATH    := hw
 LOCAL_MODULE_TAGS             := optional
-LOCAL_C_INCLUDES              := $(common_includes) $(kernel_includes)
-LOCAL_CFLAGS                  := $(common_flags) -DLOG_TAG=\"HWComposer\"
-LOCAL_SHARED_LIBRARIES        := $(common_libs) libEGL libhardware_legacy \
-                                 libdl libsync \
-                                 libbinder libmedia libskia libsde
-LOCAL_ADDITIONAL_DEPENDENCIES := $(common_deps)
+LOCAL_C_INCLUDES              := hardware/qcom/display/displayengine/include/ \
+                                 hardware/qcom/display/libgralloc/ \
+                                 hardware/qcom/display/libqservice/
+LOCAL_CFLAGS                  := -Wno-missing-field-initializers -Wno-unused-parameter \
+                                 -Wconversion -Wall -Werror \
+                                 -DLOG_TAG=\"SDE\"
+LOCAL_SHARED_LIBRARIES        := libsde libqservice libbinder libhardware libhardware_legacy \
+                                 libutils libcutils
 LOCAL_SRC_FILES               := hwc_session.cpp \
                                  hwc_display.cpp \
                                  hwc_display_primary.cpp \
                                  hwc_display_external.cpp \
-                                 hwc_display_virtual.cpp
+                                 hwc_display_virtual.cpp \
+                                 hwc_logger.cpp
 
 include $(BUILD_SHARED_LIBRARY)
diff --git a/displayengine/libs/hwc/hwc_display.cpp b/displayengine/libs/hwc/hwc_display.cpp
index ce81fdd..771c07f 100644
--- a/displayengine/libs/hwc/hwc_display.cpp
+++ b/displayengine/libs/hwc/hwc_display.cpp
@@ -26,11 +26,10 @@
 #include <gralloc_priv.h>
 #include <utils/constants.h>
 
-// HWC_MODULE_NAME definition must precede hwc_logger.h include.
-#define HWC_MODULE_NAME "HWCDisplay"
+#include "hwc_display.h"
 #include "hwc_logger.h"
 
-#include "hwc_display.h"
+#define __CLASS__ "HWCDisplay"
 
 namespace sde {
 
@@ -42,7 +41,7 @@
 int HWCDisplay::Init() {
   DisplayError error = core_intf_->CreateDisplay(type_, this, &display_intf_);
   if (UNLIKELY(error != kErrorNone)) {
-    DLOGE("Display device create failed. Error = %d", error);
+    DLOGE("Display create failed. Error = %d", error);
     return -EINVAL;
   }
 
@@ -52,12 +51,12 @@
 int HWCDisplay::Deinit() {
   DisplayError error = core_intf_->DestroyDisplay(display_intf_);
   if (UNLIKELY(error != kErrorNone)) {
-    DLOGE("Display device destroy failed. Error = %d", error);
+    DLOGE("Display destroy failed. Error = %d", error);
     return -EINVAL;
   }
 
-  if (LIKELY(layer_stack_.raw)) {
-    delete[] layer_stack_.raw;
+  if (LIKELY(layer_stack_memory_.raw)) {
+    delete[] layer_stack_memory_.raw;
   }
 
   return 0;
@@ -70,23 +69,47 @@
   case HWC_EVENT_VSYNC:
     error = display_intf_->SetVSyncState(enable);
     break;
-
+  case HWC_EVENT_ORIENTATION:
+    // TODO(user): Need to handle this case
+    break;
   default:
-    DLOGE("Unsupported event control type : %d", event);
+    DLOGW("Unsupported event = %d", event);
   }
 
   if (UNLIKELY(error != kErrorNone)) {
-    DLOGE("EventControl failed. event = %d, enable = %d, error = %d", event, enable, error);
+    DLOGE("Failed. event = %d, enable = %d, error = %d", event, enable, error);
     return -EINVAL;
   }
 
   return 0;
 }
 
-int HWCDisplay::Blank(int blank) {
-  DLOGI("Blank : %d, display : %d", blank, id_);
-  DisplayState state = blank ? kStateOff : kStateOn;
-  return SetState(state);
+int HWCDisplay::SetPowerMode(int mode) {
+  DLOGI("display = %d, mode = %d", id_, mode);
+  DisplayState state = kStateOff;
+
+  switch (mode) {
+  case HWC_POWER_MODE_OFF:
+    state = kStateOff;
+    break;
+  case HWC_POWER_MODE_NORMAL:
+    state = kStateOn;
+    break;
+  case HWC_POWER_MODE_DOZE:
+  case HWC_POWER_MODE_DOZE_SUSPEND:
+    state = kStateDoze;
+    break;
+  default:
+    return -EINVAL;
+  }
+
+  DisplayError error = display_intf_->SetDisplayState(state);
+  if (UNLIKELY(error != kErrorNone)) {
+    DLOGE("Set state failed. Error = %d", error);
+    return -EINVAL;
+  }
+
+  return 0;
 }
 
 int HWCDisplay::GetDisplayConfigs(uint32_t *configs, size_t *num_configs) {
@@ -102,7 +125,7 @@
   DisplayError error = kErrorNone;
 
   DisplayConfigVariableInfo variable_config;
-  error = display_intf_->GetConfig(&variable_config, 0);
+  error = display_intf_->GetConfig(config, &variable_config);
   if (UNLIKELY(error != kErrorNone)) {
     DLOGE("GetConfig variable info failed. Error = %d", error);
     return -EINVAL;
@@ -125,8 +148,11 @@
     case HWC_DISPLAY_DPI_Y:
       values[i] = INT32(variable_config.y_dpi * 1000.0f);
       break;
+    case HWC_DISPLAY_SECURE:
+      values[i] = INT32(true);  // For backward compatibility. All Physical displays are secure
+      break;
     default:
-      DLOGE("Spurious attribute type %d", attributes[i]);
+      DLOGW("Spurious attribute type = %d", attributes[i]);
       return -EINVAL;
     }
   }
@@ -134,11 +160,26 @@
   return 0;
 }
 
-int HWCDisplay::SetState(DisplayState state) {
-  DisplayError error = display_intf_->SetDisplayState(state);
-  if (UNLIKELY(error != kErrorNone)) {
-    DLOGE("Set state failed. Error = %d", error);
-    return -EINVAL;
+int HWCDisplay::GetActiveConfig() {
+  DisplayError error = kErrorNone;
+  uint32_t index = 0;
+
+  error = display_intf_->GetActiveConfig(&index);
+  if (error != kErrorNone) {
+    DLOGE("GetActiveConfig failed. Error = %d", error);
+    return -1;
+  }
+
+  return index;
+}
+
+int HWCDisplay::SetActiveConfig(int index) {
+  DisplayError error = kErrorNone;
+
+  error = display_intf_->SetActiveConfig(index);
+  if (error != kErrorNone) {
+    DLOGE("SetActiveConfig failed. Error = %d", error);
+    return -1;
   }
 
   return 0;
@@ -161,6 +202,11 @@
 }
 
 int HWCDisplay::AllocateLayerStack(hwc_display_contents_1_t *content_list) {
+  if (!content_list || !content_list->numHwLayers) {
+    DLOGW("Invalid content list");
+    return -EINVAL;
+  }
+
   size_t num_hw_layers = content_list->numHwLayers;
 
   // Allocate memory for a) total number of layers b) buffer handle for each layer c) number of
@@ -174,27 +220,28 @@
 
   // Layer array may be large enough to hold current number of layers.
   // If not, re-allocate it now.
-  if (UNLIKELY(layer_stack_.size < required_size)) {
-    if (LIKELY(layer_stack_.raw)) {
-      delete[] layer_stack_.raw;
-      layer_stack_.size = 0;
+  if (UNLIKELY(layer_stack_memory_.size < required_size)) {
+    if (LIKELY(layer_stack_memory_.raw)) {
+      delete[] layer_stack_memory_.raw;
+      layer_stack_memory_.size = 0;
     }
 
     // Allocate in multiple of kSizeSteps.
-    required_size = ROUND_UP(required_size, layer_stack_.kSizeSteps);
+    required_size = ROUND_UP(required_size, layer_stack_memory_.kSizeSteps);
 
-    layer_stack_.raw = new uint8_t[required_size];
-    if (UNLIKELY(!layer_stack_.raw)) {
+    layer_stack_memory_.raw = new uint8_t[required_size];
+    if (UNLIKELY(!layer_stack_memory_.raw)) {
       return -ENOMEM;
     }
 
-    layer_stack_.size = required_size;
+    layer_stack_memory_.size = required_size;
   }
 
   // Assign memory addresses now.
-  uint8_t *current_address = layer_stack_.raw;
+  uint8_t *current_address = layer_stack_memory_.raw;
 
   // Layer array address
+  layer_stack_ = LayerStack();
   layer_stack_.layers = reinterpret_cast<Layer *>(current_address);
   layer_stack_.layer_count = static_cast<uint32_t>(num_hw_layers);
   current_address += num_hw_layers * sizeof(Layer);
@@ -202,19 +249,25 @@
   for (size_t i = 0; i < num_hw_layers; i++) {
     hwc_layer_1_t &hwc_layer = content_list->hwLayers[i];
     Layer &layer = layer_stack_.layers[i];
+    layer = Layer();
 
     // Layer buffer handle address
     layer.input_buffer = reinterpret_cast<LayerBuffer *>(current_address);
+    *layer.input_buffer = LayerBuffer();
     current_address += sizeof(LayerBuffer);
 
     // Visible rectangle address
     layer.visible_regions.rect = reinterpret_cast<LayerRect *>(current_address);
     layer.visible_regions.count = static_cast<uint32_t>(hwc_layer.visibleRegionScreen.numRects);
+    for (size_t i = 0; i < layer.visible_regions.count; i++) {
+      *layer.visible_regions.rect = LayerRect();
+    }
     current_address += hwc_layer.visibleRegionScreen.numRects * sizeof(LayerRect);
 
     // Dirty rectangle address
     layer.dirty_regions.rect = reinterpret_cast<LayerRect *>(current_address);
     layer.dirty_regions.count = 1;
+    *layer.dirty_regions.rect = LayerRect();
     current_address += sizeof(LayerRect);
   }
 
@@ -222,13 +275,15 @@
 }
 
 int HWCDisplay::PrepareLayerStack(hwc_display_contents_1_t *content_list) {
-  size_t num_hw_layers = content_list->numHwLayers;
-  if (UNLIKELY(num_hw_layers <= 1)) {
-    return 0;
+  if (!content_list || !content_list->numHwLayers) {
+    DLOGW("Invalid content list");
+    return -EINVAL;
   }
 
-  // Reset Layer stack flags
-  layer_stack_.flags = LayerStackFlags();
+  size_t num_hw_layers = content_list->numHwLayers;
+  if (num_hw_layers <= 1) {
+    return 0;
+  }
 
   // Configure each layer
   for (size_t i = 0; i < num_hw_layers; i++) {
@@ -239,15 +294,12 @@
     LayerBuffer *layer_buffer = layer.input_buffer;
 
     if (pvt_handle) {
-      if (UNLIKELY(SetFormat(&layer_buffer->format, pvt_handle->format))) {
+      if (SetFormat(pvt_handle->format, &layer_buffer->format)) {
         return -EINVAL;
       }
 
       layer_buffer->width = pvt_handle->width;
       layer_buffer->height = pvt_handle->height;
-      layer_buffer->planes[0].fd = pvt_handle->fd;
-      layer_buffer->planes[0].offset = pvt_handle->offset;
-      layer_buffer->planes[0].stride = pvt_handle->width;
       if (pvt_handle->bufferType == BUFFER_TYPE_VIDEO) {
         layer_stack_.flags.video_present = true;
       }
@@ -256,20 +308,20 @@
       }
     }
 
-    SetRect(&layer.dst_rect, hwc_layer.displayFrame);
-    SetRect(&layer.src_rect, hwc_layer.sourceCropf);
+    SetRect(hwc_layer.displayFrame, &layer.dst_rect);
+    SetRect(hwc_layer.sourceCropf, &layer.src_rect);
     for (size_t j = 0; j < hwc_layer.visibleRegionScreen.numRects; j++) {
-        SetRect(&layer.visible_regions.rect[j], hwc_layer.visibleRegionScreen.rects[j]);
+        SetRect(hwc_layer.visibleRegionScreen.rects[j], &layer.visible_regions.rect[j]);
     }
-    SetRect(&layer.dirty_regions.rect[0], hwc_layer.dirtyRect);
-    SetComposition(&layer.composition, hwc_layer.compositionType);
-    SetBlending(&layer.blending, hwc_layer.blending);
+    SetRect(hwc_layer.dirtyRect, &layer.dirty_regions.rect[0]);
+    SetComposition(hwc_layer.compositionType, &layer.composition);
+    SetBlending(hwc_layer.blending, &layer.blending);
 
     LayerTransform &layer_transform = layer.transform;
     uint32_t &hwc_transform = hwc_layer.transform;
     layer_transform.flip_horizontal = ((hwc_transform & HWC_TRANSFORM_FLIP_H) > 0);
     layer_transform.flip_vertical = ((hwc_transform & HWC_TRANSFORM_FLIP_V) > 0);
-    layer_transform.rotation = ((hwc_transform& HWC_TRANSFORM_ROT_90) ? 90.0f : 0.0f);
+    layer_transform.rotation = ((hwc_transform & HWC_TRANSFORM_ROT_90) ? 90.0f : 0.0f);
 
     layer.plane_alpha = hwc_layer.planeAlpha;
     layer.flags.skip = ((hwc_layer.flags & HWC_SKIP_LAYER) > 0);
@@ -294,10 +346,16 @@
   for (size_t i = 0; i < num_hw_layers; i++) {
     hwc_layer_1_t &hwc_layer = content_list->hwLayers[i];
     Layer &layer = layer_stack_.layers[i];
-    // if current frame does not need frame buffer redraw, then mark them for HWC_OVERLAY
-    LayerComposition composition = needs_fb_refresh ? layer.composition : kCompositionSDE;
-    SetComposition(&hwc_layer.compositionType, composition);
+    LayerComposition composition = layer.composition;
+
+    // If current layer does not need frame buffer redraw, then mark it as HWC_OVERLAY
+    if (!needs_fb_refresh && (composition != kCompositionGPUTarget)) {
+      composition = kCompositionSDE;
+    }
+
+    SetComposition(composition, &hwc_layer.compositionType);
   }
+
   // Cache the current layer stack information like layer_count, composition type and layer handle
   // for the future.
   CacheLayerStackInfo(content_list);
@@ -305,15 +363,65 @@
   return 0;
 }
 
-void HWCDisplay::CacheLayerStackInfo(hwc_display_contents_1_t *content_list) {
-  uint32_t layer_count = layer_stack_.layer_count;
-
-  for (size_t i = 0; i < layer_count; i++) {
-    Layer &layer = layer_stack_.layers[i];
-    layer_stack_cache_.layer_cache[i].handle = content_list->hwLayers[i].handle;
-    layer_stack_cache_.layer_cache[i].composition = layer.composition;
+int HWCDisplay::CommitLayerStack(hwc_display_contents_1_t *content_list) {
+  if (!content_list || !content_list->numHwLayers) {
+    DLOGW("Invalid content list");
+    return -EINVAL;
   }
-  layer_stack_cache_.layer_count = layer_count;
+
+  int status = 0;
+
+  size_t num_hw_layers = content_list->numHwLayers;
+  if (num_hw_layers <= 1) {
+    if (!num_hw_layers) {
+      return 0;
+    }
+
+    // TODO(user): handle if only 1 layer(fb target) is received.
+    int &acquireFenceFd = content_list->hwLayers[0].acquireFenceFd;
+    if (acquireFenceFd >= 0) {
+      close(acquireFenceFd);
+    }
+
+    return 0;
+  }
+
+  for (size_t i = 0; i < num_hw_layers; i++) {
+    hwc_layer_1_t &hwc_layer = content_list->hwLayers[i];
+    const private_handle_t *pvt_handle = static_cast<const private_handle_t *>(hwc_layer.handle);
+    LayerBuffer *layer_buffer = layer_stack_.layers[i].input_buffer;
+
+    if (pvt_handle) {
+      layer_buffer->planes[0].fd = pvt_handle->fd;
+      layer_buffer->planes[0].offset = pvt_handle->offset;
+      layer_buffer->planes[0].stride = pvt_handle->width;
+    }
+
+    layer_buffer->acquire_fence_fd = hwc_layer.acquireFenceFd;
+  }
+
+  DisplayError error = display_intf_->Commit(&layer_stack_);
+  if (UNLIKELY(error != kErrorNone)) {
+    DLOGE("Commit failed. Error = %d", error);
+    status = -EINVAL;
+  }
+
+  for (size_t i = 0; i < num_hw_layers; i++) {
+    hwc_layer_1_t &hwc_layer = content_list->hwLayers[i];
+    Layer &layer = layer_stack_.layers[i];
+    LayerBuffer *layer_buffer = layer_stack_.layers[i].input_buffer;
+
+    if ((status == 0) && (layer.composition == kCompositionSDE ||
+                         layer.composition == kCompositionGPUTarget)) {
+      hwc_layer.releaseFenceFd = layer_buffer->release_fence_fd;
+    }
+
+    if (hwc_layer.acquireFenceFd >= 0) {
+      close(hwc_layer.acquireFenceFd);
+    }
+  }
+
+  return status;
 }
 
 bool HWCDisplay::NeedsFrameBufferRefresh(hwc_display_contents_1_t *content_list) {
@@ -329,13 +437,19 @@
     return true;
   }
 
-  for (size_t i = 0; i < layer_count; i++) {
+  for (uint32_t i = 0; i < layer_count; i++) {
     hwc_layer_1_t &hwc_layer = content_list->hwLayers[i];
     Layer &layer = layer_stack_.layers[i];
     LayerCache &layer_cache = layer_stack_cache_.layer_cache[i];
+
+    if (layer.composition == kCompositionGPUTarget) {
+      continue;
+    }
+
     if (layer_cache.composition != layer.composition) {
       return true;
     }
+
     if ((layer.composition == kCompositionGPU) && (layer_cache.handle != hwc_layer.handle)) {
       return true;
     }
@@ -344,117 +458,71 @@
   return false;
 }
 
-int HWCDisplay::CommitLayerStack(hwc_display_contents_1_t *content_list) {
-  size_t num_hw_layers = content_list->numHwLayers;
-  if (UNLIKELY(num_hw_layers <= 1)) {
-    return 0;
-  }
+void HWCDisplay::CacheLayerStackInfo(hwc_display_contents_1_t *content_list) {
+  uint32_t layer_count = layer_stack_.layer_count;
 
-  for (size_t i = 0; i < num_hw_layers; i++) {
-    hwc_layer_1_t &hwc_layer = content_list->hwLayers[i];
-    LayerBuffer *layer_buffer = layer_stack_.layers[i].input_buffer;
-
-    layer_buffer->acquire_fence_fd = hwc_layer.acquireFenceFd;
-  }
-
-  DisplayError error = display_intf_->Commit(&layer_stack_);
-  if (UNLIKELY(error != kErrorNone)) {
-    DLOGE("Commit failed. Error = %d", error);
-    return -EINVAL;
-  }
-
-  for (size_t i = 0; i < num_hw_layers; i++) {
-    hwc_layer_1_t &hwc_layer = content_list->hwLayers[i];
+  for (uint32_t i = 0; i < layer_count; i++) {
     Layer &layer = layer_stack_.layers[i];
-    LayerBuffer *layer_buffer = layer_stack_.layers[i].input_buffer;
 
-    if (layer.composition == kCompositionSDE || layer.composition == kCompositionGPUTarget) {
-      hwc_layer.releaseFenceFd = layer_buffer->release_fence_fd;
+    if (layer.composition == kCompositionGPUTarget) {
+      continue;
     }
 
-    if (hwc_layer.acquireFenceFd >= 0) {
-      close(hwc_layer.acquireFenceFd);
-    }
+    layer_stack_cache_.layer_cache[i].handle = content_list->hwLayers[i].handle;
+    layer_stack_cache_.layer_cache[i].composition = layer.composition;
   }
 
-  return 0;
+  layer_stack_cache_.layer_count = layer_count;
 }
 
-void HWCDisplay::SetRect(LayerRect *target, const hwc_rect_t &source) {
+void HWCDisplay::SetRect(const hwc_rect_t &source, LayerRect *target) {
   target->left = FLOAT(source.left);
   target->top = FLOAT(source.top);
   target->right = FLOAT(source.right);
   target->bottom = FLOAT(source.bottom);
 }
 
-void HWCDisplay::SetRect(LayerRect *target, const hwc_frect_t &source) {
+void HWCDisplay::SetRect(const hwc_frect_t &source, LayerRect *target) {
   target->left = source.left;
   target->top = source.top;
   target->right = source.right;
   target->bottom = source.bottom;
 }
 
-void HWCDisplay::SetComposition(LayerComposition *target, const int32_t &source) {
+void HWCDisplay::SetComposition(const int32_t &source, LayerComposition *target) {
   switch (source) {
-  case HWC_FRAMEBUFFER_TARGET:
-    *target = kCompositionGPUTarget;
-    break;
-  default:
-    *target = kCompositionSDE;
-    break;
+  case HWC_FRAMEBUFFER_TARGET:  *target = kCompositionGPUTarget;  break;
+  default:                      *target = kCompositionSDE;        break;
   }
 }
 
-void HWCDisplay::SetComposition(int32_t *target, const LayerComposition &source) {
+void HWCDisplay::SetComposition(const int32_t &source, int32_t *target) {
   switch (source) {
-  case kCompositionGPUTarget:
-    *target = HWC_FRAMEBUFFER_TARGET;
-    break;
-  case kCompositionSDE:
-    *target = HWC_OVERLAY;
-    break;
-  default:
-    *target = HWC_FRAMEBUFFER;
-    break;
+  case kCompositionGPUTarget:   *target = HWC_FRAMEBUFFER_TARGET; break;
+  case kCompositionSDE:         *target = HWC_OVERLAY;            break;
+  default:                      *target = HWC_FRAMEBUFFER;        break;
   }
 }
 
-void HWCDisplay::SetBlending(LayerBlending *target, const int32_t &source) {
+void HWCDisplay::SetBlending(const int32_t &source, LayerBlending *target) {
   switch (source) {
-  case HWC_BLENDING_PREMULT:
-    *target = kBlendingPremultiplied;
-    break;
-  case HWC_BLENDING_COVERAGE:
-    *target = kBlendingCoverage;
-    break;
-  default:
-    *target = kBlendingNone;
-    break;
+  case HWC_BLENDING_PREMULT:    *target = kBlendingPremultiplied;   break;
+  case HWC_BLENDING_COVERAGE:   *target = kBlendingCoverage;        break;
+  default:                      *target = kBlendingNone;            break;
   }
 }
 
-int HWCDisplay::SetFormat(LayerBufferFormat *target, const int &source) {
+int HWCDisplay::SetFormat(const int32_t &source, LayerBufferFormat *target) {
   switch (source) {
-  case HAL_PIXEL_FORMAT_RGBA_8888:
-    *target = kFormatRGBA8888;
-    break;
-  case HAL_PIXEL_FORMAT_BGRA_8888:
-    *target = kFormatBGRA8888;
-    break;
-  case HAL_PIXEL_FORMAT_RGBX_8888:
-    *target = kFormatRGBX8888;
-    break;
-  case HAL_PIXEL_FORMAT_BGRX_8888:
-    *target = kFormatBGRX8888;
-    break;
-  case HAL_PIXEL_FORMAT_RGB_888:
-    *target = kFormatRGB888;
-    break;
-  case HAL_PIXEL_FORMAT_RGB_565:
-    *target = kFormatRGB565;
-    break;
+  case HAL_PIXEL_FORMAT_RGBA_8888:            *target = kFormatRGBA8888;                  break;
+  case HAL_PIXEL_FORMAT_BGRA_8888:            *target = kFormatBGRA8888;                  break;
+  case HAL_PIXEL_FORMAT_RGBX_8888:            *target = kFormatRGBX8888;                  break;
+  case HAL_PIXEL_FORMAT_BGRX_8888:            *target = kFormatBGRX8888;                  break;
+  case HAL_PIXEL_FORMAT_RGB_888:              *target = kFormatRGB888;                    break;
+  case HAL_PIXEL_FORMAT_RGB_565:              *target = kFormatRGB565;                    break;
+  case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS:   *target = kFormatYCbCr420SemiPlanarVenus;   break;
   default:
-    DLOGE("Unsupported format type %d", source);
+    DLOGW("Unsupported format type = %d", source);
     return -EINVAL;
   }
 
diff --git a/displayengine/libs/hwc/hwc_display.h b/displayengine/libs/hwc/hwc_display.h
index 67356af..0ba9ca7 100644
--- a/displayengine/libs/hwc/hwc_display.h
+++ b/displayengine/libs/hwc/hwc_display.h
@@ -37,49 +37,25 @@
   virtual int Prepare(hwc_display_contents_1_t *content_list) = 0;
   virtual int Commit(hwc_display_contents_1_t *content_list) = 0;
   virtual int EventControl(int event, int enable);
-  virtual int Blank(int blank);
+  virtual int SetPowerMode(int mode);
   virtual int GetDisplayConfigs(uint32_t *configs, size_t *num_configs);
   virtual int GetDisplayAttributes(uint32_t config, const uint32_t *attributes, int32_t *values);
-  int SetState(DisplayState state);
+  virtual int GetActiveConfig();
+  virtual int SetActiveConfig(int index);
 
  protected:
   // Maximum number of layers supported by display engine.
   static const uint32_t kMaxLayerCount = 32;
 
   // Structure to track memory allocation for layer stack (layers, rectangles) object.
-  struct LayerStackMemory : LayerStack {
-    static const size_t kSizeSteps = 4096;  // Default memory allocation.
+  struct LayerStackMemory {
+    static const size_t kSizeSteps = 1024;  // Default memory allocation.
     uint8_t *raw;  // Pointer to byte array.
     size_t size;  // Current number of allocated bytes.
 
     LayerStackMemory() : raw(NULL), size(0) { }
   };
 
-  HWCDisplay(CoreInterface *core_intf, hwc_procs_t const **hwc_procs, DisplayType type, int id);
-  virtual ~HWCDisplay() { }
-
-  // DisplayEventHandler methods
-  virtual DisplayError VSync(const DisplayEventVSync &vsync);
-  virtual DisplayError Refresh();
-
-  virtual int AllocateLayerStack(hwc_display_contents_1_t *content_list);
-  virtual int PrepareLayerStack(hwc_display_contents_1_t *content_list);
-  virtual int CommitLayerStack(hwc_display_contents_1_t *content_list);
-  inline void SetRect(LayerRect *target, const hwc_rect_t &source);
-  inline void SetRect(LayerRect *target, const hwc_frect_t &source);
-  inline void SetComposition(LayerComposition *target, const int32_t &source);
-  inline void SetComposition(int32_t *target, const LayerComposition &source);
-  inline void SetBlending(LayerBlending *target, const int32_t &source);
-  inline int SetFormat(LayerBufferFormat *target, const int &source);
-
-  LayerStackMemory layer_stack_;
-  CoreInterface *core_intf_;
-  hwc_procs_t const **hwc_procs_;
-  DisplayType type_;
-  int id_;
-  DisplayInterface *display_intf_;
-
- private:
   struct LayerCache {
     buffer_handle_t handle;
     LayerComposition composition;
@@ -94,9 +70,32 @@
     LayerStackCache() : layer_count(0) { }
   };
 
+  HWCDisplay(CoreInterface *core_intf, hwc_procs_t const **hwc_procs, DisplayType type, int id);
+  virtual ~HWCDisplay() { }
+
+  // DisplayEventHandler methods
+  virtual DisplayError VSync(const DisplayEventVSync &vsync);
+  virtual DisplayError Refresh();
+
+  virtual int AllocateLayerStack(hwc_display_contents_1_t *content_list);
+  virtual int PrepareLayerStack(hwc_display_contents_1_t *content_list);
+  virtual int CommitLayerStack(hwc_display_contents_1_t *content_list);
   bool NeedsFrameBufferRefresh(hwc_display_contents_1_t *content_list);
   void CacheLayerStackInfo(hwc_display_contents_1_t *content_list);
+  inline void SetRect(const hwc_rect_t &source, LayerRect *target);
+  inline void SetRect(const hwc_frect_t &source, LayerRect *target);
+  inline void SetComposition(const int32_t &source, LayerComposition *target);
+  inline void SetComposition(const int32_t &source, int32_t *target);
+  inline void SetBlending(const int32_t &source, LayerBlending *target);
+  inline int SetFormat(const int32_t &source, LayerBufferFormat *target);
 
+  CoreInterface *core_intf_;
+  hwc_procs_t const **hwc_procs_;
+  DisplayType type_;
+  int id_;
+  DisplayInterface *display_intf_;
+  LayerStackMemory layer_stack_memory_;
+  LayerStack layer_stack_;
   LayerStackCache layer_stack_cache_;
 };
 
diff --git a/displayengine/libs/hwc/hwc_display_external.cpp b/displayengine/libs/hwc/hwc_display_external.cpp
index 369d286..468478b 100644
--- a/displayengine/libs/hwc/hwc_display_external.cpp
+++ b/displayengine/libs/hwc/hwc_display_external.cpp
@@ -24,11 +24,10 @@
 
 #include <utils/constants.h>
 
-// HWC_MODULE_NAME definition must precede hwc_logger.h include.
-#define HWC_MODULE_NAME "HWCDisplayExternal"
+#include "hwc_display_external.h"
 #include "hwc_logger.h"
 
-#include "hwc_display_external.h"
+#define __CLASS__ "HWCDisplayExternal"
 
 namespace sde {
 
@@ -36,27 +35,51 @@
   : HWCDisplay(core_intf, hwc_procs, kHDMI, HWC_DISPLAY_EXTERNAL) {
 }
 
-int HWCDisplayExternal::Init() {
-  return 0;
-}
-
-int HWCDisplayExternal::Deinit() {
-  return 0;
-}
-
 int HWCDisplayExternal::Prepare(hwc_display_contents_1_t *content_list) {
+  int status = 0;
+
+  status = AllocateLayerStack(content_list);
+  if (status) {
+    return status;
+  }
+
+  status = PrepareLayerStack(content_list);
+  if (status) {
+    return status;
+  }
+
   return 0;
 }
 
 int HWCDisplayExternal::Commit(hwc_display_contents_1_t *content_list) {
+  int status = 0;
+
+  status = HWCDisplay::CommitLayerStack(content_list);
+  if (status) {
+    return status;
+  }
+
+  content_list->retireFenceFd = layer_stack_.retire_fence_fd;
+
   return 0;
 }
 
-int HWCDisplayExternal::PowerOn() {
-  return 0;
-}
+int HWCDisplayExternal::GetDisplayConfigs(uint32_t *configs, size_t *num_configs) {
+  uint32_t config_count = 0;
+  if (*num_configs <= 0) {
+    return -EINVAL;
+  }
 
-int HWCDisplayExternal::PowerOff() {
+  display_intf_->GetNumVariableInfoConfigs(&config_count);
+  *num_configs = static_cast<size_t>(config_count);
+  if (*num_configs <= 0) {
+    return -EINVAL;
+  }
+
+  for (uint32_t i = 0; i < config_count; i++) {
+    configs[i] = i;
+  }
+
   return 0;
 }
 
diff --git a/displayengine/libs/hwc/hwc_display_external.h b/displayengine/libs/hwc/hwc_display_external.h
index 012c653..e268621 100644
--- a/displayengine/libs/hwc/hwc_display_external.h
+++ b/displayengine/libs/hwc/hwc_display_external.h
@@ -32,12 +32,9 @@
 class HWCDisplayExternal : public HWCDisplay {
  public:
   explicit HWCDisplayExternal(CoreInterface *core_intf, hwc_procs_t const **hwc_procs);
-  virtual int Init();
-  virtual int Deinit();
   virtual int Prepare(hwc_display_contents_1_t *content_list);
   virtual int Commit(hwc_display_contents_1_t *content_list);
-  virtual int PowerOn();
-  virtual int PowerOff();
+  virtual int GetDisplayConfigs(uint32_t *configs, size_t *num_configs);
 };
 
 }  // namespace sde
diff --git a/displayengine/libs/hwc/hwc_display_primary.cpp b/displayengine/libs/hwc/hwc_display_primary.cpp
index d0c0734..b282ba6 100644
--- a/displayengine/libs/hwc/hwc_display_primary.cpp
+++ b/displayengine/libs/hwc/hwc_display_primary.cpp
@@ -24,11 +24,10 @@
 
 #include <utils/constants.h>
 
-// HWC_MODULE_NAME definition must precede hwc_logger.h include.
-#define HWC_MODULE_NAME "HWCDisplayPrimary"
+#include "hwc_display_primary.h"
 #include "hwc_logger.h"
 
-#include "hwc_display_primary.h"
+#define __CLASS__ "HWCDisplayPrimary"
 
 namespace sde {
 
@@ -36,24 +35,16 @@
   : HWCDisplay(core_intf, hwc_procs, kPrimary, HWC_DISPLAY_PRIMARY) {
 }
 
-int HWCDisplayPrimary::Init() {
-  return HWCDisplay::Init();
-}
-
-int HWCDisplayPrimary::Deinit() {
-  return HWCDisplay::Deinit();
-}
-
 int HWCDisplayPrimary::Prepare(hwc_display_contents_1_t *content_list) {
   int status = 0;
 
   status = AllocateLayerStack(content_list);
-  if (UNLIKELY(status)) {
+  if (status) {
     return status;
   }
 
   status = PrepareLayerStack(content_list);
-  if (UNLIKELY(status)) {
+  if (status) {
     return status;
   }
 
@@ -64,7 +55,7 @@
   int status = 0;
 
   status = HWCDisplay::CommitLayerStack(content_list);
-  if (UNLIKELY(status)) {
+  if (status) {
     return status;
   }
 
@@ -73,13 +64,5 @@
   return 0;
 }
 
-int HWCDisplayPrimary::PowerOn() {
-  return SetState(kStateOn);
-}
-
-int HWCDisplayPrimary::PowerOff() {
-  return SetState(kStateOff);
-}
-
 }  // namespace sde
 
diff --git a/displayengine/libs/hwc/hwc_display_primary.h b/displayengine/libs/hwc/hwc_display_primary.h
index cd8ae0f..4e9e93f 100644
--- a/displayengine/libs/hwc/hwc_display_primary.h
+++ b/displayengine/libs/hwc/hwc_display_primary.h
@@ -32,12 +32,8 @@
 class HWCDisplayPrimary : public HWCDisplay {
  public:
   explicit HWCDisplayPrimary(CoreInterface *core_intf, hwc_procs_t const **hwc_procs);
-  virtual int Init();
-  virtual int Deinit();
   virtual int Prepare(hwc_display_contents_1_t *content_list);
   virtual int Commit(hwc_display_contents_1_t *content_list);
-  virtual int PowerOn();
-  virtual int PowerOff();
 };
 
 }  // namespace sde
diff --git a/displayengine/libs/hwc/hwc_display_virtual.cpp b/displayengine/libs/hwc/hwc_display_virtual.cpp
old mode 100644
new mode 100755
index 62e4d2f..88cd073
--- a/displayengine/libs/hwc/hwc_display_virtual.cpp
+++ b/displayengine/libs/hwc/hwc_display_virtual.cpp
@@ -24,11 +24,10 @@
 
 #include <utils/constants.h>
 
-// HWC_MODULE_NAME definition must precede hwc_logger.h include.
-#define HWC_MODULE_NAME "HWCDisplayVirtual"
+#include "hwc_display_virtual.h"
 #include "hwc_logger.h"
 
-#include "hwc_display_virtual.h"
+#define __CLASS__ "HWCDisplayVirtual"
 
 namespace sde {
 
@@ -36,14 +35,6 @@
   : HWCDisplay(core_intf, hwc_procs, kVirtual, HWC_DISPLAY_VIRTUAL) {
 }
 
-int HWCDisplayVirtual::Init() {
-  return 0;
-}
-
-int HWCDisplayVirtual::Deinit() {
-  return 0;
-}
-
 int HWCDisplayVirtual::Prepare(hwc_display_contents_1_t *content_list) {
   return 0;
 }
@@ -52,13 +43,5 @@
   return 0;
 }
 
-int HWCDisplayVirtual::PowerOn() {
-  return 0;
-}
-
-int HWCDisplayVirtual::PowerOff() {
-  return 0;
-}
-
 }  // namespace sde
 
diff --git a/displayengine/libs/hwc/hwc_display_virtual.h b/displayengine/libs/hwc/hwc_display_virtual.h
index 6159425..796ed32 100644
--- a/displayengine/libs/hwc/hwc_display_virtual.h
+++ b/displayengine/libs/hwc/hwc_display_virtual.h
@@ -32,12 +32,8 @@
 class HWCDisplayVirtual : public HWCDisplay {
  public:
   explicit HWCDisplayVirtual(CoreInterface *core_intf, hwc_procs_t const **hwc_procs);
-  virtual int Init();
-  virtual int Deinit();
   virtual int Prepare(hwc_display_contents_1_t *content_list);
   virtual int Commit(hwc_display_contents_1_t *content_list);
-  virtual int PowerOn();
-  virtual int PowerOff();
 };
 
 }  // namespace sde
diff --git a/displayengine/libs/hwc/hwc_logger.cpp b/displayengine/libs/hwc/hwc_logger.cpp
new file mode 100755
index 0000000..9d65e1c
--- /dev/null
+++ b/displayengine/libs/hwc/hwc_logger.cpp
@@ -0,0 +1,87 @@
+/*
+* Copyright (c) 2014, The Linux Foundation. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without modification, are permitted
+* provided that the following conditions are met:
+*    * Redistributions of source code must retain the above copyright notice, this list of
+*      conditions and the following disclaimer.
+*    * Redistributions in binary form must reproduce the above copyright notice, this list of
+*      conditions and the following disclaimer in the documentation and/or other materials provided
+*      with the distribution.
+*    * Neither the name of The Linux Foundation nor the names of its contributors may be used to
+*      endorse or promote products derived from this software without specific prior written
+*      permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <utils/constants.h>
+
+#include "hwc_logger.h"
+
+namespace sde {
+
+HWCLogHandler HWCLogHandler::log_handler_;
+uint32_t HWCLogHandler::log_flags_ = 0x1;
+
+void HWCLogHandler::LogAll(bool enable) {
+  if (enable) {
+    log_flags_ = 0xFFFFFFFF;
+  } else {
+    log_flags_ = 0x1;   // kTagNone should always be printed.
+  }
+}
+
+void HWCLogHandler::LogResources(bool enable) {
+  if (enable) {
+    SET_BIT(log_flags_, kTagResources);
+  } else {
+    CLEAR_BIT(log_flags_, kTagResources);
+  }
+}
+
+void HWCLogHandler::LogStrategy(bool enable) {
+  if (enable) {
+    SET_BIT(log_flags_, kTagStrategy);
+  } else {
+    CLEAR_BIT(log_flags_, kTagStrategy);
+  }
+}
+
+void HWCLogHandler::Error(LogTag /*tag*/, const char *format, ...) {
+  va_list list;
+  va_start(list, format);
+  __android_log_vprint(ANDROID_LOG_ERROR, LOG_TAG, format, list);
+}
+
+void HWCLogHandler::Warning(LogTag /*tag*/, const char *format, ...) {
+  va_list list;
+  va_start(list, format);
+  __android_log_vprint(ANDROID_LOG_WARN, LOG_TAG, format, list);
+}
+
+void HWCLogHandler::Info(LogTag tag, const char *format, ...) {
+  if (IS_BIT_SET(log_flags_, tag)) {
+    va_list list;
+    va_start(list, format);
+    __android_log_vprint(ANDROID_LOG_INFO, LOG_TAG, format, list);
+  }
+}
+
+void HWCLogHandler::Verbose(LogTag tag, const char *format, ...) {
+  if (IS_BIT_SET(log_flags_, tag)) {
+    va_list list;
+    va_start(list, format);
+    __android_log_vprint(ANDROID_LOG_VERBOSE, LOG_TAG, format, list);
+  }
+}
+
+}  // namespace sde
+
diff --git a/displayengine/libs/hwc/hwc_logger.h b/displayengine/libs/hwc/hwc_logger.h
old mode 100644
new mode 100755
index cee38e9..7568990
--- a/displayengine/libs/hwc/hwc_logger.h
+++ b/displayengine/libs/hwc/hwc_logger.h
@@ -25,20 +25,36 @@
 #ifndef __HWC_LOGGER_H__
 #define __HWC_LOGGER_H__
 
+#include <core/sde_types.h>
 #include <cutils/log.h>
 
-#ifndef HWC_MODULE_NAME
-#define HWC_MODULE_NAME "HWComposer"
-#endif
+#define DLOG(Macro, format, ...) Macro(__CLASS__ "::%s: " format, __FUNCTION__, ##__VA_ARGS__)
 
-#define HWC_LOG(Macro, format, ...) Macro(HWC_MODULE_NAME ": " format, ##__VA_ARGS__)
+#define DLOGE(format, ...) DLOG(ALOGE, format, ##__VA_ARGS__)
+#define DLOGW(format, ...) DLOG(ALOGW, format, ##__VA_ARGS__)
+#define DLOGI(format, ...) DLOG(ALOGI, format, ##__VA_ARGS__)
+#define DLOGV(format, ...) DLOG(ALOGV, format, ##__VA_ARGS__)
 
-// HWC_MODULE_NAME must be defined before #include this header file in respective
-// module, else default definition is used.
-#define DLOGE(format, ...) HWC_LOG(ALOGE, format, ##__VA_ARGS__)
-#define DLOGW(format, ...) HWC_LOG(ALOGW, format, ##__VA_ARGS__)
-#define DLOGI(format, ...) HWC_LOG(ALOGI, format, ##__VA_ARGS__)
-#define DLOGV(format, ...) HWC_LOG(ALOGV, format, ##__VA_ARGS__)
+namespace sde {
+
+class HWCLogHandler : public LogHandler {
+ public:
+  static inline LogHandler* Get() { return &log_handler_; }
+  static void LogAll(bool enable);
+  static void LogResources(bool enable);
+  static void LogStrategy(bool enable);
+
+  virtual void Error(LogTag tag, const char *format, ...);
+  virtual void Warning(LogTag tag, const char *format, ...);
+  virtual void Info(LogTag tag, const char *format, ...);
+  virtual void Verbose(LogTag tag, const char *format, ...);
+
+ private:
+  static HWCLogHandler log_handler_;
+  static uint32_t log_flags_;
+};
+
+}  // namespace sde
 
 #endif  // __HWC_LOGGER_H__
 
diff --git a/displayengine/libs/hwc/hwc_session.cpp b/displayengine/libs/hwc/hwc_session.cpp
index 9749fb1..3f99a23 100644
--- a/displayengine/libs/hwc/hwc_session.cpp
+++ b/displayengine/libs/hwc/hwc_session.cpp
@@ -24,12 +24,17 @@
 
 #include <core/dump_interface.h>
 #include <utils/constants.h>
-
-// HWC_MODULE_NAME definition must precede hwc_logger.h include.
-#define HWC_MODULE_NAME "HWCSession"
-#include "hwc_logger.h"
+#include <utils/String16.h>
+#include <hardware_legacy/uevent.h>
+#include <sys/resource.h>
+#include <sys/prctl.h>
+#include <binder/Parcel.h>
+#include <QService.h>
 
 #include "hwc_session.h"
+#include "hwc_logger.h"
+
+#define __CLASS__ "HWCSession"
 
 static sde::HWCSession::HWCModuleMethods g_hwc_module_methods;
 
@@ -51,60 +56,87 @@
 
 Locker HWCSession::locker_;
 
-HWCSession::HWCSession(const hw_module_t *module) : core_intf_(NULL), hwc_procs_(NULL) {
+HWCSession::HWCSession(const hw_module_t *module) : core_intf_(NULL), hwc_procs_(NULL),
+            display_primary_(NULL), display_external_(NULL), hotplug_thread_exit_(false),
+            hotplug_thread_name_("HWC_HotPlugThread") {
   hwc_composer_device_1_t::common.tag = HARDWARE_DEVICE_TAG;
-  hwc_composer_device_1_t::common.version = HWC_DEVICE_API_VERSION_1_3;
+  hwc_composer_device_1_t::common.version = HWC_DEVICE_API_VERSION_1_4;
   hwc_composer_device_1_t::common.module = const_cast<hw_module_t*>(module);
   hwc_composer_device_1_t::common.close = Close;
   hwc_composer_device_1_t::prepare = Prepare;
   hwc_composer_device_1_t::set = Set;
   hwc_composer_device_1_t::eventControl = EventControl;
-  hwc_composer_device_1_t::blank = Blank;
+  hwc_composer_device_1_t::setPowerMode = SetPowerMode;
   hwc_composer_device_1_t::query = Query;
   hwc_composer_device_1_t::registerProcs = RegisterProcs;
   hwc_composer_device_1_t::dump = Dump;
   hwc_composer_device_1_t::getDisplayConfigs = GetDisplayConfigs;
   hwc_composer_device_1_t::getDisplayAttributes = GetDisplayAttributes;
+  hwc_composer_device_1_t::getActiveConfig = GetActiveConfig;
+  hwc_composer_device_1_t::setActiveConfig = SetActiveConfig;
 }
 
 int HWCSession::Init() {
-  DisplayError error = CoreInterface::CreateCore(this, &core_intf_);
-  if (UNLIKELY(error != kErrorNone)) {
+  int status = -EINVAL;
+  const char *qservice_name = "display.qservice";
+
+  // Start QService and connect to it.
+  qService::QService::init();
+  android::sp<qService::IQService> qservice = android::interface_cast<qService::IQService>(
+                android::defaultServiceManager()->getService(android::String16(qservice_name)));
+
+  if (qservice.get()) {
+    qservice->connect(this);
+  } else {
+    DLOGE("Failed to acquire %s", qservice_name);
+    return -EINVAL;
+  }
+
+  DisplayError error = CoreInterface::CreateCore(this, HWCLogHandler::Get(), &core_intf_);
+  if (error != kErrorNone) {
     DLOGE("Display core initialization failed. Error = %d", error);
     return -EINVAL;
   }
 
-  int status = -EINVAL;
-
   // Create and power on primary display
   display_primary_ = new HWCDisplayPrimary(core_intf_, &hwc_procs_);
-  if (UNLIKELY(!display_primary_)) {
+  if (!display_primary_) {
     CoreInterface::DestroyCore();
     return -ENOMEM;
   }
 
   status = display_primary_->Init();
-  if (UNLIKELY(status)) {
+  if (status) {
     CoreInterface::DestroyCore();
     delete display_primary_;
     return status;
   }
 
-  status = display_primary_->PowerOn();
-  if (UNLIKELY(status)) {
-    CoreInterface::DestroyCore();
+  status = display_primary_->SetPowerMode(HWC_POWER_MODE_NORMAL);
+  if (status) {
     display_primary_->Deinit();
     delete display_primary_;
+    CoreInterface::DestroyCore();
     return status;
   }
 
+  if (pthread_create(&hotplug_thread_, NULL, &HWCHotPlugThread, this) < 0) {
+    DLOGE("Failed to start = %s, error = %s HDMI display Not supported", hotplug_thread_name_);
+    display_primary_->Deinit();
+    delete display_primary_;
+    CoreInterface::DestroyCore();
+    return -errno;
+  }
+
   return 0;
 }
 
 int HWCSession::Deinit() {
-  display_primary_->PowerOff();
+  display_primary_->SetPowerMode(HWC_POWER_MODE_OFF);
   display_primary_->Deinit();
   delete display_primary_;
+  hotplug_thread_exit_ = true;
+  pthread_join(hotplug_thread_, NULL);
 
   DisplayError error = CoreInterface::DestroyCore();
   if (error != kErrorNone) {
@@ -115,19 +147,19 @@
 }
 
 int HWCSession::Open(const hw_module_t *module, const char *name, hw_device_t **device) {
-  if (UNLIKELY(!module || !name || !device)) {
-    DLOGE("::%s Invalid parameters.", __FUNCTION__);
+  if (!module || !name || !device) {
+    DLOGE("Invalid parameters.");
     return -EINVAL;
   }
 
-  if (LIKELY(!strcmp(name, HWC_HARDWARE_COMPOSER))) {
+  if (!strcmp(name, HWC_HARDWARE_COMPOSER)) {
     HWCSession *hwc_session = new HWCSession(module);
-    if (UNLIKELY(!hwc_session)) {
+    if (!hwc_session) {
       return -ENOMEM;
     }
 
     int status = hwc_session->Init();
-    if (UNLIKELY(status != 0)) {
+    if (status != 0) {
       delete hwc_session;
       return status;
     }
@@ -140,7 +172,7 @@
 }
 
 int HWCSession::Close(hw_device_t *device) {
-  if (UNLIKELY(!device)) {
+  if (!device) {
     return -EINVAL;
   }
 
@@ -157,74 +189,72 @@
                         hwc_display_contents_1_t **displays) {
   SCOPE_LOCK(locker_);
 
-  if (UNLIKELY(!device || !displays)) {
+  if (!device || !displays) {
     return -EINVAL;
   }
 
   HWCSession *hwc_session = static_cast<HWCSession *>(device);
-  int status = -EINVAL;
 
-  for (size_t i = 0; i < num_displays; i++) {
+  for (ssize_t i = (num_displays-1); i >= 0; i--) {
     hwc_display_contents_1_t *content_list = displays[i];
-    if (UNLIKELY(!content_list || !content_list->numHwLayers)) {
-      DLOGE("::%s Invalid content list.", __FUNCTION__);
-      return -EINVAL;
-    }
 
     switch (i) {
     case HWC_DISPLAY_PRIMARY:
-      status = hwc_session->display_primary_->Prepare(content_list);
+      hwc_session->display_primary_->Prepare(content_list);
+      break;
+    case HWC_DISPLAY_EXTERNAL:
+      if (hwc_session->display_external_) {
+        hwc_session->display_external_->Prepare(content_list);
+      }
+      break;
+    case HWC_DISPLAY_VIRTUAL:
       break;
     default:
-      status = -EINVAL;
-    }
-
-    if (UNLIKELY(!status)) {
       break;
     }
   }
 
-  return status;
+  // Return 0, else client will go into bad state
+  return 0;
 }
 
 int HWCSession::Set(hwc_composer_device_1 *device, size_t num_displays,
                     hwc_display_contents_1_t **displays) {
   SCOPE_LOCK(locker_);
 
-  if (UNLIKELY(!device || !displays)) {
+  if (!device || !displays) {
     return -EINVAL;
   }
 
   HWCSession *hwc_session = static_cast<HWCSession *>(device);
-  int status = -EINVAL;
 
   for (size_t i = 0; i < num_displays; i++) {
     hwc_display_contents_1_t *content_list = displays[i];
-    if (UNLIKELY(!content_list || !content_list->numHwLayers)) {
-      DLOGE("::%s Invalid content list.", __FUNCTION__);
-      return -EINVAL;
-    }
 
     switch (i) {
     case HWC_DISPLAY_PRIMARY:
-      status = hwc_session->display_primary_->Commit(content_list);
+      hwc_session->display_primary_->Commit(content_list);
+      break;
+    case HWC_DISPLAY_EXTERNAL:
+      if (hwc_session->display_external_) {
+        hwc_session->display_external_->Commit(content_list);
+      }
+      break;
+    case HWC_DISPLAY_VIRTUAL:
       break;
     default:
-      status = -EINVAL;
-    }
-
-    if (UNLIKELY(!status)) {
       break;
     }
   }
 
-  return status;
+  // Return 0, else client will go into bad state
+  return 0;
 }
 
 int HWCSession::EventControl(hwc_composer_device_1 *device, int disp, int event, int enable) {
   SCOPE_LOCK(locker_);
 
-  if (UNLIKELY(!device)) {
+  if (!device) {
     return -EINVAL;
   }
 
@@ -235,17 +265,22 @@
   case HWC_DISPLAY_PRIMARY:
     status = hwc_session->display_primary_->EventControl(event, enable);
     break;
+  case HWC_DISPLAY_EXTERNAL:
+    if (hwc_session->display_external_) {
+      status = hwc_session->display_external_->EventControl(event, enable);
+    }
+    break;
   default:
     status = -EINVAL;
   }
 
-  return 0;
+  return status;
 }
 
-int HWCSession::Blank(hwc_composer_device_1 *device, int disp, int blank) {
+int HWCSession::SetPowerMode(hwc_composer_device_1 *device, int disp, int mode) {
   SCOPE_LOCK(locker_);
 
-  if (UNLIKELY(!device)) {
+  if (!device) {
     return -EINVAL;
   }
 
@@ -254,7 +289,12 @@
 
   switch (disp) {
   case HWC_DISPLAY_PRIMARY:
-    status = hwc_session->display_primary_->Blank(blank);
+    status = hwc_session->display_primary_->SetPowerMode(mode);
+    break;
+  case HWC_DISPLAY_EXTERNAL:
+    if (hwc_session->display_external_) {
+      status = hwc_session->display_external_->SetPowerMode(mode);
+    }
     break;
   default:
     status = -EINVAL;
@@ -264,7 +304,7 @@
 }
 
 int HWCSession::Query(hwc_composer_device_1 *device, int param, int *value) {
-  if (UNLIKELY(!device || !value)) {
+  if (!device || !value) {
     return -EINVAL;
   }
 
@@ -272,7 +312,7 @@
 }
 
 void HWCSession::RegisterProcs(hwc_composer_device_1 *device, hwc_procs_t const *procs) {
-  if (UNLIKELY(!device || !procs)) {
+  if (!device || !procs) {
     return;
   }
 
@@ -283,7 +323,7 @@
 void HWCSession::Dump(hwc_composer_device_1 *device, char *buffer, int length) {
   SCOPE_LOCK(locker_);
 
-  if (UNLIKELY(!device || !buffer || !length)) {
+  if (!device || !buffer || !length) {
     return;
   }
 
@@ -292,7 +332,7 @@
 
 int HWCSession::GetDisplayConfigs(hwc_composer_device_1 *device, int disp, uint32_t *configs,
                                   size_t *num_configs) {
-  if (UNLIKELY(!device || !configs || !num_configs)) {
+  if (!device || !configs || !num_configs) {
     return -EINVAL;
   }
 
@@ -303,6 +343,11 @@
   case HWC_DISPLAY_PRIMARY:
     status = hwc_session->display_primary_->GetDisplayConfigs(configs, num_configs);
     break;
+  case HWC_DISPLAY_EXTERNAL:
+    if (hwc_session->display_external_) {
+      status = hwc_session->display_external_->GetDisplayConfigs(configs, num_configs);
+    }
+    break;
   default:
     status = -EINVAL;
   }
@@ -312,7 +357,7 @@
 
 int HWCSession::GetDisplayAttributes(hwc_composer_device_1 *device, int disp, uint32_t config,
                                      const uint32_t *attributes, int32_t *values) {
-  if (UNLIKELY(!device || !attributes || !values)) {
+  if (!device || !attributes || !values) {
     return -EINVAL;
   }
 
@@ -323,6 +368,60 @@
   case HWC_DISPLAY_PRIMARY:
     status = hwc_session->display_primary_->GetDisplayAttributes(config, attributes, values);
     break;
+  case HWC_DISPLAY_EXTERNAL:
+    if (hwc_session->display_external_) {
+      status = hwc_session->display_external_->GetDisplayAttributes(config, attributes, values);
+    }
+    break;
+  default:
+    status = -EINVAL;
+  }
+
+  return status;
+}
+
+int HWCSession::GetActiveConfig(hwc_composer_device_1 *device, int disp) {
+  if (!device) {
+    return -1;
+  }
+
+  HWCSession *hwc_session = static_cast<HWCSession *>(device);
+  int active_config = -1;
+
+  switch (disp) {
+  case HWC_DISPLAY_PRIMARY:
+    active_config = hwc_session->display_primary_->GetActiveConfig();
+    break;
+  case HWC_DISPLAY_EXTERNAL:
+    if (hwc_session->display_external_) {
+      active_config = hwc_session->display_external_->GetActiveConfig();
+    }
+    break;
+  default:
+    active_config = -1;
+  }
+
+  return active_config;
+}
+
+int HWCSession::SetActiveConfig(hwc_composer_device_1 *device, int disp, int index) {
+  if (!device) {
+    return -EINVAL;
+  }
+
+  HWCSession *hwc_session = static_cast<HWCSession *>(device);
+  int status = -EINVAL;
+
+  switch (disp) {
+  case HWC_DISPLAY_PRIMARY:
+    status = hwc_session->display_primary_->SetActiveConfig(index);
+    break;
+  case HWC_DISPLAY_EXTERNAL:
+    if (hwc_session->display_external_) {
+      // TODO(user): Uncomment it. HDMI does not support resolution change currently.
+      status = 0;  // hwc_session->display_external_->SetActiveConfig(index);
+    }
+    break;
   default:
     status = -EINVAL;
   }
@@ -334,5 +433,141 @@
   return kErrorNone;
 }
 
+android::status_t HWCSession::notifyCallback(uint32_t command, const android::Parcel *input_parcel,
+                                             android::Parcel */*output_parcel*/) {
+  switch (command) {
+  case qService::IQService::DYNAMIC_DEBUG:
+    DynamicDebug(input_parcel);
+    break;
+
+  case qService::IQService::SCREEN_REFRESH:
+    hwc_procs_->invalidate(hwc_procs_);
+    break;
+
+  default:
+    DLOGW("QService command = %d is not supported", command);
+    return -EINVAL;
+  }
+
+  return 0;
+}
+
+void HWCSession::DynamicDebug(const android::Parcel *input_parcel) {
+  int type = input_parcel->readInt32();
+  bool enable = (input_parcel->readInt32() > 0);
+  DLOGI("type = %d enable = %d", type, enable);
+
+  switch (type) {
+  case qService::IQService::DEBUG_ALL:
+    HWCLogHandler::LogAll(enable);
+    break;
+
+  case qService::IQService::DEBUG_MDPCOMP:
+    HWCLogHandler::LogStrategy(enable);
+    break;
+
+  case qService::IQService::DEBUG_PIPE_LIFECYCLE:
+    HWCLogHandler::LogResources(enable);
+    break;
+
+  default:
+    DLOGW("type = %d is not supported", type);
+  }
+}
+void* HWCSession::HWCHotPlugThread(void *context) {
+  if (context) {
+    return reinterpret_cast<HWCSession *>(context)->HWCHotPlugThreadHandler();
+  }
+
+  return NULL;
+}
+
+void* HWCSession::HWCHotPlugThreadHandler() {
+  static char uevent_data[PAGE_SIZE];
+  int length = 0;
+  prctl(PR_SET_NAME, hotplug_thread_name_, 0, 0, 0);
+  setpriority(PRIO_PROCESS, 0, HAL_PRIORITY_URGENT_DISPLAY);
+  if (!uevent_init()) {
+    DLOGE("Failed to init uevent");
+    pthread_exit(0);
+    return NULL;
+  }
+
+  while (!hotplug_thread_exit_) {
+    // keep last 2 zeroes to ensure double 0 termination
+    length = uevent_next_event(uevent_data, INT32(sizeof(uevent_data)) - 2);
+
+    if (!strcasestr("change@/devices/virtual/switch/hdmi", uevent_data)) {
+      continue;
+    }
+    DLOGI("Uevent HDMI = %s", uevent_data);
+    int connected = GetHDMIConnectedState(uevent_data, length);
+    if (connected >= 0) {
+      DLOGI("HDMI = %s", connected ? "connected" : "disconnected");
+      if (HotPlugHandler(connected) == -1) {
+        DLOGE("Failed handling Hotplug = %s", connected ? "connected" : "disconnected");
+      }
+    }
+  }
+  pthread_exit(0);
+
+  return NULL;
+}
+
+int HWCSession::GetHDMIConnectedState(const char *uevent_data, int length) {
+  const char* iterator_str = uevent_data;
+  while (((iterator_str - uevent_data) <= length) && (*iterator_str)) {
+    char* pstr = strstr(iterator_str, "SWITCH_STATE=");
+    if (pstr != NULL) {
+      return (atoi(iterator_str + strlen("SWITCH_STATE=")));
+    }
+    iterator_str += strlen(iterator_str) + 1;
+  }
+  return -1;
+}
+
+
+int HWCSession::HotPlugHandler(bool connected) {
+  if (!hwc_procs_) {
+     DLOGW("Ignore hotplug - hwc_proc not registered");
+    return -1;
+  }
+
+  if (connected) {
+    SCOPE_LOCK(locker_);
+    if (display_external_) {
+     DLOGE("HDMI already connected");
+     return -1;
+    }
+    // Create hdmi display
+    display_external_ = new HWCDisplayExternal(core_intf_, &hwc_procs_);
+    if (!display_external_) {
+      return -1;
+    }
+    int status = display_external_->Init();
+    if (status) {
+      delete display_external_;
+      display_external_ = NULL;
+      return -1;
+    }
+  } else {
+    SCOPE_LOCK(locker_);
+    if (!display_external_) {
+     DLOGE("HDMI not connected");
+     return -1;
+    }
+    display_external_->SetPowerMode(HWC_POWER_MODE_OFF);
+    display_external_->Deinit();
+    delete display_external_;
+    display_external_ = NULL;
+  }
+
+  // notify client and trigger a screen refresh
+  hwc_procs_->hotplug(hwc_procs_, HWC_DISPLAY_EXTERNAL, connected);
+  hwc_procs_->invalidate(hwc_procs_);
+
+  return 0;
+}
+
 }  // namespace sde
 
diff --git a/displayengine/libs/hwc/hwc_session.h b/displayengine/libs/hwc/hwc_session.h
index 6b3346b..488da9d 100644
--- a/displayengine/libs/hwc/hwc_session.h
+++ b/displayengine/libs/hwc/hwc_session.h
@@ -28,12 +28,14 @@
 #include <hardware/hwcomposer.h>
 #include <core/core_interface.h>
 #include <utils/locker.h>
+#include <IQClient.h>
 
 #include "hwc_display_primary.h"
+#include "hwc_display_external.h"
 
 namespace sde {
 
-class HWCSession : public hwc_composer_device_1_t, public CoreEventHandler {
+class HWCSession : hwc_composer_device_1_t, CoreEventHandler, public qClient::BnQClient {
  public:
   struct HWCModuleMethods : public hw_module_methods_t {
     HWCModuleMethods() {
@@ -54,7 +56,7 @@
   static int Set(hwc_composer_device_1 *device, size_t num_displays,
                  hwc_display_contents_1_t **displays);
   static int EventControl(hwc_composer_device_1 *device, int disp, int event, int enable);
-  static int Blank(hwc_composer_device_1 *device, int disp, int blank);
+  static int SetPowerMode(hwc_composer_device_1 *device, int disp, int mode);
   static int Query(hwc_composer_device_1 *device, int param, int *value);
   static void RegisterProcs(hwc_composer_device_1 *device, hwc_procs_t const *procs);
   static void Dump(hwc_composer_device_1 *device, char *buffer, int length);
@@ -62,14 +64,31 @@
                                size_t *numConfigs);
   static int GetDisplayAttributes(hwc_composer_device_1 *device, int disp, uint32_t config,
                                   const uint32_t *attributes, int32_t *values);
+  static int GetActiveConfig(hwc_composer_device_1 *device, int disp);
+  static int SetActiveConfig(hwc_composer_device_1 *device, int disp, int index);
+
+  // Hotplug thread for HDMI connect/disconnect
+  static void* HWCHotPlugThread(void *context);
+  void* HWCHotPlugThreadHandler();
+  int GetHDMIConnectedState(const char *uevent_data, int length);
+  int HotPlugHandler(bool connected);
 
   // CoreEventHandler methods
   virtual DisplayError Hotplug(const CoreEventHotplug &hotplug);
 
+  // QClient methods
+  virtual android::status_t notifyCallback(uint32_t command, const android::Parcel *input_parcel,
+                                           android::Parcel *output_parcel);
+  void DynamicDebug(const android::Parcel *input_parcel);
+
   static Locker locker_;
   CoreInterface *core_intf_;
   hwc_procs_t const *hwc_procs_;
   HWCDisplayPrimary *display_primary_;
+  HWCDisplayExternal *display_external_;
+  pthread_t hotplug_thread_;
+  bool hotplug_thread_exit_;
+  const char *hotplug_thread_name_;
 };
 
 }  // namespace sde
diff --git a/displayengine/libs/utils/Android.mk b/displayengine/libs/utils/Android.mk
index d5ba512..db97dd5 100644
--- a/displayengine/libs/utils/Android.mk
+++ b/displayengine/libs/utils/Android.mk
@@ -1,13 +1,13 @@
 LOCAL_PATH := $(call my-dir)
-include hardware/qcom/display/displayengine/libs/common.mk
 include $(CLEAR_VARS)
 
 LOCAL_MODULE                  := libsdeutils
 LOCAL_MODULE_TAGS             := optional
-LOCAL_C_INCLUDES              := $(common_includes) $(kernel_includes)
-LOCAL_CFLAGS                  := $(common_flags) -DLOG_TAG=\"SDE\"
-LOCAL_SHARED_LIBRARIES        := $(common_libs)
-LOCAL_ADDITIONAL_DEPENDENCIES := $(common_deps)
+LOCAL_C_INCLUDES              := hardware/qcom/display/displayengine/include/
+LOCAL_CFLAGS                  := -Wno-missing-field-initializers -Wno-unused-parameter \
+                                 -Wconversion -Wall -Werror \
+                                 -DLOG_TAG=\"SDE\"
+LOCAL_SHARED_LIBRARIES        := libcutils
 LOCAL_SRC_FILES               := debug_android.cpp
 
 include $(BUILD_SHARED_LIBRARY)
diff --git a/displayengine/libs/utils/debug_android.cpp b/displayengine/libs/utils/debug_android.cpp
old mode 100644
new mode 100755
index 09b32fe..31bd40b
--- a/displayengine/libs/utils/debug_android.cpp
+++ b/displayengine/libs/utils/debug_android.cpp
@@ -31,35 +31,29 @@
 
 Debug Debug::debug_;
 
-Debug::Debug() : virtual_driver_(false) {
+Debug::Debug() : log_handler_(&default_log_handler_), virtual_driver_(false) {
   char property[PROPERTY_VALUE_MAX];
   if (property_get("displaycore.virtualdriver", property, NULL) > 0) {
     virtual_driver_ = (atoi(property) == 1);
   }
 }
 
-void Debug::Error(const LogTag & /*tag*/, const char *format, ...) {
-  va_list list;
-  va_start(list, format);
-  __android_log_vprint(ANDROID_LOG_ERROR, LOG_TAG, format, list);
+uint32_t Debug::GetSimulationFlag() {
+  char property[PROPERTY_VALUE_MAX];
+  if (property_get("debug.hwc.simulate", property, NULL) > 0) {
+    return atoi(property);
+  }
+
+  return 0;
 }
 
-void Debug::Warning(const LogTag & /*tag*/, const char *format, ...) {
-  va_list list;
-  va_start(list, format);
-  __android_log_vprint(ANDROID_LOG_WARN, LOG_TAG, format, list);
-}
+uint32_t Debug::GetHDMIResolution() {
+  char property[PROPERTY_VALUE_MAX];
+  if (property_get("hw.hdmi.resolution", property, NULL) > 0) {
+    return atoi(property);
+  }
 
-void Debug::Info(const LogTag & /*tag*/, const char *format, ...) {
-  va_list list;
-  va_start(list, format);
-  __android_log_vprint(ANDROID_LOG_INFO, LOG_TAG, format, list);
-}
-
-void Debug::Verbose(const LogTag & /*tag*/, const char *format, ...) {
-  va_list list;
-  va_start(list, format);
-  __android_log_vprint(ANDROID_LOG_VERBOSE, LOG_TAG, format, list);
+  return 0;
 }
 
 }  // namespace sde
diff --git a/libcopybit/copybit.cpp b/libcopybit/copybit.cpp
index da18c7b..e4624e0 100644
--- a/libcopybit/copybit.cpp
+++ b/libcopybit/copybit.cpp
@@ -505,7 +505,8 @@
             int flags = 0;
 
             private_handle_t* src_hnd = (private_handle_t*)src->handle;
-            if(src_hnd != NULL && src_hnd->flags & private_handle_t::PRIV_FLAGS_DO_NOT_FLUSH) {
+            if(src_hnd != NULL &&
+                (!(src_hnd->flags & private_handle_t::PRIV_FLAGS_CACHED))) {
                 flags |=  MDP_BLIT_NON_CACHED;
             }
 
diff --git a/libcopybit/copybit.h b/libcopybit/copybit.h
index 9a6de9b..6428023 100644
--- a/libcopybit/copybit.h
+++ b/libcopybit/copybit.h
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2008 The Android Open Source Project
- * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2015, The Linux Foundation. All rights reserved.
  *
  * Not a Contribution, Apache license notifications and license are retained
  * for attribution purposes only.
@@ -26,6 +26,7 @@
 #include <stdint.h>
 #include <sys/cdefs.h>
 #include <sys/types.h>
+#include <gralloc_priv.h>
 
 __BEGIN_DECLS
 
diff --git a/libcopybit/copybit_c2d.cpp b/libcopybit/copybit_c2d.cpp
index 23daa27..3807f33 100644
--- a/libcopybit/copybit_c2d.cpp
+++ b/libcopybit/copybit_c2d.cpp
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2008 The Android Open Source Project
- * Copyright (c) 2010-2014, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2010-2015, The Linux Foundation. All rights reserved.
  *
  * Not a Contribution, Apache license notifications and license are retained
  * for attribution purposes only.
@@ -35,7 +35,6 @@
 
 #include <EGL/eglplatform.h>
 #include <cutils/native_handle.h>
-#include <gralloc_priv.h>
 
 #include <copybit.h>
 #include <alloc_controller.h>
diff --git a/libgralloc/alloc_controller.cpp b/libgralloc/alloc_controller.cpp
index 4167ae2..596ca77 100644
--- a/libgralloc/alloc_controller.cpp
+++ b/libgralloc/alloc_controller.cpp
@@ -76,6 +76,21 @@
     return true;
 }
 
+/* The default policy is to return cached buffers unless the client explicity
+ * sets the PRIVATE_UNCACHED flag or indicates that the buffer will be rarely
+ * read or written in software. Any combination with a _RARELY_ flag will be
+ * treated as uncached. */
+static bool useUncached(const int& usage) {
+    if((usage & GRALLOC_USAGE_PRIVATE_UNCACHED) or
+            ((usage & GRALLOC_USAGE_SW_WRITE_MASK) ==
+            GRALLOC_USAGE_SW_WRITE_RARELY) or
+            ((usage & GRALLOC_USAGE_SW_READ_MASK) ==
+            GRALLOC_USAGE_SW_READ_RARELY))
+        return true;
+
+    return false;
+}
+
 //-------------- AdrenoMemInfo-----------------------//
 AdrenoMemInfo::AdrenoMemInfo()
 {
@@ -279,9 +294,6 @@
     data.uncached = useUncached(usage);
     data.allocType = 0;
 
-    if(usage & GRALLOC_USAGE_PRIVATE_UI_CONTIG_HEAP)
-        ionFlags |= ION_HEAP(ION_SF_HEAP_ID);
-
     if(usage & GRALLOC_USAGE_PRIVATE_SYSTEM_HEAP)
         ionFlags |= ION_HEAP(ION_SYSTEM_HEAP_ID);
 
@@ -292,6 +304,11 @@
         if (usage & GRALLOC_USAGE_PRIVATE_MM_HEAP) {
             ionFlags |= ION_HEAP(ION_CP_MM_HEAP_ID);
             ionFlags |= ION_SECURE;
+#ifdef ION_FLAG_ALLOW_NON_CONTIG
+            if (!(usage & GRALLOC_USAGE_PRIVATE_SECURE_DISPLAY)) {
+                ionFlags |= ION_FLAG_ALLOW_NON_CONTIG;
+            }
+#endif
         } else {
             // for targets/OEMs which do not need HW level protection
             // do not set ion secure flag & MM heap. Fallback to IOMMU heap.
@@ -659,14 +676,3 @@
         delete hnd;
 
 }
-
-bool useUncached(const int& usage) {
-    if(usage & GRALLOC_USAGE_PRIVATE_UNCACHED)
-        return true;
-
-    if(not (usage & (GRALLOC_USAGE_SW_WRITE_OFTEN |
-            GRALLOC_USAGE_SW_READ_OFTEN)))
-        return true;
-
-    return false;
-}
diff --git a/libgralloc/gpu.cpp b/libgralloc/gpu.cpp
index 9b98f1b..5533ffb 100644
--- a/libgralloc/gpu.cpp
+++ b/libgralloc/gpu.cpp
@@ -153,6 +153,17 @@
             flags |= private_handle_t::PRIV_FLAGS_CPU_RENDERED;
         }
 
+        if (usage & (GRALLOC_USAGE_HW_VIDEO_ENCODER |
+                GRALLOC_USAGE_HW_CAMERA_WRITE |
+                GRALLOC_USAGE_HW_RENDER |
+                GRALLOC_USAGE_HW_FB)) {
+            flags |= private_handle_t::PRIV_FLAGS_NON_CPU_WRITER;
+        }
+
+        if(false == data.uncached) {
+            flags |= private_handle_t::PRIV_FLAGS_CACHED;
+        }
+
         flags |= data.allocType;
         uint64_t eBaseAddr = (uint64_t)(eData.base) + eData.offset;
         private_handle_t *hnd = new private_handle_t(data.fd, size, flags,
diff --git a/libgralloc/gr.h b/libgralloc/gr.h
index 37ee4e5..797d57e 100644
--- a/libgralloc/gr.h
+++ b/libgralloc/gr.h
@@ -71,10 +71,6 @@
 void free_buffer(private_handle_t *hnd);
 int getYUVPlaneInfo(private_handle_t* pHnd, struct android_ycbcr* ycbcr);
 
-// Use uncached for all scenarios except when the CPU needs to read or write
-// often
-bool useUncached(const int& usage);
-
 /*****************************************************************************/
 
 class Locker {
diff --git a/libgralloc/gralloc_priv.h b/libgralloc/gralloc_priv.h
old mode 100644
new mode 100755
index d64914e..b60eaff
--- a/libgralloc/gralloc_priv.h
+++ b/libgralloc/gralloc_priv.h
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2008 The Android Open Source Project
- * Copyright (c) 2011-2014, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011-2015, The Linux Foundation. All rights reserved.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -40,8 +40,9 @@
     /* SYSTEM heap comes from kernel vmalloc,
      * can never be uncached, is not secured*/
     GRALLOC_USAGE_PRIVATE_SYSTEM_HEAP     =       GRALLOC_USAGE_PRIVATE_0,
-    /* SF heap is used for application buffers, is not secured */
-    GRALLOC_USAGE_PRIVATE_UI_CONTIG_HEAP  =       GRALLOC_USAGE_PRIVATE_1,
+
+    /* GRALLOC_USAGE_PRIVATE_1 is unused */
+
     /* IOMMU heap comes from manually allocated pages,
      * can be cached/uncached, is not secured */
     GRALLOC_USAGE_PRIVATE_IOMMU_HEAP      =       GRALLOC_USAGE_PRIVATE_2,
@@ -70,23 +71,20 @@
     GRALLOC_USAGE_PRIVATE_SECURE_DISPLAY  =       0x00800000,
 };
 
-enum {
-    /* Gralloc perform enums
-    */
-    GRALLOC_MODULE_PERFORM_CREATE_HANDLE_FROM_BUFFER = 1,
-    // This will be deprecated from latest graphics drivers. This is kept
-    // for those backward compatibility i.e., newer Display HAL + older graphics
-    // libraries
-    GRALLOC_MODULE_PERFORM_GET_STRIDE,
-    GRALLOC_MODULE_PERFORM_GET_CUSTOM_STRIDE_FROM_HANDLE,
-    GRALLOC_MODULE_PERFORM_GET_CUSTOM_STRIDE_AND_HEIGHT_FROM_HANDLE,
-    GRALLOC_MODULE_PERFORM_GET_ATTRIBUTES,
-    GRALLOC_MODULE_PERFORM_GET_COLOR_SPACE_FROM_HANDLE,
-    GRALLOC_MODULE_PERFORM_GET_YUV_PLANE_INFO,
-};
+/* define Gralloc perform */
+#define GRALLOC_MODULE_PERFORM_CREATE_HANDLE_FROM_BUFFER 1
+// This will be used by the graphics drivers to know if certain features
+// are defined in this display HAL.
+// Ex: Newer GFX libraries + Older Display HAL
+#define GRALLOC_MODULE_PERFORM_GET_STRIDE 2
+#define GRALLOC_MODULE_PERFORM_GET_CUSTOM_STRIDE_FROM_HANDLE 3
+#define GRALLOC_MODULE_PERFORM_GET_CUSTOM_STRIDE_AND_HEIGHT_FROM_HANDLE 4
+#define GRALLOC_MODULE_PERFORM_GET_ATTRIBUTES 5
+#define GRALLOC_MODULE_PERFORM_GET_COLOR_SPACE_FROM_HANDLE 6
+#define GRALLOC_MODULE_PERFORM_GET_YUV_PLANE_INFO 7
+#define GRALLOC_MODULE_PERFORM_GET_MAP_SECURE_BUFFER_INFO 8
 
-#define GRALLOC_HEAP_MASK   (GRALLOC_USAGE_PRIVATE_UI_CONTIG_HEAP |\
-                             GRALLOC_USAGE_PRIVATE_SYSTEM_HEAP    |\
+#define GRALLOC_HEAP_MASK   (GRALLOC_USAGE_PRIVATE_SYSTEM_HEAP    |\
                              GRALLOC_USAGE_PRIVATE_IOMMU_HEAP     |\
                              GRALLOC_USAGE_PRIVATE_MM_HEAP        |\
                              GRALLOC_USAGE_PRIVATE_ADSP_HEAP)
@@ -94,58 +92,62 @@
 #define INTERLACE_MASK 0x80
 #define S3D_FORMAT_MASK 0xFF000
 /*****************************************************************************/
-enum {
-    /* OEM specific HAL formats */
-    HAL_PIXEL_FORMAT_NV12_ENCODEABLE        = 0x102,
-    HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS     = 0x7FA30C04,
-    HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED     = 0x7FA30C03,
-    HAL_PIXEL_FORMAT_YCbCr_420_SP           = 0x109,
-    HAL_PIXEL_FORMAT_YCrCb_420_SP_ADRENO    = 0x7FA30C01,
-    HAL_PIXEL_FORMAT_YCrCb_422_SP           = 0x10B,
-    HAL_PIXEL_FORMAT_R_8                    = 0x10D,
-    HAL_PIXEL_FORMAT_RG_88                  = 0x10E,
-    HAL_PIXEL_FORMAT_YCbCr_444_SP           = 0x10F,
-    HAL_PIXEL_FORMAT_YCrCb_444_SP           = 0x110,
-    HAL_PIXEL_FORMAT_YCrCb_422_I            = 0x111,
-    HAL_PIXEL_FORMAT_BGRX_8888              = 0x112,
-    HAL_PIXEL_FORMAT_NV21_ZSL               = 0x113,
-    HAL_PIXEL_FORMAT_INTERLACE              = 0x180,
-    //v4l2_fourcc('Y', 'U', 'Y', 'L'). 24 bpp YUYV 4:2:2 10 bit per component
-    HAL_PIXEL_FORMAT_YCbCr_422_I_10BIT      = 0x4C595559,
-    //v4l2_fourcc('Y', 'B', 'W', 'C'). 10 bit per component. This compressed
-    //format reduces the memory access bandwidth
-    HAL_PIXEL_FORMAT_YCbCr_422_I_10BIT_COMPRESSED = 0x43574259,
 
-    //Khronos ASTC formats
-    HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_4x4_KHR    = 0x93B0,
-    HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_5x4_KHR    = 0x93B1,
-    HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_5x5_KHR    = 0x93B2,
-    HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_6x5_KHR    = 0x93B3,
-    HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_6x6_KHR    = 0x93B4,
-    HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_8x5_KHR    = 0x93B5,
-    HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_8x6_KHR    = 0x93B6,
-    HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_8x8_KHR    = 0x93B7,
-    HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_10x5_KHR   = 0x93B8,
-    HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_10x6_KHR   = 0x93B9,
-    HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_10x8_KHR   = 0x93BA,
-    HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_10x10_KHR  = 0x93BB,
-    HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_12x10_KHR  = 0x93BC,
-    HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_12x12_KHR  = 0x93BD,
-    HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR    = 0x93D0,
-    HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR    = 0x93D1,
-    HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR    = 0x93D2,
-    HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR    = 0x93D3,
-    HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR    = 0x93D4,
-    HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR    = 0x93D5,
-    HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR    = 0x93D6,
-    HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR    = 0x93D7,
-    HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR   = 0x93D8,
-    HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR   = 0x93D9,
-    HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR   = 0x93DA,
-    HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR  = 0x93DB,
-    HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR  = 0x93DC,
-    HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR  = 0x93DD,
-};
+/* OEM specific HAL formats */
+
+#define HAL_PIXEL_FORMAT_RGBA_5551               6
+#define HAL_PIXEL_FORMAT_RGBA_4444               7
+#define HAL_PIXEL_FORMAT_NV12_ENCODEABLE         0x102
+#define HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS      0x7FA30C04
+#define HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED      0x7FA30C03
+#define HAL_PIXEL_FORMAT_YCbCr_420_SP            0x109
+#define HAL_PIXEL_FORMAT_YCrCb_420_SP_ADRENO     0x7FA30C01
+#define HAL_PIXEL_FORMAT_YCrCb_422_SP            0x10B
+#define HAL_PIXEL_FORMAT_R_8                     0x10D
+#define HAL_PIXEL_FORMAT_RG_88                   0x10E
+#define HAL_PIXEL_FORMAT_YCbCr_444_SP            0x10F
+#define HAL_PIXEL_FORMAT_YCrCb_444_SP            0x110
+#define HAL_PIXEL_FORMAT_YCrCb_422_I             0x111
+#define HAL_PIXEL_FORMAT_BGRX_8888               0x112
+#define HAL_PIXEL_FORMAT_NV21_ZSL                0x113
+#define HAL_PIXEL_FORMAT_INTERLACE               0x180
+
+//v4l2_fourcc('Y', 'U', 'Y', 'L'). 24 bpp YUYV 4:2:2 10 bit per component
+#define HAL_PIXEL_FORMAT_YCbCr_422_I_10BIT       0x4C595559
+
+//v4l2_fourcc('Y', 'B', 'W', 'C'). 10 bit per component. This compressed
+//format reduces the memory access bandwidth
+#define HAL_PIXEL_FORMAT_YCbCr_422_I_10BIT_COMPRESSED  0x43574259
+
+//Khronos ASTC formats
+#define HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_4x4_KHR             0x93B0
+#define HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_5x4_KHR             0x93B1
+#define HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_5x5_KHR             0x93B2
+#define HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_6x5_KHR             0x93B3
+#define HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_6x6_KHR             0x93B4
+#define HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_8x5_KHR             0x93B5
+#define HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_8x6_KHR             0x93B6
+#define HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_8x8_KHR             0x93B7
+#define HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_10x5_KHR            0x93B8
+#define HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_10x6_KHR            0x93B9
+#define HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_10x8_KHR            0x93BA
+#define HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_10x10_KHR           0x93BB
+#define HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_12x10_KHR           0x93BC
+#define HAL_PIXEL_FORMAT_COMPRESSED_RGBA_ASTC_12x12_KHR           0x93BD
+#define HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR     0x93D0
+#define HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR     0x93D1
+#define HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR     0x93D2
+#define HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR     0x93D3
+#define HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR     0x93D4
+#define HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR     0x93D5
+#define HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR     0x93D6
+#define HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR     0x93D7
+#define HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR    0x93D8
+#define HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR    0x93D9
+#define HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR    0x93DA
+#define HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR   0x93DB
+#define HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR   0x93DC
+#define HAL_PIXEL_FORMAT_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR   0x93DD
 
 /* possible formats for 3D content*/
 enum {
@@ -180,12 +182,9 @@
             PRIV_FLAGS_USES_ION           = 0x00000008,
             PRIV_FLAGS_USES_ASHMEM        = 0x00000010,
             PRIV_FLAGS_NEEDS_FLUSH        = 0x00000020,
-            // Uncached memory or no CPU writers
-            PRIV_FLAGS_DO_NOT_FLUSH       = 0x00000040,
-            PRIV_FLAGS_SW_LOCK            = 0x00000080,
+            PRIV_FLAGS_NON_CPU_WRITER     = 0x00000080,
             PRIV_FLAGS_NONCONTIGUOUS_MEM  = 0x00000100,
-            // Set by HWC when storing the handle
-            PRIV_FLAGS_HWC_LOCK           = 0x00000200,
+            PRIV_FLAGS_CACHED             = 0x00000200,
             PRIV_FLAGS_SECURE_BUFFER      = 0x00000400,
             // For explicit synchronization
             PRIV_FLAGS_UNSYNCHRONIZED     = 0x00000800,
diff --git a/libgralloc/ionalloc.cpp b/libgralloc/ionalloc.cpp
index 23e225d..91a930c 100644
--- a/libgralloc/ionalloc.cpp
+++ b/libgralloc/ionalloc.cpp
@@ -77,12 +77,18 @@
     ionAllocData.len = data.size;
     ionAllocData.align = data.align;
     ionAllocData.heap_id_mask = data.flags & ~ION_SECURE;
+#ifdef ION_FLAG_ALLOW_NON_CONTIG
+    ionAllocData.heap_id_mask &= (data.flags & ~ION_FLAG_ALLOW_NON_CONTIG);
+#endif
     ionAllocData.flags = data.uncached ? 0 : ION_FLAG_CACHED;
     // ToDo: replace usage of alloc data structure with
     //  ionallocdata structure.
     if (data.flags & ION_SECURE)
         ionAllocData.flags |= ION_SECURE;
-
+#ifdef ION_FLAG_ALLOW_NON_CONTIG
+    if (data.flags & ION_FLAG_ALLOW_NON_CONTIG)
+        ionAllocData.flags |= ION_FLAG_ALLOW_NON_CONTIG;
+#endif
     err = open_device();
     if (err)
         return err;
diff --git a/libgralloc/mapper.cpp b/libgralloc/mapper.cpp
index 943e64f..356001e 100644
--- a/libgralloc/mapper.cpp
+++ b/libgralloc/mapper.cpp
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2008 The Android Open Source Project
- * Copyright (c) 2011-2014, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011-2015, The Linux Foundation. All rights reserved.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -237,36 +237,25 @@
             pthread_mutex_unlock(lock);
         }
         if (hnd->flags & private_handle_t::PRIV_FLAGS_USES_ION and
-                    not useUncached(usage)) {
-            bool nonCPUWriters = usage & (
-                        GRALLOC_USAGE_HW_RENDER |
-                        GRALLOC_USAGE_HW_FB |
-                        GRALLOC_USAGE_HW_VIDEO_ENCODER |
-                        GRALLOC_USAGE_HW_CAMERA_WRITE);
-
+                hnd->flags & private_handle_t::PRIV_FLAGS_CACHED) {
             //Invalidate if CPU reads in software and there are non-CPU
             //writers. No need to do this for the metadata buffer as it is
             //only read/written in software.
-            //Corner case: If we reach here with a READ_RARELY, then there must
-            //be a WRITE_OFTEN that caused caching to be used.
-            if ((usage & GRALLOC_USAGE_SW_READ_MASK) and nonCPUWriters) {
+            if ((usage & GRALLOC_USAGE_SW_READ_MASK) and
+                    (hnd->flags & private_handle_t::PRIV_FLAGS_NON_CPU_WRITER))
+            {
                 IMemAlloc* memalloc = getAllocator(hnd->flags) ;
                 err = memalloc->clean_buffer((void*)hnd->base,
                         hnd->size, hnd->offset, hnd->fd,
                         CACHE_INVALIDATE);
             }
             //Mark the buffer to be flushed after CPU write.
-            //Corner case: If we reach here with a WRITE_RARELY, then there
-            //must be a READ_OFTEN that caused caching to be used.
             if (usage & GRALLOC_USAGE_SW_WRITE_MASK) {
                 hnd->flags |= private_handle_t::PRIV_FLAGS_NEEDS_FLUSH;
             }
         }
     }
 
-    if(useUncached(usage))
-        hnd->flags |= private_handle_t::PRIV_FLAGS_DO_NOT_FLUSH;
-
     return err;
 }
 
@@ -314,9 +303,6 @@
         hnd->flags &= ~private_handle_t::PRIV_FLAGS_NEEDS_FLUSH;
     }
 
-    if(hnd->flags & private_handle_t::PRIV_FLAGS_DO_NOT_FLUSH)
-            hnd->flags &= ~private_handle_t::PRIV_FLAGS_DO_NOT_FLUSH;
-
     return err;
 }
 
@@ -436,6 +422,7 @@
                     res = 0;
                 }
             } break;
+
         case GRALLOC_MODULE_PERFORM_GET_YUV_PLANE_INFO:
             {
                 private_handle_t* hnd =  va_arg(args, private_handle_t*);
@@ -445,6 +432,22 @@
                 }
             } break;
 
+        case GRALLOC_MODULE_PERFORM_GET_MAP_SECURE_BUFFER_INFO:
+            {
+                private_handle_t* hnd =  va_arg(args, private_handle_t*);
+                int *map_secure_buffer = va_arg(args, int *);
+                if (private_handle_t::validate(hnd)) {
+                    return res;
+                }
+                MetaData_t *metadata = (MetaData_t *)hnd->base_metadata;
+                if(metadata && metadata->operation & MAP_SECURE_BUFFER) {
+                    *map_secure_buffer = metadata->mapSecureBuffer;
+                    res = 0;
+                } else {
+                    *map_secure_buffer = 0;
+                }
+            } break;
+
         default:
             break;
     }
diff --git a/libhwcomposer/hwc.cpp b/libhwcomposer/hwc.cpp
index c96eb1e..2bf421f 100644
--- a/libhwcomposer/hwc.cpp
+++ b/libhwcomposer/hwc.cpp
@@ -257,7 +257,8 @@
     bool fbComp = false;
     if (LIKELY(list && list->numHwLayers > 1) &&
             (ctx->dpyAttr[dpy].isActive ||
-             ctx->mHDMIDisplay->isHDMIPrimaryDisplay())) {
+             ctx->mHDMIDisplay->isHDMIPrimaryDisplay())
+            && !ctx->dpyAttr[dpy].isPause) {
 
         // When HDMI is primary we should rely on the first valid
         // draw call in order to activate the display
@@ -475,10 +476,11 @@
                 return -errno;
             }
 
-            if(mode == HWC_POWER_MODE_NORMAL) {
+            if(mode == HWC_POWER_MODE_NORMAL && !ctx->mHPDEnabled) {
                 // Enable HPD here, as during bootup POWER_MODE_NORMAL is set
                 // when SF is completely initialized
                 ctx->mHDMIDisplay->setHPD(1);
+                ctx->mHPDEnabled = true;
             }
 
             ctx->dpyAttr[dpy].isActive = not(mode == HWC_POWER_MODE_OFF);
@@ -585,7 +587,8 @@
     ATRACE_CALL();
     int ret = 0;
     const int dpy = HWC_DISPLAY_PRIMARY;
-    if (LIKELY(list) && ctx->dpyAttr[dpy].isActive) {
+    if (LIKELY(list) && ctx->dpyAttr[dpy].isActive
+            && !ctx->dpyAttr[dpy].isPause) {
         size_t last = list->numHwLayers - 1;
         hwc_layer_1_t *fbLayer = &list->hwLayers[last];
         int fd = -1; //FenceFD from the Copybit(valid in async mode)
diff --git a/libhwcomposer/hwc_ad.cpp b/libhwcomposer/hwc_ad.cpp
index 7e96d97..b9cf5ce 100644
--- a/libhwcomposer/hwc_ad.cpp
+++ b/libhwcomposer/hwc_ad.cpp
@@ -134,7 +134,7 @@
         const hwc_layer_1_t* layer = &list->hwLayers[nYuvIndex];
         private_handle_t *hnd = (private_handle_t *)layer->handle;
         qdutils::MDPVersion& mdpHw =  qdutils::MDPVersion::getInstance();
-        if(hnd && hnd->width <= (int) mdpHw.getMaxMixerWidth()) {
+        if(hnd && hnd->width <= (int) mdpHw.getMaxPipeWidth()) {
             mDoable = true;
         }
     }
diff --git a/libhwcomposer/hwc_dump_layers.cpp b/libhwcomposer/hwc_dump_layers.cpp
index e717c26..6a8feb2 100644
--- a/libhwcomposer/hwc_dump_layers.cpp
+++ b/libhwcomposer/hwc_dump_layers.cpp
@@ -319,7 +319,7 @@
         bool bResult = false;
         char dumpFilename[PATH_MAX];
         SkBitmap *tempSkBmp = new SkBitmap();
-        SkBitmap::Config tempSkBmpConfig = SkBitmap::kNo_Config;
+        SkColorType tempSkBmpColor = kUnknown_SkColorType;
         snprintf(dumpFilename, sizeof(dumpFilename),
             "%s/sfdump%03d.layer%zu.%s.png", mDumpDirPng,
             mDumpCntrPng, layerIndex, mDisplayName);
@@ -327,21 +327,24 @@
         switch (hnd->format) {
             case HAL_PIXEL_FORMAT_RGBA_8888:
             case HAL_PIXEL_FORMAT_RGBX_8888:
+                tempSkBmpColor = kRGBA_8888_SkColorType;
+                break;
             case HAL_PIXEL_FORMAT_BGRA_8888:
-                tempSkBmpConfig = SkBitmap::kARGB_8888_Config;
+                tempSkBmpColor = kBGRA_8888_SkColorType;
                 break;
             case HAL_PIXEL_FORMAT_RGB_565:
+                tempSkBmpColor = kRGB_565_SkColorType;
+                break;
             case HAL_PIXEL_FORMAT_RGBA_5551:
             case HAL_PIXEL_FORMAT_RGBA_4444:
-                tempSkBmpConfig = SkBitmap::kRGB_565_Config;
-                break;
             case HAL_PIXEL_FORMAT_RGB_888:
             default:
-                tempSkBmpConfig = SkBitmap::kNo_Config;
+                tempSkBmpColor = kUnknown_SkColorType;
                 break;
         }
-        if (SkBitmap::kNo_Config != tempSkBmpConfig) {
-            tempSkBmp->setConfig(tempSkBmpConfig, getWidth(hnd), getHeight(hnd));
+        if (kUnknown_SkColorType != tempSkBmpColor) {
+            tempSkBmp->setInfo(SkImageInfo::Make(getWidth(hnd), getHeight(hnd),
+                    tempSkBmpColor, kIgnore_SkAlphaType), 0);
             tempSkBmp->setPixels((void*)hnd->base);
             bResult = SkImageEncoder::EncodeFile(dumpFilename,
                                     *tempSkBmp, SkImageEncoder::kPNG_Type, 100);
diff --git a/libhwcomposer/hwc_fbupdate.cpp b/libhwcomposer/hwc_fbupdate.cpp
index 58cf374..08a4fb9 100644
--- a/libhwcomposer/hwc_fbupdate.cpp
+++ b/libhwcomposer/hwc_fbupdate.cpp
@@ -529,7 +529,7 @@
     const uint32_t layerClock = getLayerClock(dstWidth, dstHeight, cropHeight);
     const uint32_t mixerClock = lSplit;
 
-    if((cropWidth > qdutils::MDPVersion::getInstance().getMaxMixerWidth()) or
+    if((cropWidth > qdutils::MDPVersion::getInstance().getMaxPipeWidth()) or
             (primarySplitAlways and
             (cropWidth > lSplit or layerClock > mixerClock))) {
         destR = ov.getPipe(pipeSpecs);
diff --git a/libhwcomposer/hwc_mdpcomp.cpp b/libhwcomposer/hwc_mdpcomp.cpp
index 466151b..7e7b44b 100644
--- a/libhwcomposer/hwc_mdpcomp.cpp
+++ b/libhwcomposer/hwc_mdpcomp.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2012-2014, The Linux Foundation. All rights reserved.
+ * Copyright (C) 2012-2015, The Linux Foundation. All rights reserved.
  * Not a Contribution, Apache license notifications and license are retained
  * for attribution purposes only.
  *
@@ -19,6 +19,7 @@
 #include <math.h>
 #include "hwc_mdpcomp.h"
 #include <sys/ioctl.h>
+#include <dlfcn.h>
 #include "hdmi.h"
 #include "qdMetaData.h"
 #include "mdp_version.h"
@@ -26,6 +27,7 @@
 #include "hwc_ad.h"
 #include <overlayRotator.h>
 #include "hwc_copybit.h"
+#include "qd_utils.h"
 
 using namespace overlay;
 using namespace qdutils;
@@ -46,7 +48,15 @@
 int MDPComp::sMaxPipesPerMixer = 0;
 bool MDPComp::sEnableYUVsplit = false;
 bool MDPComp::sSrcSplitEnabled = false;
+int MDPComp::sMaxSecLayers = 1;
 bool MDPComp::enablePartialUpdateForMDP3 = false;
+bool MDPComp::sIsPartialUpdateActive = true;
+void *MDPComp::sLibPerfHint = NULL;
+int MDPComp::sPerfLockHandle = 0;
+int (*MDPComp::sPerfLockAcquire)(int, int, int*, int) = NULL;
+int (*MDPComp::sPerfLockRelease)(int value) = NULL;
+int MDPComp::sPerfHintWindow = -1;
+
 MDPComp* MDPComp::getObject(hwc_context_t *ctx, const int& dpy) {
     if(qdutils::MDPVersion::getInstance().isSrcSplit()) {
         sSrcSplitEnabled = true;
@@ -130,15 +140,23 @@
 
     qdutils::MDPVersion &mdpVersion = qdutils::MDPVersion::getInstance();
 
-    /* MDSS_MDP_STAGE_UNUSED and MDSS_MDP_STAGE_BASE are not available for MDP
-     * composition. */
-    sMaxPipesPerMixer = (int)mdpVersion.getBlendStages() - 2;
+    sMaxPipesPerMixer = (int)mdpVersion.getBlendStages();
     if(property_get("persist.hwc.mdpcomp.maxpermixer", property, "-1") > 0) {
         int val = atoi(property);
         if(val >= 0)
             sMaxPipesPerMixer = min(val, sMaxPipesPerMixer);
     }
 
+    /* Maximum layers allowed to use MDP on secondary panels. If property
+     * doesn't exist, default to 1. Using the property it can be set to 0 or
+     * more.
+     */
+    if(property_get("persist.hwc.maxseclayers", property, "1") > 0) {
+        int val = atoi(property);
+        sMaxSecLayers = (val >= 0) ? val : 1;
+        sMaxSecLayers = min(sMaxSecLayers, sMaxPipesPerMixer);
+    }
+
     if(ctx->mMDP.panel != MIPI_CMD_PANEL) {
         sIdleInvalidator = IdleInvalidator::getInstance();
         if(sIdleInvalidator->init(timeout_handler, ctx) < 0) {
@@ -181,6 +199,16 @@
        enablePartialUpdateForMDP3 = true;
     }
 
+    sIsPartialUpdateActive = getPartialUpdatePref(ctx);
+
+    if(property_get("persist.mdpcomp_perfhint", property, "-1") > 0) {
+        int val = atoi(property);
+        if(val > 0 && loadPerfLib()) {
+            sPerfHintWindow = val;
+            ALOGI("PerfHintWindow = %d", sPerfHintWindow);
+        }
+    }
+
     return true;
 }
 
@@ -203,24 +231,28 @@
         ALOGE("%s: received empty data in timer callback", __FUNCTION__);
         return;
     }
-    Locker::Autolock _l(ctx->mDrawLock);
+
+    ctx->mDrawLock.lock();
     // Handle timeout event only if the previous composition is MDP or MIXED.
     if(!sHandleTimeout) {
         ALOGD_IF(isDebug(), "%s:Do not handle this timeout", __FUNCTION__);
+        ctx->mDrawLock.unlock();
         return;
     }
     if(!ctx->proc) {
         ALOGE("%s: HWC proc not registered", __FUNCTION__);
+        ctx->mDrawLock.unlock();
         return;
     }
     sIdleFallBack = true;
+    ctx->mDrawLock.unlock();
     /* Trigger SF to redraw the current frame */
     ctx->proc->invalidate(ctx->proc);
 }
 
 void MDPComp::setMaxPipesPerMixer(const uint32_t value) {
     qdutils::MDPVersion &mdpVersion = qdutils::MDPVersion::getInstance();
-    uint32_t maxSupported = (int)mdpVersion.getBlendStages() - 2;
+    uint32_t maxSupported = (int)mdpVersion.getBlendStages();
     if(value > maxSupported) {
         ALOGW("%s: Input exceeds max value supported. Setting to"
                 "max value: %d", __FUNCTION__, maxSupported);
@@ -413,7 +445,7 @@
                 /* On targets that doesnt support Decimation (eg.,8x26)
                  * maximum downscale support is overlay pipe downscale.
                  */
-                if(crop_w > (int) mdpHw.getMaxMixerWidth() ||
+                if(crop_w > (int) mdpHw.getMaxPipeWidth() ||
                         w_dscale > maxMDPDownscale ||
                         h_dscale > maxMDPDownscale)
                     return false;
@@ -424,7 +456,7 @@
                      *      1. Src crop > Mixer limit on nonsplit MDPComp
                      *      2. exceeds maximum downscale limit
                      */
-                    if(((crop_w > (int) mdpHw.getMaxMixerWidth()) &&
+                    if(((crop_w > (int) mdpHw.getMaxPipeWidth()) &&
                                 !sSrcSplitEnabled) ||
                             w_dscale > maxMDPDownscale ||
                             h_dscale > maxMDPDownscale) {
@@ -733,7 +765,6 @@
                                 hwc_display_contents_1_t* list){
 
     const int numAppLayers = ctx->listStats[mDpy].numAppLayers;
-    int priDispW = ctx->dpyAttr[HWC_DISPLAY_PRIMARY].xres;
 
     // Fall back to video only composition, if AIV video mode is enabled
     if(ctx->listStats[mDpy].mAIVVideoMode) {
@@ -742,11 +773,11 @@
         return false;
     }
 
-    // No Idle fall back, if secure display or secure RGB layers are present or
-    // if there's only a single layer being composed
-    if(sIdleFallBack && (!ctx->listStats[mDpy].secureUI &&
-                    !ctx->listStats[mDpy].secureRGBCount) &&
-                    (ctx->listStats[mDpy].numAppLayers != 1)) {
+    /* No Idle fall back if secure display or secure RGB layers are present
+     * or if there is only a single layer being composed */
+    if(sIdleFallBack && !ctx->listStats[mDpy].secureUI &&
+                  !ctx->listStats[mDpy].secureRGBCount &&
+                  (ctx->listStats[mDpy].numAppLayers > 1)) {
         ALOGD_IF(isDebug(), "%s: Idle fallback dpy %d",__FUNCTION__, mDpy);
         return false;
     }
@@ -770,19 +801,6 @@
         return false;
     }
 
-    MDPVersion& mdpHw = MDPVersion::getInstance();
-    if(mDpy > HWC_DISPLAY_PRIMARY &&
-            (priDispW >  (int) mdpHw.getMaxMixerWidth()) &&
-            (ctx->dpyAttr[mDpy].xres <  mdpHw.getMaxMixerWidth())) {
-        // Disable MDP comp on Secondary when the primary is highres panel and
-        // the secondary is a normal 1080p, because, MDP comp on secondary under
-        // in such usecase, decimation gets used for downscale and there will be
-        // a quality mismatch when there will be a fallback to GPU comp
-        ALOGD_IF(isDebug(), "%s: Disable MDP Compositon for Secondary Disp",
-              __FUNCTION__);
-        return false;
-    }
-
     // check for action safe flag and MDP scaling mode which requires scaling.
     if(ctx->dpyAttr[mDpy].mActionSafePresent
             || ctx->dpyAttr[mDpy].mMDPScalingMode) {
@@ -804,6 +822,7 @@
 
         //For 8x26 with panel width>1k, if RGB layer needs HFLIP fail mdp comp
         // may not need it if Gfx pre-rotation can handle all flips & rotations
+        MDPVersion& mdpHw = MDPVersion::getInstance();
         int transform = (layer->flags & HWC_COLOR_FILL) ? 0 : layer->transform;
         if( mdpHw.is8x26() && (ctx->dpyAttr[mDpy].xres > 1024) &&
                 (transform & HWC_TRANSFORM_FLIP_H) && (!isYuvBuffer(hnd)))
@@ -832,13 +851,6 @@
     if(sSimulationFlags & MDPCOMP_AVOID_FULL_MDP)
         return false;
 
-    //Will benefit presentation / secondary-only layer.
-    if((mDpy > HWC_DISPLAY_PRIMARY) &&
-            (list->numHwLayers - 1) > MAX_SEC_LAYERS) {
-        ALOGD_IF(isDebug(), "%s: Exceeds max secondary pipes",__FUNCTION__);
-        return false;
-    }
-
     const int numAppLayers = ctx->listStats[mDpy].numAppLayers;
     for(int i = 0; i < numAppLayers; i++) {
         hwc_layer_1_t* layer = &list->hwLayers[i];
@@ -1160,14 +1172,6 @@
         adjustForSourceSplit(ctx, list);
     }
 
-    //Will benefit cases where a video has non-updating background.
-    if((mDpy > HWC_DISPLAY_PRIMARY) and
-            (mdpCount > MAX_SEC_LAYERS)) {
-        ALOGD_IF(isDebug(), "%s: Exceeds max secondary pipes",__FUNCTION__);
-        reset(ctx);
-        return false;
-    }
-
     if(!postHeuristicsHandling(ctx, list)) {
         ALOGD_IF(isDebug(), "post heuristic handling failed");
         reset(ctx);
@@ -1281,7 +1285,7 @@
         hwc_display_contents_1_t* list){
     if(!qdutils::MDPVersion::getInstance().isPartialUpdateEnabled() ||
             isSkipPresent(ctx, mDpy) || (list->flags & HWC_GEOMETRY_CHANGED) ||
-            mDpy ) {
+            !sIsPartialUpdateActive || mDpy ) {
         return false;
     }
     if(ctx->listStats[mDpy].secureUI)
@@ -1300,7 +1304,22 @@
         hwc_display_contents_1_t* list, bool secureOnly) {
     if(sSimulationFlags & MDPCOMP_AVOID_VIDEO_ONLY)
         return false;
+
     int numAppLayers = ctx->listStats[mDpy].numAppLayers;
+    if(!isSecurePresent(ctx, mDpy)) {
+       /* Bail out if we are processing only secured video layers
+        * and we dont have any */
+       if(secureOnly) {
+           ALOGD_IF(isDebug(),"%s: No Secure Video Layers", __FUNCTION__);
+           return false;
+       }
+       /* No Idle fall back for secure video layers and if there is only
+        * single layer being composed. */
+       if(sIdleFallBack && (ctx->listStats[mDpy].numAppLayers > 1)) {
+           ALOGD_IF(isDebug(), "%s: Idle fallback dpy %d",__FUNCTION__, mDpy);
+           return false;
+        }
+    }
 
     mCurrentFrame.reset(numAppLayers);
     mCurrentFrame.fbCount -= mCurrentFrame.dropCount;
@@ -1312,13 +1331,6 @@
         return false;
     }
 
-    /* Bail out if we are processing only secured video layers
-     * and we dont have any */
-    if(!isSecurePresent(ctx, mDpy) && secureOnly){
-        reset(ctx);
-        return false;
-    }
-
     if(mCurrentFrame.fbCount)
         mCurrentFrame.fbZ = mCurrentFrame.mdpCount;
 
@@ -1328,6 +1340,11 @@
 
     if(!postHeuristicsHandling(ctx, list)) {
         ALOGD_IF(isDebug(), "post heuristic handling failed");
+        if(errno == ENOBUFS) {
+            ALOGD_IF(isDebug(), "SMP Allocation failed");
+            //On SMP allocation failure in video only comp add padding round
+            ctx->isPaddingRound = true;
+        }
         reset(ctx);
         return false;
     }
@@ -1359,14 +1376,28 @@
     if(sSimulationFlags & MDPCOMP_AVOID_MDP_ONLY_LAYERS)
         return false;
 
-    /* Bail out if we are processing only secured video layers
-     * and we dont have any */
-    if(!isSecurePresent(ctx, mDpy) && secureOnly){
+    int numAppLayers = ctx->listStats[mDpy].numAppLayers;
+    if(!isSecurePresent(ctx, mDpy) && !ctx->listStats[mDpy].secureUI) {
+        /* Bail out if we are processing only secured video/ui layers
+         * and we dont have any */
+        if(secureOnly) {
+            ALOGD_IF(isDebug(), "%s: No secure video/ui layers");
+            return false;
+        }
+        /* No Idle fall back for secure video/ui layers and if there is only
+         * single layer being composed. */
+        if(sIdleFallBack && (ctx->listStats[mDpy].numAppLayers > 1)) {
+           ALOGD_IF(isDebug(), "%s: Idle fallback dpy %d",__FUNCTION__, mDpy);
+           return false;
+       }
+    }
+
+    /* Bail out if we dont have any secure RGB layers */
+    if (!ctx->listStats[mDpy].secureRGBCount) {
         reset(ctx);
         return false;
     }
 
-    int numAppLayers = ctx->listStats[mDpy].numAppLayers;
     mCurrentFrame.reset(numAppLayers);
     mCurrentFrame.fbCount -= mCurrentFrame.dropCount;
 
@@ -1819,6 +1850,14 @@
         ALOGD_IF(isDebug(), "%s: Exceeds MAX_PIPES_PER_MIXER",__FUNCTION__);
         return false;
     }
+
+    //Will benefit cases where a video has non-updating background.
+    if((mDpy > HWC_DISPLAY_PRIMARY) and
+            (mCurrentFrame.mdpCount > sMaxSecLayers)) {
+        ALOGD_IF(isDebug(), "%s: Exceeds max secondary pipes",__FUNCTION__);
+        return false;
+    }
+
     // Init rotCount to number of rotate sessions used by other displays
     int rotCount = ctx->mRotMgr->getNumActiveSessions();
     // Count the number of rotator sessions required for current display
@@ -1882,6 +1921,46 @@
     return true;
 }
 
+// Checks only if videos or single layer(RGB) is updating
+// which is used for setting dynamic fps or perf hint for single
+// layer video playback
+bool MDPComp::onlyVideosUpdating(hwc_context_t *ctx,
+                                hwc_display_contents_1_t* list) {
+    bool support = false;
+    FrameInfo frame;
+    frame.reset(mCurrentFrame.layerCount);
+    memset(&frame.drop, 0, sizeof(frame.drop));
+    frame.dropCount = 0;
+    ALOGD_IF(isDebug(), "%s: Update Cache and YUVInfo", __FUNCTION__);
+    updateLayerCache(ctx, list, frame);
+    updateYUV(ctx, list, false /*secure only*/, frame);
+    // There are only updating YUV layers or there is single RGB
+    // Layer(Youtube)
+    if((ctx->listStats[mDpy].yuvCount == frame.mdpCount) ||
+                                        (frame.layerCount == 1)) {
+        support = true;
+    }
+    return support;
+}
+
+void MDPComp::setDynRefreshRate(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
+    //For primary display, set the dynamic refreshrate
+    if(!mDpy && qdutils::MDPVersion::getInstance().isDynFpsSupported() &&
+                                        ctx->mUseMetaDataRefreshRate) {
+        uint32_t refreshRate = ctx->dpyAttr[mDpy].refreshRate;
+        MDPVersion& mdpHw = MDPVersion::getInstance();
+        if(sIdleFallBack) {
+            //Set minimum panel refresh rate during idle timeout
+            refreshRate = mdpHw.getMinFpsSupported();
+        } else if(onlyVideosUpdating(ctx, list)) {
+            //Set the new fresh rate, if there is only one updating YUV layer
+            //or there is one single RGB layer with this request
+            refreshRate = ctx->listStats[mDpy].refreshRateRequest;
+        }
+        setRefreshRate(ctx, mDpy, refreshRate);
+    }
+}
+
 int MDPComp::prepare(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
     int ret = 0;
     char property[PROPERTY_VALUE_MAX];
@@ -1908,19 +1987,22 @@
     if(!mDpy)
         memset(&(ctx->mPtorInfo), 0, sizeof(ctx->mPtorInfo));
 
+    //reset old data
+    mCurrentFrame.reset(numLayers);
+    memset(&mCurrentFrame.drop, 0, sizeof(mCurrentFrame.drop));
+    mCurrentFrame.dropCount = 0;
+
     //Do not cache the information for next draw cycle.
     if(numLayers > MAX_NUM_APP_LAYERS or (!numLayers)) {
         ALOGI("%s: Unsupported layer count for mdp composition",
                 __FUNCTION__);
         mCachedFrame.reset();
+#ifdef DYNAMIC_FPS
+        setDynRefreshRate(ctx, list);
+#endif
         return -1;
     }
 
-    //reset old data
-    mCurrentFrame.reset(numLayers);
-    memset(&mCurrentFrame.drop, 0, sizeof(mCurrentFrame.drop));
-    mCurrentFrame.dropCount = 0;
-
     // Detect the start of animation and fall back to GPU only once to cache
     // all the layers in FB and display FB content untill animation completes.
     if(ctx->listStats[mDpy].isDisplayAnimating) {
@@ -1931,6 +2013,9 @@
         }
         setMDPCompLayerFlags(ctx, list);
         mCachedFrame.updateCounts(mCurrentFrame);
+#ifdef DYNAMIC_FPS
+        setDynRefreshRate(ctx, list);
+#endif
         ret = -1;
         return ret;
     } else {
@@ -1983,26 +2068,9 @@
     }
 
 #ifdef DYNAMIC_FPS
-    //For primary display, set the dynamic refreshrate
-    if(!mDpy && qdutils::MDPVersion::getInstance().isDynFpsSupported()) {
-        FrameInfo frame;
-        frame.reset(mCurrentFrame.layerCount);
-        memset(&frame.drop, 0, sizeof(frame.drop));
-        frame.dropCount = 0;
-        ALOGD_IF(isDebug(), "%s: Update Cache and YUVInfo for Dyn Refresh Rate",
-                 __FUNCTION__);
-        updateLayerCache(ctx, list, frame);
-        updateYUV(ctx, list, false /*secure only*/, frame);
-        uint32_t refreshRate = ctx->dpyAttr[mDpy].refreshRate;
-        //Set the new fresh rate, if there is only one updating YUV layer
-        //or there is one single RGB layer with this request
-        if((ctx->listStats[mDpy].yuvCount == frame.mdpCount) ||
-                                (frame.layerCount == 1)) {
-            refreshRate = ctx->listStats[mDpy].refreshRateRequest;
-        }
-        setRefreshRate(ctx, mDpy, refreshRate);
-    }
+    setDynRefreshRate(ctx, list);
 #endif
+    setPerfHint(ctx, list);
 
     mCachedFrame.cacheAll(list);
     mCachedFrame.updateCounts(mCurrentFrame);
@@ -2405,10 +2473,10 @@
     eDest rDest = mdp_info.rIndex;
 
     ALOGD_IF(isDebug(),"%s: configuring: layer: %p z_order: %d dest_pipeL: %d"
-             "dest_pipeR: %d",__FUNCTION__, layer, zOrder, lDest, rDest);
+            "dest_pipeR: %d",__FUNCTION__, layer, zOrder, lDest, rDest);
 
     return configureSplit(ctx, layer, mDpy, mdpFlagsL, zOrder, lDest,
-                            rDest, &PipeLayerPair.rot);
+            rDest, &PipeLayerPair.rot);
 }
 
 bool MDPCompSplit::draw(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
@@ -2592,8 +2660,8 @@
     //pipe line length, we are still using 2 pipes. This is fine just because
     //this is source split where destination doesn't matter. Evaluate later to
     //see if going through all the calcs to save a pipe is worth it
-    if(dstWidth > mdpHw.getMaxMixerWidth() or
-            cropWidth > mdpHw.getMaxMixerWidth() or
+    if(dstWidth > mdpHw.getMaxPipeWidth() or
+            cropWidth > mdpHw.getMaxPipeWidth() or
             (primarySplitAlways and
             (cropWidth > lSplit or layerClock > mixerClock))) {
         pipe_info.rIndex = ctx->mOverlay->getPipe(pipeSpecs);
@@ -2745,5 +2813,110 @@
     return 0;
 }
 
+bool MDPComp::getPartialUpdatePref(hwc_context_t *ctx) {
+    Locker::Autolock _l(ctx->mDrawLock);
+    const int fbNum = Overlay::getFbForDpy(Overlay::DPY_PRIMARY);
+    char path[MAX_SYSFS_FILE_PATH];
+    snprintf (path, sizeof(path), "sys/class/graphics/fb%d/dyn_pu", fbNum);
+    int fd = open(path, O_RDONLY);
+    if(fd < 0) {
+        ALOGE("%s: Failed to open sysfd node: %s", __FUNCTION__, path);
+        return -1;
+    }
+    char value[4];
+    ssize_t size_read = read(fd, value, sizeof(value)-1);
+    if(size_read <= 0) {
+        ALOGE("%s: Failed to read sysfd node: %s", __FUNCTION__, path);
+        close(fd);
+        return -1;
+    }
+    close(fd);
+    value[size_read] = '\0';
+    return atoi(value);
+}
+
+int MDPComp::setPartialUpdatePref(hwc_context_t *ctx, bool enable) {
+    Locker::Autolock _l(ctx->mDrawLock);
+    const int fbNum = Overlay::getFbForDpy(Overlay::DPY_PRIMARY);
+    char path[MAX_SYSFS_FILE_PATH];
+    snprintf (path, sizeof(path), "sys/class/graphics/fb%d/dyn_pu", fbNum);
+    int fd = open(path, O_WRONLY);
+    if(fd < 0) {
+        ALOGE("%s: Failed to open sysfd node: %s", __FUNCTION__, path);
+        return -1;
+    }
+    char value[4];
+    snprintf(value, sizeof(value), "%d", (int)enable);
+    ssize_t ret = write(fd, value, strlen(value));
+    if(ret <= 0) {
+        ALOGE("%s: Failed to write to sysfd nodes: %s", __FUNCTION__, path);
+        close(fd);
+        return -1;
+    }
+    close(fd);
+    sIsPartialUpdateActive = enable;
+    return 0;
+}
+
+bool MDPComp::loadPerfLib() {
+    char perfLibPath[PROPERTY_VALUE_MAX] = {0};
+    bool success = false;
+    if((property_get("ro.vendor.extension_library", perfLibPath, NULL) <= 0)) {
+        ALOGE("vendor library not set in ro.vendor.extension_library");
+        return false;
+    }
+
+    sLibPerfHint = dlopen(perfLibPath, RTLD_NOW);
+    if(sLibPerfHint) {
+        *(void **)&sPerfLockAcquire = dlsym(sLibPerfHint, "perf_lock_acq");
+        *(void **)&sPerfLockRelease = dlsym(sLibPerfHint, "perf_lock_rel");
+        if (!sPerfLockAcquire || !sPerfLockRelease) {
+            ALOGE("Failed to load symbols for perfLock");
+            dlclose(sLibPerfHint);
+            sLibPerfHint = NULL;
+            return false;
+        }
+        success = true;
+        ALOGI("Successfully Loaded perf hint API's");
+    } else {
+        ALOGE("Failed to open %s : %s", perfLibPath, dlerror());
+    }
+    return success;
+}
+
+void MDPComp::setPerfHint(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
+    if ((sPerfHintWindow < 0) || mDpy || !sLibPerfHint) {
+        return;
+    }
+    static int count = sPerfHintWindow;
+    static int perflockFlag = 0;
+
+    /* Send hint to mpctl when single layer is updated
+     * for a successful number of windows. Hint release
+     * happens immediately upon multiple layer update.
+     */
+    if (onlyVideosUpdating(ctx, list)) {
+        if(count) {
+            count--;
+        }
+    } else {
+        if (perflockFlag) {
+            perflockFlag = 0;
+            sPerfLockRelease(sPerfLockHandle);
+        }
+        count = sPerfHintWindow;
+    }
+    if (count == 0 && !perflockFlag) {
+        int perfHint = 0x4501; // 45-display layer hint, 01-Enable
+        sPerfLockHandle = sPerfLockAcquire(0 /*handle*/, 0/*duration*/,
+                                    &perfHint, sizeof(perfHint)/sizeof(int));
+        if(sPerfLockHandle < 0) {
+            ALOGE("Perf Lock Acquire Failed");
+        } else {
+            perflockFlag = 1;
+        }
+    }
+}
+
 }; //namespace
 
diff --git a/libhwcomposer/hwc_mdpcomp.h b/libhwcomposer/hwc_mdpcomp.h
index 7fa6674..302b047 100644
--- a/libhwcomposer/hwc_mdpcomp.h
+++ b/libhwcomposer/hwc_mdpcomp.h
@@ -56,10 +56,11 @@
     static void dynamicDebug(bool enable){ sDebugLogs = enable; }
     static void setIdleTimeout(const uint32_t& timeout);
     static void setMaxPipesPerMixer(const uint32_t value);
+    static int setPartialUpdatePref(hwc_context_t *ctx, bool enable);
+    static bool getPartialUpdatePref(hwc_context_t *ctx);
+    void setDynRefreshRate(hwc_context_t *ctx, hwc_display_contents_1_t* list);
 
 protected:
-    enum { MAX_SEC_LAYERS = 1 }; //TODO add property support
-
     enum ePipeType {
         MDPCOMP_OV_RGB = ovutils::OV_MDP_PIPE_RGB,
         MDPCOMP_OV_VG = ovutils::OV_MDP_PIPE_VG,
@@ -246,6 +247,10 @@
             hwc_display_contents_1_t* list);
     /* checks for conditions to enable partial udpate */
     bool canPartialUpdate(hwc_context_t *ctx, hwc_display_contents_1_t* list);
+    // Checks if only videocontent is updating
+    bool onlyVideosUpdating(hwc_context_t *ctx, hwc_display_contents_1_t* list);
+    static bool loadPerfLib();
+    void setPerfHint(hwc_context_t *ctx, hwc_display_contents_1_t* list);
 
     int mDpy;
     static bool sEnabled;
@@ -258,6 +263,8 @@
     static int sMaxPipesPerMixer;
     static bool sSrcSplitEnabled;
     static IdleInvalidator *sIdleInvalidator;
+    static int sMaxSecLayers;
+    static bool sIsPartialUpdateActive;
     struct FrameInfo mCurrentFrame;
     struct LayerCache mCachedFrame;
     //Enable 4kx2k yuv layer split
@@ -266,6 +273,12 @@
     bool allocSplitVGPipesfor4k2k(hwc_context_t *ctx, int index);
     //Enable Partial Update for MDP3 targets
     static bool enablePartialUpdateForMDP3;
+    static void *sLibPerfHint;
+    static int sPerfLockHandle;
+    static int (*sPerfLockAcquire)(int, int, int*, int);
+    static int (*sPerfLockRelease)(int value);
+    static int sPerfHintWindow;
+
 };
 
 class MDPCompNonSplit : public MDPComp {
diff --git a/libhwcomposer/hwc_qclient.cpp b/libhwcomposer/hwc_qclient.cpp
index 398995a..09013c6 100644
--- a/libhwcomposer/hwc_qclient.cpp
+++ b/libhwcomposer/hwc_qclient.cpp
@@ -34,6 +34,7 @@
 #include <hwc_mdpcomp.h>
 #include <hwc_virtual.h>
 #include <overlay.h>
+#include <display_config.h>
 
 #define QCLIENT_DEBUG 0
 
@@ -58,34 +59,39 @@
 }
 
 static void securing(hwc_context_t *ctx, uint32_t startEnd) {
-    Locker::Autolock _sl(ctx->mDrawLock);
     //The only way to make this class in this process subscribe to media
     //player's death.
     IMediaDeathNotifier::getMediaPlayerService();
 
+    ctx->mDrawLock.lock();
     ctx->mSecuring = startEnd;
     //We're done securing
     if(startEnd == IQService::END)
         ctx->mSecureMode = true;
+    ctx->mDrawLock.unlock();
+
     if(ctx->proc)
         ctx->proc->invalidate(ctx->proc);
 }
 
 static void unsecuring(hwc_context_t *ctx, uint32_t startEnd) {
-    Locker::Autolock _sl(ctx->mDrawLock);
+    ctx->mDrawLock.lock();
     ctx->mSecuring = startEnd;
     //We're done unsecuring
     if(startEnd == IQService::END)
         ctx->mSecureMode = false;
+    ctx->mDrawLock.unlock();
+
     if(ctx->proc)
         ctx->proc->invalidate(ctx->proc);
 }
 
 void QClient::MPDeathNotifier::died() {
-    Locker::Autolock _sl(mHwcContext->mDrawLock);
+    mHwcContext->mDrawLock.lock();
     ALOGD_IF(QCLIENT_DEBUG, "Media Player died");
     mHwcContext->mSecuring = false;
     mHwcContext->mSecureMode = false;
+    mHwcContext->mDrawLock.unlock();
     if(mHwcContext->proc)
         mHwcContext->proc->invalidate(mHwcContext->proc);
 }
@@ -175,13 +181,13 @@
                                         dpy, getExternalDisplayState(status));
 
     if(dpy > HWC_DISPLAY_PRIMARY && dpy <= HWC_DISPLAY_VIRTUAL) {
-        if(dpy == HWC_DISPLAY_VIRTUAL && status == EXTERNAL_OFFLINE) {
+        if(dpy == HWC_DISPLAY_VIRTUAL && status == qdutils::EXTERNAL_OFFLINE) {
             ctx->mWfdSyncLock.lock();
             ctx->mWfdSyncLock.signal();
             ctx->mWfdSyncLock.unlock();
-        } else if(status == EXTERNAL_PAUSE) {
+        } else if(status == qdutils::EXTERNAL_PAUSE) {
             handle_pause(ctx, dpy);
-        } else if(status == EXTERNAL_RESUME) {
+        } else if(status == qdutils::EXTERNAL_RESUME) {
             handle_resume(ctx, dpy);
         }
     } else {
@@ -263,6 +269,75 @@
     }
 }
 
+static void configureDynRefreshRate(hwc_context_t* ctx,
+                                    const Parcel* inParcel) {
+    uint32_t op = (uint32_t)inParcel->readInt32();
+    uint32_t refresh_rate = (uint32_t)inParcel->readInt32();
+    MDPVersion& mdpHw = MDPVersion::getInstance();
+    uint32_t dpy = HWC_DISPLAY_PRIMARY;
+
+    if(mdpHw.isDynFpsSupported()) {
+        Locker::Autolock _sl(ctx->mDrawLock);
+
+        switch (op) {
+        case DISABLE_METADATA_DYN_REFRESH_RATE:
+            ctx->mUseMetaDataRefreshRate = false;
+            setRefreshRate(ctx, dpy, ctx->dpyAttr[dpy].refreshRate);
+            break;
+        case ENABLE_METADATA_DYN_REFRESH_RATE:
+            ctx->mUseMetaDataRefreshRate = true;
+            setRefreshRate(ctx, dpy, ctx->dpyAttr[dpy].refreshRate);
+            break;
+        case SET_BINDER_DYN_REFRESH_RATE:
+            if(ctx->mUseMetaDataRefreshRate)
+                ALOGW("%s: Ignoring binder request to change refresh-rate",
+                      __FUNCTION__);
+            else {
+                uint32_t rate = roundOff(refresh_rate);
+                if((rate >= mdpHw.getMinFpsSupported() &&
+                    rate <= mdpHw.getMaxFpsSupported())) {
+                    setRefreshRate(ctx, dpy, rate);
+                } else {
+                    ALOGE("%s: Requested refresh-rate should be between \
+                          (%d) and (%d). Given (%d)", __FUNCTION__,
+                          mdpHw.getMinFpsSupported(),
+                          mdpHw.getMaxFpsSupported(), rate);
+                }
+            }
+            break;
+        default:
+            ALOGE("%s: Invalid op %d",__FUNCTION__,op);
+        }
+    }
+}
+
+static status_t setPartialUpdatePref(hwc_context_t *ctx, uint32_t enable) {
+    ALOGD("%s: enable: %d", __FUNCTION__, enable);
+    if(qhwc::MDPComp::setPartialUpdatePref(ctx, (bool)enable) < 0)
+        return NO_INIT;
+    return NO_ERROR;
+}
+
+static void toggleScreenUpdate(hwc_context_t* ctx, uint32_t on) {
+    ALOGD("%s: toggle update: %d", __FUNCTION__, on);
+    if (on == 0) {
+        ctx->mDrawLock.lock();
+        ctx->dpyAttr[HWC_DISPLAY_PRIMARY].isPause = true;
+        ctx->mOverlay->configBegin();
+        ctx->mOverlay->configDone();
+        ctx->mRotMgr->clear();
+        if(!Overlay::displayCommit(ctx->dpyAttr[0].fd)) {
+            ALOGE("%s: Display commit failed", __FUNCTION__);
+        }
+        ctx->mDrawLock.unlock();
+    } else {
+        ctx->mDrawLock.lock();
+        ctx->dpyAttr[HWC_DISPLAY_PRIMARY].isPause = false;
+        ctx->mDrawLock.unlock();
+        ctx->proc->invalidate(ctx->proc);
+    }
+}
+
 status_t QClient::notifyCallback(uint32_t command, const Parcel* inParcel,
         Parcel* outParcel) {
     status_t ret = NO_ERROR;
@@ -311,9 +386,18 @@
         case IQService::SET_MAX_PIPES_PER_MIXER:
             setMaxPipesPerMixer(mHwcContext, inParcel);
             break;
+        case IQService::SET_PARTIAL_UPDATE:
+            ret = setPartialUpdatePref(mHwcContext, inParcel->readInt32());
+            break;
         case IQService::TOGGLE_BWC:
             toggleBWC(mHwcContext, inParcel);
             break;
+        case IQService::CONFIGURE_DYN_REFRESH_RATE:
+            configureDynRefreshRate(mHwcContext, inParcel);
+            break;
+        case IQService::TOGGLE_SCREEN_UPDATE:
+            toggleScreenUpdate(mHwcContext, inParcel->readInt32());
+            break;
         default:
             ret = NO_ERROR;
     }
diff --git a/libhwcomposer/hwc_utils.cpp b/libhwcomposer/hwc_utils.cpp
index 300e90a..adb3b9c 100644
--- a/libhwcomposer/hwc_utils.cpp
+++ b/libhwcomposer/hwc_utils.cpp
@@ -81,12 +81,12 @@
 
 namespace qhwc {
 
-//Std refresh rates for digital videos- 24p, 30p and 48p
-uint32_t stdRefreshRates[] = { 30, 24, 48 };
+// Std refresh rates for digital videos- 24p, 30p, 48p and 60p
+uint32_t stdRefreshRates[] = { 30, 24, 48, 60 };
 
 bool isValidResolution(hwc_context_t *ctx, uint32_t xres, uint32_t yres)
 {
-    return !((xres > qdutils::MDPVersion::getInstance().getMaxMixerWidth() &&
+    return !((xres > qdutils::MDPVersion::getInstance().getMaxPipeWidth() &&
                 !isDisplaySplit(ctx, HWC_DISPLAY_PRIMARY)) ||
             (xres < MIN_DISPLAY_XRES || yres < MIN_DISPLAY_YRES));
 }
@@ -406,7 +406,14 @@
         ctx->mWindowboxFeature = true;
     }
 
+    ctx->mUseMetaDataRefreshRate = true;
+    if(property_get("persist.metadata_dynfps.disable", value, "false")
+            && !strcmp(value, "true")) {
+        ctx->mUseMetaDataRefreshRate = false;
+    }
+
     memset(&(ctx->mPtorInfo), 0, sizeof(ctx->mPtorInfo));
+    ctx->mHPDEnabled = false;
     ALOGI("Initializing Qualcomm Hardware Composer");
     ALOGI("MDP version: %d", ctx->mMDP.version);
 }
@@ -465,7 +472,7 @@
 }
 
 //Helper to roundoff the refreshrates
-static uint32_t roundOff(uint32_t refreshRate) {
+uint32_t roundOff(uint32_t refreshRate) {
     int count =  (int) (sizeof(stdRefreshRates)/sizeof(stdRefreshRates[0]));
     uint32_t rate = refreshRate;
     for(int i=0; i< count; i++) {
@@ -487,7 +494,7 @@
     const int fbNum = Overlay::getFbForDpy(dpy);
     char sysfsPath[qdutils::MAX_SYSFS_FILE_PATH];
     snprintf (sysfsPath, sizeof(sysfsPath),
-            "/sys/class/graphics/fb%d/dynamic_fps", fbNum);
+            "/sys/devices/virtual/graphics/fb%d/dynamic_fps", fbNum);
 
     int fd = open(sysfsPath, O_WRONLY);
     if(fd >= 0) {
@@ -1057,7 +1064,7 @@
             ctx->listStats[dpy].preMultipliedAlpha = true;
 
 #ifdef DYNAMIC_FPS
-        if (dpy == HWC_DISPLAY_PRIMARY && mdpHw.isDynFpsSupported()) {
+        if (!dpy && mdpHw.isDynFpsSupported() && ctx->mUseMetaDataRefreshRate){
             //dyn fps: get refreshrate from metadata
             //Support multiple refresh rates if they are same
             //else set to  default
@@ -2232,8 +2239,6 @@
         (*rot) = ctx->mRotMgr->getNext();
         if((*rot) == NULL) return -1;
         ctx->mLayerRotMap[dpy]->add(layer, *rot);
-        BwcPM::setBwc(ctx, dpy, hnd, crop, dst, transform, downscale,
-                mdpFlagsL);
         //Configure rotator for pre-rotation
         if(configRotator(*rot, whf, crop, mdpFlagsL, orient, downscale) < 0) {
             ALOGE("%s: configRotator failed!", __FUNCTION__);
@@ -2347,7 +2352,7 @@
 
 bool isDisplaySplit(hwc_context_t* ctx, int dpy) {
     qdutils::MDPVersion& mdpHw = qdutils::MDPVersion::getInstance();
-    if(ctx->dpyAttr[dpy].xres > mdpHw.getMaxMixerWidth()) {
+    if(ctx->dpyAttr[dpy].xres > mdpHw.getMaxPipeWidth()) {
         return true;
     }
     //For testing we could split primary via device tree values
@@ -2514,7 +2519,7 @@
         swap(src_w, src_h);
     }
     //src width > MAX mixer supported dim
-    if(src_w > (int) qdutils::MDPVersion::getInstance().getMaxMixerWidth()) {
+    if(src_w > (int) qdutils::MDPVersion::getInstance().getMaxPipeWidth()) {
         return;
     }
     //Decimation necessary, cannot use BWC. H/W requirement.
diff --git a/libhwcomposer/hwc_utils.h b/libhwcomposer/hwc_utils.h
index f629574..797f9b0 100644
--- a/libhwcomposer/hwc_utils.h
+++ b/libhwcomposer/hwc_utils.h
@@ -96,7 +96,7 @@
     //It should be active also. (UNBLANKED)
     bool isActive;
     // In pause state, composition is bypassed
-    // used for WFD displays only
+    // used for WFD displays and in QDCM calibration mode
     bool isPause;
     // To trigger padding round to clean up mdp
     // pipes
@@ -326,6 +326,8 @@
 void getAspectRatioPosition(hwc_context_t* ctx, int dpy, int extOrientation,
                                 hwc_rect_t& inRect, hwc_rect_t& outRect);
 
+uint32_t roundOff(uint32_t refreshRate);
+
 void setRefreshRate(hwc_context_t *ctx, int dpy, uint32_t refreshRate);
 
 bool isPrimaryPortrait(hwc_context_t *ctx);
@@ -457,9 +459,9 @@
 
 // Returns true if the buffer is yuv and exceeds the mixer width
 static inline bool isYUVSplitNeeded(const private_handle_t* hnd) {
-    int maxMixerWidth = qdutils::MDPVersion::getInstance().getMaxMixerWidth();
+    int maxPipeWidth = qdutils::MDPVersion::getInstance().getMaxPipeWidth();
     return (hnd && (hnd->bufferType == BUFFER_TYPE_VIDEO) &&
-            (hnd->width > maxMixerWidth));
+            (hnd->width > maxPipeWidth));
 }
 
 // Returns true if the buffer is secure
@@ -477,11 +479,6 @@
     return (hnd && (private_handle_t::PRIV_FLAGS_TILE_RENDERED & hnd->flags));
 }
 
-//Return true if buffer is marked locked
-static inline bool isBufferLocked(const private_handle_t* hnd) {
-    return (hnd && (private_handle_t::PRIV_FLAGS_HWC_LOCK & hnd->flags));
-}
-
 //Return true if the buffer is intended for Secure Display
 static inline bool isSecureDisplayBuffer(const private_handle_t* hnd) {
     return (hnd && (hnd->flags & private_handle_t::PRIV_FLAGS_SECURE_DISPLAY));
@@ -640,6 +637,10 @@
     float mAspectRatioToleranceLevel;
     // Runtime switch for BWC for targets that support it
     bool mBWCEnabled;
+    // Provides a way for OEM's to disable setting dynfps via metadata.
+    bool mUseMetaDataRefreshRate;
+   // Stores the hpd enabled status- avoids re-enabling HDP on suspend resume.
+    bool mHPDEnabled;
 };
 
 namespace qhwc {
diff --git a/libmemtrack/kgsl.c b/libmemtrack/kgsl.c
index 3026175..b120246 100644
--- a/libmemtrack/kgsl.c
+++ b/libmemtrack/kgsl.c
@@ -113,7 +113,7 @@
                 unaccounted_size += size;
 
         } else if (type == MEMTRACK_TYPE_GRAPHICS && strcmp(line_type, "ion") == 0) {
-            if (!is_surfaceflinger || strcmp(line_usage, "egl_image") != 0) {
+            if ( !(is_surfaceflinger == false && strcmp(line_usage, "egl_surface") == 0)) {
                 unaccounted_size += size;
             }
         }
diff --git a/liboverlay/mdpWrapper.h b/liboverlay/mdpWrapper.h
index 349b720..f689e45 100644
--- a/liboverlay/mdpWrapper.h
+++ b/liboverlay/mdpWrapper.h
@@ -72,7 +72,7 @@
 bool setOverlay(int fd, mdp_overlay& ov);
 
 /* MSMFB_OVERLAY_PREPARE */
-bool validateAndSet(const int& fd, mdp_overlay_list& list);
+int validateAndSet(const int& fd, mdp_overlay_list& list);
 
 /* MSM_ROTATOR_IOCTL_FINISH */
 bool endRotator(int fd, int sessionId);
@@ -180,7 +180,7 @@
     return true;
 }
 
-inline bool validateAndSet(const int& fd, mdp_overlay_list& list) {
+inline int validateAndSet(const int& fd, mdp_overlay_list& list) {
     ATRACE_CALL();
     uint32_t id = 0;
     if(UNLIKELY(Overlay::isDebugPipeLifecycle())) {
@@ -198,7 +198,7 @@
     if (ioctl(fd, MSMFB_OVERLAY_PREPARE, &list) < 0) {
         ALOGD_IF(IOCTL_DEBUG, "Failed to call ioctl MSMFB_OVERLAY_PREPARE "
                 "err=%s", strerror(errno));
-        return false;
+        return errno;
     }
 
     if(UNLIKELY(Overlay::isDebugPipeLifecycle())) {
@@ -209,7 +209,7 @@
         ALOGD("%s Pipe mask after OVERLAY_PREPARE 0x%04x", __FUNCTION__, id);
     }
 
-    return true;
+    return 0;
 }
 
 inline bool endRotator(int fd, uint32_t sessionId) {
diff --git a/liboverlay/overlay.cpp b/liboverlay/overlay.cpp
index e9c0a13..c250919 100644
--- a/liboverlay/overlay.cpp
+++ b/liboverlay/overlay.cpp
@@ -47,6 +47,9 @@
 
     initScalar();
     setDMAMultiplexingSupported();
+#ifdef USES_POST_PROCESSING
+    initPostProc();
+#endif
 }
 
 Overlay::~Overlay() {
@@ -54,6 +57,9 @@
         mPipeBook[i].destroy();
     }
     destroyScalar();
+#ifdef USES_POST_PROCESSING
+    destroyPostProc();
+#endif
 }
 
 void Overlay::configBegin() {
@@ -526,6 +532,23 @@
     }
 }
 
+void Overlay::initPostProc() {
+    sLibAblHandle = dlopen("libmm-abl.so", RTLD_NOW);
+    if (sLibAblHandle) {
+        *(void **)&sFnppParams = dlsym(sLibAblHandle,
+                                       "display_pp_compute_params");
+    } else {
+        ALOGE("%s: Not able to load libmm-abl.so", __FUNCTION__);
+    }
+}
+
+void Overlay::destroyPostProc() {
+    if (sLibAblHandle) {
+        dlclose(sLibAblHandle);
+        sLibAblHandle = NULL;
+    }
+}
+
 void Overlay::PipeBook::init() {
     mPipe = NULL;
     mDisplay = DPY_UNUSED;
@@ -557,5 +580,9 @@
     {utils::OV_MDP_PIPE_ANY};
 void *Overlay::sLibScaleHandle = NULL;
 int (*Overlay::sFnProgramScale)(struct mdp_overlay_list *) = NULL;
+/* Dynamically link ABL library */
+void *Overlay::sLibAblHandle = NULL;
+int (*Overlay::sFnppParams)(const struct compute_params *,
+                            struct mdp_overlay_pp_params *) = NULL;
 
 }; // namespace overlay
diff --git a/liboverlay/overlay.h b/liboverlay/overlay.h
index 665e23f..984b439 100644
--- a/liboverlay/overlay.h
+++ b/liboverlay/overlay.h
@@ -33,6 +33,9 @@
 #include "overlayUtils.h"
 #include "mdp_version.h"
 #include "utils/threads.h"
+#ifdef USES_POST_PROCESSING
+#include "lib-postproc.h"
+#endif
 
 struct MetaData_t;
 
@@ -186,6 +189,12 @@
     /* Sets the pipe type RGB/VG/DMA*/
     void setPipeType(utils::eDest pipeIndex, const utils::eMdpPipeType pType);
 
+    /* Dynamically link ABL library */
+    static void initPostProc();
+    static void destroyPostProc();
+    static int (*getFnPpParams())(const struct compute_params *,
+                                 struct mdp_overlay_pp_params *);
+
     /* Just like a Facebook for pipes, but much less profile info */
     struct PipeBook {
         void init();
@@ -251,6 +260,10 @@
     static bool sDMAMultiplexingSupported;
     static void *sLibScaleHandle;
     static int (*sFnProgramScale)(struct mdp_overlay_list *);
+    /* Dynamically link ABL library */
+    static void *sLibAblHandle;
+    static int (*sFnppParams)(const struct compute_params *,
+                            struct mdp_overlay_pp_params *);
     static bool sDebugPipeLifecycle;
 
     friend class MdpCtrl;
@@ -345,6 +358,11 @@
     return sFnProgramScale;
 }
 
+inline int (*Overlay::getFnPpParams())(const struct compute_params *,
+                    struct mdp_overlay_pp_params *) {
+    return sFnppParams;
+}
+
 inline void Overlay::debugPipeLifecycle(const bool& enable) {
     sDebugPipeLifecycle = enable;
 }
diff --git a/liboverlay/overlayMdp.cpp b/liboverlay/overlayMdp.cpp
index b8bb33e..3932c4c 100644
--- a/liboverlay/overlayMdp.cpp
+++ b/liboverlay/overlayMdp.cpp
@@ -21,6 +21,7 @@
 #include "overlayMdp.h"
 #include "mdp_version.h"
 #include <overlay.h>
+#include <dlfcn.h>
 
 #define HSIC_SETTINGS_DEBUG 0
 
@@ -263,7 +264,7 @@
         }
 
         if (needUpdate) {
-            mParams.params.pa_params.hue = data.hsicData.hue;
+            mParams.params.pa_params.hue = (float)data.hsicData.hue;
             mParams.params.pa_params.sat = data.hsicData.saturation;
             mParams.params.pa_params.intensity = data.hsicData.intensity;
             mParams.params.pa_params.contrast = data.hsicData.contrast;
@@ -333,7 +334,15 @@
     }
 
     if (needUpdate) {
-        display_pp_compute_params(&mParams, &mOVInfo.overlay_pp_cfg);
+        int (*sFnppParams)(const struct compute_params *,
+                           struct mdp_overlay_pp_params *) =
+                           Overlay::getFnPpParams();
+        if(sFnppParams) {
+           int ret = sFnppParams(&mParams, &mOVInfo.overlay_pp_cfg);
+           if (ret) {
+             ALOGE("%s: Unable to set PP params", __FUNCTION__);
+           }
+        }
     }
 #endif
     return true;
@@ -359,9 +368,12 @@
         fnProgramScale(&list);
     }
 
-    if(!mdp_wrapper::validateAndSet(fbFd, list)) {
+    // Error value is based on file errno-base.h
+    // 0 - indicates no error.
+    int errVal = mdp_wrapper::validateAndSet(fbFd, list);
+    if(errVal) {
         /* No dump for failure due to insufficient resource */
-        if(errno != E2BIG) {
+        if(errVal != E2BIG) {
             mdp_wrapper::dump("Bad ov dump: ",
                 *list.overlay_list[list.processed_overlays]);
         }
diff --git a/liboverlay/overlayUtils.cpp b/liboverlay/overlayUtils.cpp
index 32b2013..dd030ef 100644
--- a/liboverlay/overlayUtils.cpp
+++ b/liboverlay/overlayUtils.cpp
@@ -277,13 +277,14 @@
     if((int)verDscale)
         vertDeci = (uint8_t)log2f(verDscale);
 
-    if(src_w > (int) mdpHw.getMaxMixerWidth()) {
+    if(src_w > (int) mdpHw.getMaxPipeWidth()) {
         //If the client sends us something > what a layer mixer supports
         //then it means it doesn't want to use split-pipe but wants us to
-        //decimate. A minimum decimation of 2 will ensure that the width is
+        //decimate. A minimum decimation of 1 will ensure that the width is
         //always within layer mixer limits.
-        if(horzDeci < 2)
-            horzDeci = 2;
+        const uint8_t minDeci = 1;
+        if(horzDeci < minDeci)
+            horzDeci = minDeci;
     }
 }
 
diff --git a/libqdutils/display_config.cpp b/libqdutils/display_config.cpp
index 4fdf19e..03a7046 100644
--- a/libqdutils/display_config.cpp
+++ b/libqdutils/display_config.cpp
@@ -152,6 +152,24 @@
     return err;
 }
 
+int configureDynRefreshRate(uint32_t op, uint32_t refreshRate) {
+    status_t err = (status_t) FAILED_TRANSACTION;
+    sp<IQService> binder = getBinder();
+    Parcel inParcel, outParcel;
+    inParcel.writeInt32(op);
+    inParcel.writeInt32(refreshRate);
+
+    if(binder != NULL) {
+        err = binder->dispatch(IQService::CONFIGURE_DYN_REFRESH_RATE,
+                               &inParcel, &outParcel);
+    }
+
+    if(err)
+        ALOGE("%s: Failed setting op %d err=%d", __FUNCTION__, op, err);
+
+    return err;
+}
+
 }; //namespace
 
 // ----------------------------------------------------------------------------
diff --git a/libqdutils/display_config.h b/libqdutils/display_config.h
index 9b6ab56..8bafe91 100644
--- a/libqdutils/display_config.h
+++ b/libqdutils/display_config.h
@@ -39,6 +39,12 @@
 
 namespace qdutils {
 
+
+/* TODO: Have all the common enums that need be exposed to clients and which
+ * are also needed in hwc defined here. Remove such definitions we have in
+ * hwc_utils.h
+ */
+
 // Use this enum to specify the dpy parameters where needed
 enum {
     DISPLAY_PRIMARY = 0,
@@ -55,6 +61,12 @@
     EXTERNAL_RESUME,
 };
 
+enum {
+    DISABLE_METADATA_DYN_REFRESH_RATE = 0,
+    ENABLE_METADATA_DYN_REFRESH_RATE,
+    SET_BINDER_DYN_REFRESH_RATE,
+};
+
 // 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)
 struct DisplayAttributes_t {
@@ -89,4 +101,7 @@
 
 // Set the secondary display status(pause/resume/offline etc.,)
 int setSecondaryDisplayStatus(int dpy, uint32_t status);
+
+// Enable/Disable/Set refresh rate dynamically
+int configureDynRefreshRate(uint32_t op, uint32_t refreshRate);
 }; //namespace
diff --git a/libqdutils/mdp_version.cpp b/libqdutils/mdp_version.cpp
index f8729a5..402e129 100644
--- a/libqdutils/mdp_version.cpp
+++ b/libqdutils/mdp_version.cpp
@@ -75,7 +75,7 @@
 #define MDSS_MDP_HW_REV_109 0x10090000 //8994 v2
 #endif
 #ifndef MDSS_MDP_HW_REV_110
-#define MDSS_MDP_HW_REV_110 0x100a0000 //Next version
+#define MDSS_MDP_HW_REV_110 0x100a0000 //8992
 #endif
 #ifndef MDSS_MDP_HW_REV_200
 #define MDSS_MDP_HW_REV_200 0x20000000 //8092
@@ -101,12 +101,16 @@
     mSourceSplitAlways = false;
     mRGBHasNoScalar = false;
     mRotDownscale = false;
-    mBlendStages = 6; //min no. of stages supported by MDP.
+    mBlendStages = 4; //min no. of stages supported by MDP.
 
     // this is the default limit of mixer unless driver reports it.
-    // For resolutions beyond this, we use dual/split overlay pipes.
+    // For resolutions beyond this, we use dual mixer/ping pong split.
     mMaxMixerWidth = 2048;
 
+    // Default width of MDSS SSPP. For layer resolutions beyond this, we drive
+    // using two SSPP's.
+    mMaxPipeWidth = 2048;
+
     updatePanelInfo();
 
     if(!updateSysFsInfo()) {
@@ -324,6 +328,9 @@
                 } else if(!strncmp(tokens[0], "max_mixer_width",
                         strlen("max_mixer_width"))) {
                     mMaxMixerWidth = atoi(tokens[1]);
+                } else if(!strncmp(tokens[0], "max_pipe_width",
+                        strlen("max_pipe_width"))) {
+                    mMaxPipeWidth = atoi(tokens[1]);
                 } else if(!strncmp(tokens[0], "features", strlen("features"))) {
                     for(int i=1; i<index;i++) {
                         if(!strncmp(tokens[i], "bwc", strlen("bwc"))) {
diff --git a/libqdutils/mdp_version.h b/libqdutils/mdp_version.h
index dcde240..3b10010 100644
--- a/libqdutils/mdp_version.h
+++ b/libqdutils/mdp_version.h
@@ -139,6 +139,7 @@
     uint32_t getMinFpsSupported() { return mPanelInfo.mMinFps; }
     uint32_t getMaxFpsSupported() { return mPanelInfo.mMaxFps; }
     uint32_t getMaxMixerWidth() const { return mMaxMixerWidth; }
+    uint32_t getMaxPipeWidth() const { return mMaxPipeWidth; }
     bool hasMinCropWidthLimitation() const;
     bool isSrcSplit() const;
     bool isSrcSplitAlways() const;
@@ -179,6 +180,7 @@
     bool mRGBHasNoScalar;
     bool mRotDownscale;
     uint32_t mMaxMixerWidth; //maximum x-res of a given mdss mixer.
+    uint32_t mMaxPipeWidth; //maximum x-res of the mdp pipe.
 };
 }; //namespace qdutils
 #endif //INCLUDE_LIBQCOMUTILS_MDPVER
diff --git a/libqservice/IQService.h b/libqservice/IQService.h
index ea40334..ef47475 100644
--- a/libqservice/IQService.h
+++ b/libqservice/IQService.h
@@ -55,6 +55,10 @@
         DYNAMIC_DEBUG = 15,     // Enable more logging on the fly
         SET_IDLE_TIMEOUT = 16,  // Set idle timeout for GPU fallback
         TOGGLE_BWC = 17,           // Toggle BWC On/Off on targets that support
+        /* Enable/Disable/Set refresh rate dynamically */
+        CONFIGURE_DYN_REFRESH_RATE = 18,
+        SET_PARTIAL_UPDATE = 19,   // Preference on partial update feature
+        TOGGLE_SCREEN_UPDATE = 20, // Provides ability to disable screen updates
         COMMAND_LIST_END = 400,
     };
 
diff --git a/libqservice/QServiceUtils.h b/libqservice/QServiceUtils.h
index f53d140..71277e8 100644
--- a/libqservice/QServiceUtils.h
+++ b/libqservice/QServiceUtils.h
@@ -74,6 +74,14 @@
     return sendSingleParam(qService::IQService::SCREEN_REFRESH, 1);
 }
 
+inline android::status_t toggleScreenUpdate(uint32_t on) {
+    return sendSingleParam(qService::IQService::TOGGLE_SCREEN_UPDATE, on);
+}
+
+inline android::status_t setPartialUpdate(uint32_t enable) {
+    return sendSingleParam(qService::IQService::SET_PARTIAL_UPDATE, enable);
+}
+
 inline android::status_t setExtOrientation(uint32_t orientation) {
     return sendSingleParam(qService::IQService::EXTERNAL_ORIENTATION,
             orientation);