sdm: Align to new SDM design.

- Align code base to new SDM design.

Change-Id: I38d7d138ae704cf036e2b96c16453aea63bc333f
diff --git a/sdm/libs/core/Android.mk b/sdm/libs/core/Android.mk
new file mode 100644
index 0000000..8831c3f
--- /dev/null
+++ b/sdm/libs/core/Android.mk
@@ -0,0 +1,30 @@
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE                  := libsdmcore
+LOCAL_MODULE_TAGS             := optional
+LOCAL_C_INCLUDES              := hardware/qcom/display/sdm/include/ \
+                                 $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr/include
+LOCAL_CFLAGS                  := -Wno-missing-field-initializers -Wno-unused-parameter \
+                                 -Wconversion -Wall -Werror \
+                                 -DLOG_TAG=\"SDM\"
+LOCAL_HW_INTF_PATH            := fb
+LOCAL_SHARED_LIBRARIES        := libdl libsdmutils
+LOCAL_ADDITIONAL_DEPENDENCIES := $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr
+LOCAL_SRC_FILES               := core_interface.cpp \
+                                 core_impl.cpp \
+                                 display_base.cpp \
+                                 display_primary.cpp \
+                                 display_hdmi.cpp \
+                                 display_virtual.cpp \
+                                 comp_manager.cpp \
+                                 strategy.cpp \
+                                 resource_default.cpp \
+                                 dump_impl.cpp \
+                                 $(LOCAL_HW_INTF_PATH)/hw_info.cpp \
+                                 $(LOCAL_HW_INTF_PATH)/hw_device.cpp \
+                                 $(LOCAL_HW_INTF_PATH)/hw_primary.cpp \
+                                 $(LOCAL_HW_INTF_PATH)/hw_hdmi.cpp \
+                                 $(LOCAL_HW_INTF_PATH)/hw_virtual.cpp
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/sdm/libs/core/comp_manager.cpp b/sdm/libs/core/comp_manager.cpp
new file mode 100644
index 0000000..69e3ec7
--- /dev/null
+++ b/sdm/libs/core/comp_manager.cpp
@@ -0,0 +1,359 @@
+/*
+* 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:
+*    * 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 <utils/debug.h>
+#include <core/buffer_allocator.h>
+
+#include "comp_manager.h"
+#include "strategy.h"
+
+#define __CLASS__ "CompManager"
+
+namespace sdm {
+
+CompManager::CompManager()
+  : resource_intf_(NULL), registered_displays_(0), configured_displays_(0), safe_mode_(false),
+    extension_intf_(NULL) {
+}
+
+DisplayError CompManager::Init(const HWResourceInfo &hw_res_info,
+                               ExtensionInterface *extension_intf) {
+  SCOPE_LOCK(locker_);
+
+  DisplayError error = kErrorNone;
+
+  if (extension_intf) {
+    error = extension_intf->CreateResourceExtn(hw_res_info, &resource_intf_);
+  } else {
+    resource_intf_ = &resource_default_;
+    error = resource_default_.Init(hw_res_info);
+  }
+
+  if (error != kErrorNone) {
+    return error;
+  }
+
+  hw_res_info_ = hw_res_info;
+  extension_intf_ = extension_intf;
+
+  return error;
+}
+
+DisplayError CompManager::Deinit() {
+  SCOPE_LOCK(locker_);
+
+  if (extension_intf_) {
+    extension_intf_->DestroyResourceExtn(resource_intf_);
+  } else {
+    resource_default_.Deinit();
+  }
+
+  return kErrorNone;
+}
+
+DisplayError CompManager::RegisterDisplay(DisplayType type, const HWDisplayAttributes &attributes,
+                                          const HWPanelInfo &hw_panel_info, Handle *display_ctx) {
+  SCOPE_LOCK(locker_);
+
+  DisplayError error = kErrorNone;
+
+  DisplayCompositionContext *display_comp_ctx = new DisplayCompositionContext();
+  if (!display_comp_ctx) {
+    return kErrorMemory;
+  }
+
+  Strategy *&strategy = display_comp_ctx->strategy;
+  strategy = new Strategy(extension_intf_, type, hw_res_info_, hw_panel_info);
+  if (!strategy) {
+    DLOGE("Unable to create strategy");
+    delete display_comp_ctx;
+    return kErrorMemory;
+  }
+
+  error = strategy->Init();
+  if (error != kErrorNone) {
+    delete strategy;
+    delete display_comp_ctx;
+    return error;
+  }
+
+  error = resource_intf_->RegisterDisplay(type, attributes, hw_panel_info,
+                                          &display_comp_ctx->display_resource_ctx);
+  if (error != kErrorNone) {
+    strategy->Deinit();
+    delete strategy;
+    delete display_comp_ctx;
+    display_comp_ctx = NULL;
+    return error;
+  }
+
+  SET_BIT(registered_displays_, type);
+  display_comp_ctx->display_type = type;
+  *display_ctx = display_comp_ctx;
+  // New non-primary display device has been added, so move the composition mode to safe mode until
+  // resources for the added display is configured properly.
+  if (type != kPrimary) {
+    safe_mode_ = true;
+  }
+
+  DLOGV_IF(kTagCompManager, "registered display bit mask 0x%x, configured display bit mask 0x%x, " \
+           "display type %d", registered_displays_, configured_displays_,
+           display_comp_ctx->display_type);
+
+  return kErrorNone;
+}
+
+DisplayError CompManager::UnregisterDisplay(Handle comp_handle) {
+  SCOPE_LOCK(locker_);
+
+  DisplayCompositionContext *display_comp_ctx =
+                             reinterpret_cast<DisplayCompositionContext *>(comp_handle);
+
+  if (!display_comp_ctx) {
+    return kErrorParameters;
+  }
+
+  resource_intf_->UnregisterDisplay(display_comp_ctx->display_resource_ctx);
+
+  Strategy *&strategy = display_comp_ctx->strategy;
+  strategy->Deinit();
+  delete strategy;
+
+  CLEAR_BIT(registered_displays_, display_comp_ctx->display_type);
+  CLEAR_BIT(configured_displays_, display_comp_ctx->display_type);
+
+  DLOGV_IF(kTagCompManager, "registered display bit mask 0x%x, configured display bit mask 0x%x, " \
+           "display type %d", registered_displays_, configured_displays_,
+           display_comp_ctx->display_type);
+
+  delete display_comp_ctx;
+  display_comp_ctx = NULL;
+  return kErrorNone;
+}
+
+void CompManager::ReconfigureDisplay(Handle comp_handle, const HWDisplayAttributes &attributes,
+                                     const HWPanelInfo &hw_panel_info) {
+  DisplayCompositionContext *display_comp_ctx =
+                             reinterpret_cast<DisplayCompositionContext *>(comp_handle);
+
+  resource_intf_->ReconfigureDisplay(display_comp_ctx->display_resource_ctx, attributes,
+                                     hw_panel_info);
+
+  // TODO(user): Need to reconfigure strategy with updated panel info
+}
+
+void CompManager::PrepareStrategyConstraints(Handle comp_handle, HWLayers *hw_layers) {
+  DisplayCompositionContext *display_comp_ctx =
+                             reinterpret_cast<DisplayCompositionContext *>(comp_handle);
+  StrategyConstraints *constraints = &display_comp_ctx->constraints;
+
+  constraints->safe_mode = safe_mode_;
+
+  // Limit 2 layer SDE Comp on HDMI/Virtual
+  if (display_comp_ctx->display_type != kPrimary) {
+    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;
+  }
+
+  if (display_comp_ctx->idle_fallback || display_comp_ctx->fallback_) {
+    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->Start(&hw_layers->info, &display_comp_ctx->max_strategies);
+  display_comp_ctx->remaining_strategies = display_comp_ctx->max_strategies;
+
+  // Avoid idle fallback, if there is only one app layer.
+  // TODO(user): App layer count will change for hybrid composition
+  uint32_t app_layer_count = hw_layers->info.stack->layer_count - 1;
+  if (!display_comp_ctx->idle_fallback && app_layer_count > 1) {
+    display_comp_ctx->handle_idle_timeout = true;
+  }
+}
+
+DisplayError CompManager::Prepare(Handle display_ctx, HWLayers *hw_layers) {
+  SCOPE_LOCK(locker_);
+
+  DisplayCompositionContext *display_comp_ctx =
+                             reinterpret_cast<DisplayCompositionContext *>(display_ctx);
+  Handle &display_resource_ctx = display_comp_ctx->display_resource_ctx;
+
+  DisplayError error = kErrorUndefined;
+
+  PrepareStrategyConstraints(display_ctx, hw_layers);
+
+  // Select a composition strategy, and try to allocate resources for it.
+  resource_intf_->Start(display_resource_ctx);
+
+  bool exit = false;
+  uint32_t &count = display_comp_ctx->remaining_strategies;
+  for (; !exit && count > 0; count--) {
+    error = display_comp_ctx->strategy->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.
+      exit = true;
+    }
+
+    if (!exit) {
+      error = resource_intf_->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);
+  }
+
+  resource_intf_->Stop(display_resource_ctx);
+
+  return error;
+}
+
+DisplayError CompManager::PostPrepare(Handle display_ctx, HWLayers *hw_layers) {
+  SCOPE_LOCK(locker_);
+  DisplayCompositionContext *display_comp_ctx =
+                             reinterpret_cast<DisplayCompositionContext *>(display_ctx);
+  Handle &display_resource_ctx = display_comp_ctx->display_resource_ctx;
+
+  DisplayError error = kErrorNone;
+  error = resource_intf_->PostPrepare(display_resource_ctx, hw_layers);
+  if (error != kErrorNone) {
+    return error;
+  }
+
+  display_comp_ctx->strategy->Stop();
+
+  return kErrorNone;
+}
+
+DisplayError CompManager::PostCommit(Handle display_ctx, HWLayers *hw_layers) {
+  SCOPE_LOCK(locker_);
+
+  DisplayError error = kErrorNone;
+  DisplayCompositionContext *display_comp_ctx =
+                             reinterpret_cast<DisplayCompositionContext *>(display_ctx);
+  SET_BIT(configured_displays_, display_comp_ctx->display_type);
+  if (configured_displays_ == registered_displays_) {
+      safe_mode_ = false;
+  }
+
+  error = resource_intf_->PostCommit(display_comp_ctx->display_resource_ctx, hw_layers);
+  if (error != kErrorNone) {
+    return error;
+  }
+
+  display_comp_ctx->idle_fallback = false;
+
+  DLOGV_IF(kTagCompManager, "registered display bit mask 0x%x, configured display bit mask 0x%x, " \
+           "display type %d", registered_displays_, configured_displays_,
+           display_comp_ctx->display_type);
+
+  return kErrorNone;
+}
+
+void CompManager::Purge(Handle display_ctx) {
+  SCOPE_LOCK(locker_);
+
+  DisplayCompositionContext *display_comp_ctx =
+                             reinterpret_cast<DisplayCompositionContext *>(display_ctx);
+
+  resource_intf_->Purge(display_comp_ctx->display_resource_ctx);
+}
+
+bool CompManager::ProcessIdleTimeout(Handle display_ctx) {
+  SCOPE_LOCK(locker_);
+
+  DisplayCompositionContext *display_comp_ctx =
+                             reinterpret_cast<DisplayCompositionContext *>(display_ctx);
+
+  if (!display_comp_ctx) {
+    return false;
+  }
+
+  // 1. handle_idle_timeout flag is set to true on start of every draw call, if the current
+  //    composition is not due to idle fallback.
+  // 2. idle_fallback flag will be set only if handle_idle_timeout flag is true and there is no
+  //    update to the screen for specified amount of time.
+  // 3. handle_idle_timeout flag helps us handle the very first idle timeout event and
+  //    ignore the next idle timeout event on consecutive two idle timeout events.
+  if (display_comp_ctx->handle_idle_timeout) {
+    display_comp_ctx->idle_fallback = true;
+    display_comp_ctx->handle_idle_timeout = false;
+
+    return true;
+  }
+
+  return false;
+}
+
+void CompManager::ProcessThermalEvent(Handle display_ctx, int64_t thermal_level) {
+  SCOPE_LOCK(locker_);
+
+  DisplayCompositionContext *display_comp_ctx =
+          reinterpret_cast<DisplayCompositionContext *>(display_ctx);
+
+  if (thermal_level >= kMaxThermalLevel) {
+    display_comp_ctx->fallback_ = true;
+  } else {
+    display_comp_ctx->fallback_ = false;
+  }
+}
+
+DisplayError CompManager::SetMaxMixerStages(Handle display_ctx, uint32_t max_mixer_stages) {
+  SCOPE_LOCK(locker_);
+
+  DisplayError error = kErrorNone;
+  DisplayCompositionContext *display_comp_ctx =
+                             reinterpret_cast<DisplayCompositionContext *>(display_ctx);
+
+  if (display_comp_ctx) {
+    error = resource_intf_->SetMaxMixerStages(display_comp_ctx->display_resource_ctx,
+                                              max_mixer_stages);
+  }
+
+  return error;
+}
+
+void CompManager::AppendDump(char *buffer, uint32_t length) {
+  SCOPE_LOCK(locker_);
+}
+
+DisplayError CompManager::ValidateScaling(const LayerRect &crop, const LayerRect &dst,
+                                          bool rotate90) {
+  return resource_intf_->ValidateScaling(crop, dst, rotate90);
+}
+
+}  // namespace sdm
+
diff --git a/sdm/libs/core/comp_manager.h b/sdm/libs/core/comp_manager.h
new file mode 100644
index 0000000..f48beed
--- /dev/null
+++ b/sdm/libs/core/comp_manager.h
@@ -0,0 +1,99 @@
+/*
+* 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:
+*    * Redistributions of source code must retain the above copyright notice, this list of
+*      conditions and the following disclaimer.
+*    * Redistributions in binary form must reproduce the above copyright notice, this list of
+*      conditions and the following disclaimer in the documentation and/or other materials provided
+*      with the distribution.
+*    * Neither the name of The Linux Foundation nor the names of its contributors may be used to
+*      endorse or promote products derived from this software without specific prior written
+*      permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef __COMP_MANAGER_H__
+#define __COMP_MANAGER_H__
+
+#include <core/display_interface.h>
+#include <private/extension_interface.h>
+#include <utils/locker.h>
+
+#include "strategy.h"
+#include "resource_default.h"
+#include "hw_interface.h"
+#include "dump_impl.h"
+
+namespace sdm {
+
+class CompManager : public DumpImpl {
+ public:
+  CompManager();
+  DisplayError Init(const HWResourceInfo &hw_res_info_, ExtensionInterface *extension_intf);
+  DisplayError Deinit();
+  DisplayError RegisterDisplay(DisplayType type, const HWDisplayAttributes &attributes,
+                               const HWPanelInfo &hw_panel_info, Handle *res_mgr_hnd);
+  DisplayError UnregisterDisplay(Handle res_mgr_hnd);
+  void ReconfigureDisplay(Handle display_ctx, const HWDisplayAttributes &attributes,
+                          const HWPanelInfo &hw_panel_info);
+  void PrePrepare(Handle display_ctx, HWLayers *hw_layers);
+  DisplayError Prepare(Handle display_ctx, HWLayers *hw_layers);
+  DisplayError PostPrepare(Handle display_ctx, HWLayers *hw_layers);
+  DisplayError PostCommit(Handle display_ctx, HWLayers *hw_layers);
+  void Purge(Handle display_ctx);
+  bool ProcessIdleTimeout(Handle display_ctx);
+  void ProcessThermalEvent(Handle display_ctx, int64_t thermal_level);
+  DisplayError SetMaxMixerStages(Handle display_ctx, uint32_t max_mixer_stages);
+  DisplayError ValidateScaling(const LayerRect &crop, const LayerRect &dst, bool rotate90);
+
+  // DumpImpl method
+  virtual void AppendDump(char *buffer, uint32_t length);
+
+ private:
+  static const int kMaxThermalLevel = 3;
+
+  void PrepareStrategyConstraints(Handle display_ctx, HWLayers *hw_layers);
+
+  struct DisplayCompositionContext {
+    Strategy *strategy;
+    StrategyConstraints constraints;
+    Handle display_resource_ctx;
+    DisplayType display_type;
+    uint32_t max_strategies;
+    uint32_t remaining_strategies;
+    bool idle_fallback;
+    bool handle_idle_timeout;
+    bool fallback_;
+
+    DisplayCompositionContext()
+      : display_resource_ctx(NULL), display_type(kPrimary), max_strategies(0),
+        remaining_strategies(0), idle_fallback(false), handle_idle_timeout(true),
+        fallback_(false) { }
+  };
+
+  Locker locker_;
+  ResourceInterface *resource_intf_;
+  ResourceDefault resource_default_;
+  uint64_t registered_displays_;        // Stores the bit mask of registered displays
+  uint64_t configured_displays_;        // Stores the bit mask of sucessfully configured displays
+  bool safe_mode_;                      // Flag to notify all displays to be in resource crunch
+                                        // mode, where strategy manager chooses the best strategy
+                                        // that uses optimal number of pipes for each display
+  HWResourceInfo hw_res_info_;
+  ExtensionInterface *extension_intf_;
+};
+
+}  // namespace sdm
+
+#endif  // __COMP_MANAGER_H__
+
diff --git a/sdm/libs/core/core_impl.cpp b/sdm/libs/core/core_impl.cpp
new file mode 100644
index 0000000..f017d8d
--- /dev/null
+++ b/sdm/libs/core/core_impl.cpp
@@ -0,0 +1,208 @@
+/*
+* 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:
+*    * 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 <dlfcn.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"
+#include "hw_info_interface.h"
+
+#define __CLASS__ "CoreImpl"
+
+namespace sdm {
+
+CoreImpl::CoreImpl(CoreEventHandler *event_handler, BufferAllocator *buffer_allocator,
+                   BufferSyncHandler *buffer_sync_handler)
+  : event_handler_(event_handler), buffer_allocator_(buffer_allocator),
+    buffer_sync_handler_(buffer_sync_handler), hw_resource_(NULL), hw_info_intf_(NULL),
+    rotator_intf_(NULL), extension_lib_(NULL), extension_intf_(NULL),
+    create_extension_intf_(NULL), destroy_extension_intf_(NULL) {
+}
+
+DisplayError CoreImpl::Init() {
+  SCOPE_LOCK(locker_);
+  DisplayError error = kErrorNone;
+
+  // Try to load extension library & get handle to its interface.
+  extension_lib_ = ::dlopen(EXTENSION_LIBRARY_NAME, RTLD_NOW);
+  if (extension_lib_) {
+    void **create_sym = reinterpret_cast<void **>(&create_extension_intf_);
+    void **destroy_sym = reinterpret_cast<void **>(&destroy_extension_intf_);
+
+    *create_sym = ::dlsym(extension_lib_, CREATE_EXTENSION_INTERFACE_NAME);
+    *destroy_sym = ::dlsym(extension_lib_, DESTROY_EXTENSION_INTERFACE_NAME);
+
+    if (!create_extension_intf_ || !destroy_extension_intf_) {
+      DLOGE("Unable to load symbols");
+      ::dlclose(extension_lib_);
+      return kErrorUndefined;
+    }
+
+    error = create_extension_intf_(EXTENSION_VERSION_TAG, &extension_intf_);
+    if(error != kErrorNone) {
+      DLOGE("Unable to create interface");
+      ::dlclose(extension_lib_);
+      return error;
+    }
+  } else {
+    DLOGW("Unable to load = %s", EXTENSION_LIBRARY_NAME);
+  }
+
+  error = HWInfoInterface::Create(&hw_info_intf_);
+  if (error != kErrorNone) {
+    goto CleanupOnError;
+  }
+
+  hw_resource_ = new HWResourceInfo();
+  if (!hw_resource_) {
+    error = kErrorMemory;
+    goto CleanupOnError;
+  }
+
+  error = hw_info_intf_->GetHWResourceInfo(hw_resource_);
+  if (error != kErrorNone) {
+    goto CleanupOnError;
+  }
+
+  error = comp_mgr_.Init(*hw_resource_, extension_intf_);
+  if (error != kErrorNone) {
+    goto CleanupOnError;
+  }
+
+  if (extension_intf_) {
+    error = extension_intf_->CreateRotator(buffer_allocator_, buffer_sync_handler_,
+                                           &rotator_intf_);
+    if (error != kErrorNone) {
+      comp_mgr_.Deinit();
+      goto CleanupOnError;
+    }
+  }
+
+  return kErrorNone;
+
+CleanupOnError:
+  if (hw_info_intf_) {
+    HWInfoInterface::Destroy(hw_info_intf_);
+  }
+
+  if (hw_resource_) {
+    delete hw_resource_;
+  }
+
+  if (extension_lib_) {
+    destroy_extension_intf_(extension_intf_);
+    ::dlclose(extension_lib_);
+  }
+
+  return error;
+}
+
+DisplayError CoreImpl::Deinit() {
+  SCOPE_LOCK(locker_);
+
+  if (extension_intf_) {
+    extension_intf_->DestroyRotator(rotator_intf_);
+  }
+
+  comp_mgr_.Deinit();
+  HWInfoInterface::Destroy(hw_info_intf_);
+
+  if (hw_resource_) {
+    delete hw_resource_;
+  }
+
+  if (extension_lib_) {
+    destroy_extension_intf_(extension_intf_);
+    ::dlclose(extension_lib_);
+  }
+
+  return kErrorNone;
+}
+
+DisplayError CoreImpl::CreateDisplay(DisplayType type, DisplayEventHandler *event_handler,
+                                     DisplayInterface **intf) {
+  SCOPE_LOCK(locker_);
+
+  if (!event_handler || !intf) {
+    return kErrorParameters;
+  }
+
+  DisplayBase *display_base = NULL;
+
+  switch (type) {
+  case kPrimary:
+    display_base = new DisplayPrimary(event_handler, hw_info_intf_, buffer_sync_handler_,
+                                      &comp_mgr_, rotator_intf_);
+    break;
+  case kHDMI:
+    display_base = new DisplayHDMI(event_handler, hw_info_intf_, buffer_sync_handler_,
+                                   &comp_mgr_, rotator_intf_);
+    break;
+  case kVirtual:
+    display_base = new DisplayVirtual(event_handler, hw_info_intf_, buffer_sync_handler_,
+                                      &comp_mgr_, rotator_intf_);
+    break;
+  default:
+    DLOGE("Spurious display type %d", type);
+    return kErrorParameters;
+  }
+
+  if (!display_base) {
+    return kErrorMemory;
+  }
+
+  DisplayError error = display_base->Init();
+  if (error != kErrorNone) {
+    display_base->Deinit();
+    delete display_base;
+    display_base = NULL;
+    return error;
+  }
+
+  *intf = display_base;
+  return kErrorNone;
+}
+
+DisplayError CoreImpl::DestroyDisplay(DisplayInterface *intf) {
+  SCOPE_LOCK(locker_);
+
+  if (!intf) {
+    return kErrorParameters;
+  }
+
+  DisplayBase *display_base = static_cast<DisplayBase *>(intf);
+  display_base->Deinit();
+  delete display_base;
+  display_base = NULL;
+
+  return kErrorNone;
+}
+
+}  // namespace sdm
+
diff --git a/sdm/libs/core/core_impl.h b/sdm/libs/core/core_impl.h
new file mode 100644
index 0000000..bad241c
--- /dev/null
+++ b/sdm/libs/core/core_impl.h
@@ -0,0 +1,80 @@
+/*
+* 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:
+*    * Redistributions of source code must retain the above copyright notice, this list of
+*      conditions and the following disclaimer.
+*    * Redistributions in binary form must reproduce the above copyright notice, this list of
+*      conditions and the following disclaimer in the documentation and/or other materials provided
+*      with the distribution.
+*    * Neither the name of The Linux Foundation nor the names of its contributors may be used to
+*      endorse or promote products derived from this software without specific prior written
+*      permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef __CORE_IMPL_H__
+#define __CORE_IMPL_H__
+
+#include <core/core_interface.h>
+#include <private/extension_interface.h>
+#include <utils/locker.h>
+
+#include "hw_interface.h"
+#include "comp_manager.h"
+
+#define SET_REVISION(major, minor) ((major << 8) | minor)
+
+namespace sdm {
+
+class HWInfoInterface;
+class RotatorCtrl;
+
+class CoreImpl : public CoreInterface {
+ public:
+  // This class implements display core interface revision 1.0.
+  static const uint16_t kRevision = SET_REVISION(1, 0);
+
+  CoreImpl(CoreEventHandler *event_handler, BufferAllocator *buffer_allocator,
+           BufferSyncHandler *buffer_sync_handler);
+  virtual ~CoreImpl() { }
+
+  // This method returns the interface revision for the current display core object.
+  // Future revisions will override this method and return the appropriate revision upon query.
+  virtual uint16_t GetRevision() { return kRevision; }
+  virtual DisplayError Init();
+  virtual DisplayError Deinit();
+
+  // Methods from core interface
+  virtual DisplayError CreateDisplay(DisplayType type, DisplayEventHandler *event_handler,
+                                     DisplayInterface **intf);
+  virtual DisplayError DestroyDisplay(DisplayInterface *intf);
+
+ protected:
+  Locker locker_;
+  CoreEventHandler *event_handler_;
+  BufferAllocator *buffer_allocator_;
+  BufferSyncHandler *buffer_sync_handler_;
+  HWResourceInfo *hw_resource_;
+  CompManager comp_mgr_;
+  HWInfoInterface *hw_info_intf_;
+  RotatorInterface *rotator_intf_;
+  void *extension_lib_;
+  ExtensionInterface *extension_intf_;
+  CreateExtensionInterface create_extension_intf_;
+  DestroyExtensionInterface destroy_extension_intf_;
+};
+
+}  // namespace sdm
+
+#endif  // __CORE_IMPL_H__
+
diff --git a/sdm/libs/core/core_interface.cpp b/sdm/libs/core/core_interface.cpp
new file mode 100644
index 0000000..34eceff
--- /dev/null
+++ b/sdm/libs/core/core_interface.cpp
@@ -0,0 +1,124 @@
+/*
+* 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:
+*     * 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/locker.h>
+#include <utils/constants.h>
+#include <utils/debug.h>
+#include <core/buffer_sync_handler.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)
+
+namespace sdm {
+
+// Currently, we support only one client and one session for display core. So, create a global
+// singleton core object.
+struct CoreSingleton {
+  CoreSingleton() : core_impl(NULL) { }
+
+  CoreImpl *core_impl;
+  Locker locker;
+} g_core;
+
+// TODO(user): Have a single structure handle carries all the interface pointers.
+DisplayError CoreInterface::CreateCore(CoreEventHandler *event_handler, DebugHandler *debug_handler,
+                                       BufferAllocator *buffer_allocator,
+                                       BufferSyncHandler *buffer_sync_handler,
+                                       CoreInterface **interface, uint32_t client_version) {
+  SCOPE_LOCK(g_core.locker);
+
+  if (!event_handler || !debug_handler || !buffer_allocator || !buffer_sync_handler || !interface) {
+    return kErrorParameters;
+  }
+
+  // Check compatibility of client and core.
+  uint32_t lib_version = SDM_VERSION_TAG;
+  if (GET_REVISION(client_version) > GET_REVISION(lib_version)) {
+    return kErrorVersion;
+  } else if (GET_DATA_ALIGNMENT(client_version) != GET_DATA_ALIGNMENT(lib_version)) {
+    return kErrorDataAlignment;
+  } else if (GET_INSTRUCTION_SET(client_version) != GET_INSTRUCTION_SET(lib_version)) {
+    return kErrorInstructionSet;
+  }
+
+  CoreImpl *&core_impl = g_core.core_impl;
+  if (core_impl) {
+    return kErrorUndefined;
+  }
+
+  Debug::SetDebugHandler(debug_handler);
+
+  // Create appropriate CoreImpl object based on client version.
+  if (GET_REVISION(client_version) == CoreImpl::kRevision) {
+    core_impl = new CoreImpl(event_handler, buffer_allocator, buffer_sync_handler);
+  } else {
+    return kErrorNotSupported;
+  }
+
+  if (!core_impl) {
+    return kErrorMemory;
+  }
+
+  DisplayError error = core_impl->Init();
+  if (error != kErrorNone) {
+    delete core_impl;
+    core_impl = NULL;
+    return error;
+  }
+
+  *interface = core_impl;
+  DLOGI("Open interface handle = %p", *interface);
+
+  return kErrorNone;
+}
+
+DisplayError CoreInterface::DestroyCore() {
+  SCOPE_LOCK(g_core.locker);
+
+  DLOGI("Close handle");
+
+  CoreImpl *&core_impl = g_core.core_impl;
+  if (!core_impl) {
+    return kErrorUndefined;
+  }
+
+  core_impl->Deinit();
+  delete core_impl;
+  core_impl = NULL;
+
+  return kErrorNone;
+}
+
+}  // namespace sdm
+
diff --git a/sdm/libs/core/display_base.cpp b/sdm/libs/core/display_base.cpp
new file mode 100644
index 0000000..8dc9b19
--- /dev/null
+++ b/sdm/libs/core/display_base.cpp
@@ -0,0 +1,564 @@
+/*
+* 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:
+*    * 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 <stdio.h>
+#include <utils/constants.h>
+#include <utils/debug.h>
+
+#include "display_base.h"
+
+#define __CLASS__ "DisplayBase"
+
+namespace sdm {
+
+// TODO(user): Have a single structure handle carries all the interface pointers and variables.
+DisplayBase::DisplayBase(DisplayType display_type, DisplayEventHandler *event_handler,
+                         HWDeviceType hw_device_type, BufferSyncHandler *buffer_sync_handler,
+                         CompManager *comp_manager, RotatorInterface *rotator_intf)
+  : display_type_(display_type), event_handler_(event_handler), hw_device_type_(hw_device_type),
+    buffer_sync_handler_(buffer_sync_handler), comp_manager_(comp_manager),
+    rotator_intf_(rotator_intf), 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), underscan_supported_(false) {
+}
+
+DisplayError DisplayBase::Init() {
+  DisplayError error = kErrorNone;
+  hw_panel_info_ = HWPanelInfo();
+  hw_intf_->GetHWPanelInfo(&hw_panel_info_);
+
+  error = hw_intf_->GetNumDisplayAttributes(&num_modes_);
+  if (error != kErrorNone) {
+    goto CleanupOnError;
+  }
+
+  display_attributes_ = new HWDisplayAttributes[num_modes_];
+  if (!display_attributes_) {
+    error = kErrorMemory;
+    goto CleanupOnError;
+  }
+
+  for (uint32_t i = 0; i < num_modes_; i++) {
+    error = hw_intf_->GetDisplayAttributes(&display_attributes_[i], i);
+    if (error != kErrorNone) {
+      goto CleanupOnError;
+    }
+  }
+
+  active_mode_index_ = GetBestConfig();
+
+  error = hw_intf_->SetDisplayAttributes(active_mode_index_);
+  if (error != kErrorNone) {
+    goto CleanupOnError;
+  }
+
+  error = comp_manager_->RegisterDisplay(display_type_, display_attributes_[active_mode_index_],
+                                         hw_panel_info_, &display_comp_ctx_);
+  if (error != kErrorNone) {
+    goto CleanupOnError;
+  }
+
+  if (rotator_intf_) {
+    error = rotator_intf_->RegisterDisplay(display_type_, &display_rotator_ctx_);
+    if (error != kErrorNone) {
+      goto CleanupOnError;
+    }
+  }
+
+  return kErrorNone;
+
+CleanupOnError:
+  if (display_comp_ctx_) {
+    comp_manager_->UnregisterDisplay(display_comp_ctx_);
+  }
+
+  if (display_attributes_) {
+    delete[] display_attributes_;
+    display_attributes_ = NULL;
+  }
+
+  hw_intf_->Close();
+
+  return error;
+}
+
+DisplayError DisplayBase::Deinit() {
+  if (rotator_intf_) {
+    rotator_intf_->UnregisterDisplay(display_rotator_ctx_);
+  }
+
+  comp_manager_->UnregisterDisplay(display_comp_ctx_);
+
+  if (display_attributes_) {
+    delete[] display_attributes_;
+    display_attributes_ = NULL;
+  }
+
+  hw_intf_->Close();
+
+  return kErrorNone;
+}
+
+DisplayError DisplayBase::Prepare(LayerStack *layer_stack) {
+  DisplayError error = kErrorNone;
+
+  if (!layer_stack) {
+    return kErrorParameters;
+  }
+
+  pending_commit_ = false;
+
+  if (state_ == kStateOn) {
+    // Clean hw layers for reuse.
+    hw_layers_.info = HWLayersInfo();
+    hw_layers_.info.stack = layer_stack;
+    hw_layers_.output_compression = 1.0f;
+
+    comp_manager_->PrePrepare(display_comp_ctx_, &hw_layers_);
+    while (true) {
+      error = comp_manager_->Prepare(display_comp_ctx_, &hw_layers_);
+      if (error != kErrorNone) {
+        break;
+      }
+
+      if (IsRotationRequired(&hw_layers_)) {
+        if (!rotator_intf_) {
+          continue;
+        }
+        error = rotator_intf_->Prepare(display_rotator_ctx_, &hw_layers_);
+      } else {
+        // Release all the previous rotator sessions.
+        if (rotator_intf_) {
+          error = rotator_intf_->Purge(display_rotator_ctx_, &hw_layers_);
+        }
+      }
+
+      if (error == kErrorNone) {
+        error = hw_intf_->Validate(&hw_layers_);
+        if (error == kErrorNone) {
+          // Strategy is successful now, wait for Commit().
+          pending_commit_ = true;
+          break;
+        }
+      }
+    }
+    comp_manager_->PostPrepare(display_comp_ctx_, &hw_layers_);
+  } else {
+    return kErrorNotSupported;
+  }
+
+  return error;
+}
+
+DisplayError DisplayBase::Commit(LayerStack *layer_stack) {
+  DisplayError error = kErrorNone;
+
+  if (!layer_stack) {
+    return kErrorParameters;
+  }
+
+  if (state_ != kStateOn) {
+    return kErrorNotSupported;
+  }
+
+  if (!pending_commit_) {
+    DLOGE("Commit: Corresponding Prepare() is not called for display = %d", display_type_);
+    return kErrorUndefined;
+  }
+
+  pending_commit_ = false;
+
+  if (rotator_intf_ && IsRotationRequired(&hw_layers_)) {
+    error = rotator_intf_->Commit(display_rotator_ctx_, &hw_layers_);
+    if (error != kErrorNone) {
+      return error;
+    }
+  }
+
+  error = hw_intf_->Commit(&hw_layers_);
+  if (error != kErrorNone) {
+    return error;
+  }
+
+  if (rotator_intf_ && IsRotationRequired(&hw_layers_)) {
+    error = rotator_intf_->PostCommit(display_rotator_ctx_, &hw_layers_);
+    if (error != kErrorNone) {
+      return error;
+    }
+  }
+
+  error = comp_manager_->PostCommit(display_comp_ctx_, &hw_layers_);
+  if (error != kErrorNone) {
+    return error;
+  }
+
+  return kErrorNone;
+}
+
+DisplayError DisplayBase::Flush() {
+  DisplayError error = kErrorNone;
+
+  if (state_ != kStateOn) {
+    return kErrorNone;
+  }
+
+  hw_layers_.info.count = 0;
+  error = hw_intf_->Flush();
+  if (error == kErrorNone) {
+    comp_manager_->Purge(display_comp_ctx_);
+    pending_commit_ = false;
+  } else {
+    DLOGV("Failed to flush device.");
+  }
+
+  return error;
+}
+
+DisplayError DisplayBase::GetDisplayState(DisplayState *state) {
+  if (!state) {
+    return kErrorParameters;
+  }
+
+  *state = state_;
+  return kErrorNone;
+}
+
+DisplayError DisplayBase::GetNumVariableInfoConfigs(uint32_t *count) {
+  if (!count) {
+    return kErrorParameters;
+  }
+
+  *count = num_modes_;
+
+  return kErrorNone;
+}
+
+DisplayError DisplayBase::GetConfig(DisplayConfigFixedInfo *fixed_info) {
+  if (!fixed_info) {
+    return kErrorParameters;
+  }
+
+  return kErrorNone;
+}
+
+DisplayError DisplayBase::GetConfig(uint32_t index, DisplayConfigVariableInfo *variable_info) {
+  if (!variable_info || index >= num_modes_) {
+    return kErrorParameters;
+  }
+
+  *variable_info = display_attributes_[index];
+
+  return kErrorNone;
+}
+
+DisplayError DisplayBase::GetActiveConfig(uint32_t *index) {
+  if (!index) {
+    return kErrorParameters;
+  }
+
+  *index = active_mode_index_;
+
+  return kErrorNone;
+}
+
+DisplayError DisplayBase::GetVSyncState(bool *enabled) {
+  if (!enabled) {
+    return kErrorParameters;
+  }
+
+  return kErrorNone;
+}
+
+bool DisplayBase::IsUnderscanSupported() {
+  return underscan_supported_;
+}
+
+DisplayError DisplayBase::SetDisplayState(DisplayState state) {
+  DisplayError error = kErrorNone;
+
+  DLOGI("Set state = %d, display %d", state, display_type_);
+
+  if (state == state_) {
+    DLOGI("Same state transition is requested.");
+    return kErrorNone;
+  }
+
+  switch (state) {
+  case kStateOff:
+    hw_layers_.info.count = 0;
+    error = hw_intf_->Flush();
+    if (error == kErrorNone) {
+      comp_manager_->Purge(display_comp_ctx_);
+
+      error = hw_intf_->PowerOff();
+    }
+    break;
+
+  case kStateOn:
+    error = hw_intf_->PowerOn();
+    break;
+
+  case kStateDoze:
+    error = hw_intf_->Doze();
+    break;
+
+  case kStateDozeSuspend:
+    error = hw_intf_->DozeSuspend();
+    break;
+
+  case kStateStandby:
+    error = hw_intf_->Standby();
+    break;
+
+  default:
+    DLOGE("Spurious state = %d transition requested.", state);
+    break;
+  }
+
+  if (error == kErrorNone) {
+    state_ = state;
+  }
+
+  return error;
+}
+
+DisplayError DisplayBase::SetActiveConfig(uint32_t index) {
+  DisplayError error = kErrorNone;
+
+  if (index >= num_modes_) {
+    return kErrorParameters;
+  }
+
+  error = hw_intf_->SetDisplayAttributes(index);
+  if (error != kErrorNone) {
+    return error;
+  }
+
+  active_mode_index_ = index;
+
+  if (display_comp_ctx_) {
+    comp_manager_->UnregisterDisplay(display_comp_ctx_);
+  }
+
+  error = comp_manager_->RegisterDisplay(display_type_, display_attributes_[index], hw_panel_info_,
+                                         &display_comp_ctx_);
+
+  return error;
+}
+
+DisplayError DisplayBase::SetMaxMixerStages(uint32_t max_mixer_stages) {
+  DisplayError error = kErrorNone;
+
+  if (comp_manager_) {
+    error = comp_manager_->SetMaxMixerStages(display_comp_ctx_, max_mixer_stages);
+  }
+
+  return error;
+}
+
+DisplayError DisplayBase::SetDisplayMode(uint32_t mode) {
+  return kErrorNotSupported;
+}
+
+DisplayError DisplayBase::IsScalingValid(const LayerRect &crop, const LayerRect &dst,
+                                         bool rotate90) {
+  return comp_manager_->ValidateScaling(crop, dst, rotate90);
+}
+
+void DisplayBase::AppendDump(char *buffer, uint32_t length) {
+  DumpImpl::AppendString(buffer, length, "\n-----------------------");
+  DumpImpl::AppendString(buffer, length, "\ndevice type: %u", display_type_);
+  DumpImpl::AppendString(buffer, length, "\nstate: %u, vsync on: %u", state_, INT(vsync_enable_));
+  DumpImpl::AppendString(buffer, length, "\nnum configs: %u, active config index: %u",
+                         num_modes_, active_mode_index_);
+
+  DisplayConfigVariableInfo &info = display_attributes_[active_mode_index_];
+  DumpImpl::AppendString(buffer, length, "\nres:%u x %u, dpi:%.2f x %.2f, fps:%.2f,"
+                         "vsync period: %u", info.x_pixels, info.y_pixels, info.x_dpi,
+                         info.y_dpi, info.fps, info.vsync_period_ns);
+
+  DumpImpl::AppendString(buffer, length, "\n");
+
+  uint32_t num_layers = 0;
+  uint32_t num_hw_layers = 0;
+  if (hw_layers_.info.stack) {
+    num_layers = hw_layers_.info.stack->layer_count;
+    num_hw_layers = hw_layers_.info.count;
+  }
+
+  if (num_hw_layers == 0) {
+    DumpImpl::AppendString(buffer, length, "\nNo hardware layers programmed");
+    return;
+  }
+
+  HWLayersInfo &layer_info = hw_layers_.info;
+  LayerRect &l_roi = layer_info.left_partial_update;
+  LayerRect &r_roi = layer_info.right_partial_update;
+  DumpImpl::AppendString(buffer, length, "\nROI(L T R B) : LEFT(%d %d %d %d), RIGHT(%d %d %d %d)",
+                         INT(l_roi.left), INT(l_roi.top), INT(l_roi.right), INT(l_roi.bottom),
+                         INT(r_roi.left), INT(r_roi.top), INT(r_roi.right), INT(r_roi.bottom));
+
+  const char *header  = "\n| Idx |  Comp Type  |  Split | WB |  Pipe |    W x H    |       Format       |  Src Rect (L T R B) |  Dst Rect (L T R B) |  Z |    Flags   | Deci(HxV) |";  //NOLINT
+  const char *newline = "\n|-----|-------------|--------|----|-------|-------------|--------------------|---------------------|---------------------|----|------------|-----------|";  //NOLINT
+  const char *format  = "\n| %3s | %11s "     "| %6s " "| %2s | 0x%03x | %4d x %4d | %18s "            "| %4d %4d %4d %4d "  "| %4d %4d %4d %4d "  "| %2s | %10s "   "| %9s |";  //NOLINT
+
+  DumpImpl::AppendString(buffer, length, "\n");
+  DumpImpl::AppendString(buffer, length, newline);
+  DumpImpl::AppendString(buffer, length, header);
+  DumpImpl::AppendString(buffer, length, newline);
+
+  for (uint32_t i = 0; i < num_hw_layers; i++) {
+    uint32_t layer_index = hw_layers_.info.index[i];
+    Layer &layer = hw_layers_.info.stack->layers[layer_index];
+    LayerBuffer *input_buffer = layer.input_buffer;
+    HWLayerConfig &layer_config = hw_layers_.config[i];
+    HWRotatorSession &hw_rotator_session = layer_config.hw_rotator_session;
+
+    char idx[8] = { 0 };
+    const char *comp_type = GetName(layer.composition);
+    const char *buffer_format = GetName(input_buffer->format);
+    const char *rotate_split[2] = { "Rot-L", "Rot-R" };
+    const char *comp_split[2] = { "Comp-L", "Comp-R" };
+
+    snprintf(idx, sizeof(idx), "%d", layer_index);
+
+    for (uint32_t count = 0; count < hw_rotator_session.hw_block_count; count++) {
+      char writeback_id[8];
+      HWRotateInfo &rotate = hw_rotator_session.hw_rotate_info[count];
+      LayerRect &src_roi = rotate.src_roi;
+      LayerRect &dst_roi = rotate.dst_roi;
+
+      snprintf(writeback_id, sizeof(writeback_id), "%d", rotate.writeback_id);
+
+      DumpImpl::AppendString(buffer, length, format, idx, comp_type, rotate_split[count],
+                             writeback_id, rotate.pipe_id, input_buffer->width,
+                             input_buffer->height, buffer_format, INT(src_roi.left),
+                             INT(src_roi.top), INT(src_roi.right), INT(src_roi.bottom),
+                             INT(dst_roi.left), INT(dst_roi.top), INT(dst_roi.right),
+                             INT(dst_roi.bottom), "-", "-    ", "-    ");
+
+      // print the below only once per layer block, fill with spaces for rest.
+      idx[0] = 0;
+      comp_type = "";
+    }
+
+    if (hw_rotator_session.hw_block_count > 0) {
+      input_buffer = &hw_rotator_session.output_buffer;
+      buffer_format = GetName(input_buffer->format);
+    }
+
+    for (uint32_t count = 0; count < 2; count++) {
+      char decimation[16];
+      char flags[16];
+      char z_order[8];
+      HWPipeInfo &pipe = (count == 0) ? layer_config.left_pipe : layer_config.right_pipe;
+
+      if (!pipe.valid) {
+        continue;
+      }
+
+      LayerRect &src_roi = pipe.src_roi;
+      LayerRect &dst_roi = pipe.dst_roi;
+
+      snprintf(z_order, sizeof(z_order), "%d", pipe.z_order);
+      snprintf(flags, sizeof(flags), "0x%08x", layer.flags.flags);
+      snprintf(decimation, sizeof(decimation), "%3d x %3d", pipe.horizontal_decimation,
+               pipe.vertical_decimation);
+
+      DumpImpl::AppendString(buffer, length, format, idx, comp_type, comp_split[count],
+                             "-", pipe.pipe_id, input_buffer->width, input_buffer->height,
+                             buffer_format, INT(src_roi.left), INT(src_roi.top),
+                             INT(src_roi.right), INT(src_roi.bottom), INT(dst_roi.left),
+                             INT(dst_roi.top), INT(dst_roi.right), INT(dst_roi.bottom),
+                             z_order, flags, decimation);
+
+      // print the below only once per layer block, fill with spaces for rest.
+      idx[0] = 0;
+      comp_type = "";
+    }
+
+    DumpImpl::AppendString(buffer, length, newline);
+  }
+}
+
+int DisplayBase::GetBestConfig() {
+  return (num_modes_ == 1) ? 0 : -1;
+}
+
+bool DisplayBase::IsRotationRequired(HWLayers *hw_layers) {
+  HWLayersInfo &layer_info = hw_layers->info;
+
+  for (uint32_t i = 0; i < layer_info.count; i++) {
+    Layer& layer = layer_info.stack->layers[layer_info.index[i]];
+    HWRotatorSession *hw_rotator_session = &hw_layers->config[i].hw_rotator_session;
+
+    if (hw_rotator_session->hw_block_count) {
+      return true;
+    }
+  }
+
+  return false;
+}
+
+const char * DisplayBase::GetName(const LayerComposition &composition) {
+  switch (composition) {
+  case kCompositionGPU:         return "GPU";
+  case kCompositionSDE:         return "SDE";
+  case kCompositionGPUTarget:   return "GPU_TARGET";
+  default:                      return "UNKNOWN";
+  }
+}
+
+const char * DisplayBase::GetName(const LayerBufferFormat &format) {
+  switch (format) {
+  case kFormatARGB8888:                 return "ARGB_8888";
+  case kFormatRGBA8888:                 return "RGBA_8888";
+  case kFormatBGRA8888:                 return "BGRA_8888";
+  case kFormatXRGB8888:                 return "XRGB_8888";
+  case kFormatRGBX8888:                 return "RGBX_8888";
+  case kFormatBGRX8888:                 return "BGRX_8888";
+  case kFormatRGBA5551:                 return "RGBA_5551";
+  case kFormatRGBA4444:                 return "RGBA_4444";
+  case kFormatRGB888:                   return "RGB_888";
+  case kFormatBGR888:                   return "BGR_888";
+  case kFormatRGB565:                   return "RGB_565";
+  case kFormatRGBA8888Ubwc:             return "RGBA_8888_UBWC";
+  case kFormatRGBX8888Ubwc:             return "RGBX_8888_UBWC";
+  case kFormatRGB565Ubwc:               return "RGB_565_UBWC";
+  case kFormatYCbCr420Planar:           return "Y_CB_CR_420";
+  case kFormatYCrCb420Planar:           return "Y_CR_CB_420";
+  case kFormatYCbCr420SemiPlanar:       return "Y_CBCR_420";
+  case kFormatYCrCb420SemiPlanar:       return "Y_CRCB_420";
+  case kFormatYCbCr420SemiPlanarVenus:  return "Y_CBCR_420_VENUS";
+  case kFormatYCbCr422H1V2SemiPlanar:   return "Y_CBCR_422_H1V2";
+  case kFormatYCrCb422H1V2SemiPlanar:   return "Y_CRCB_422_H1V2";
+  case kFormatYCbCr422H2V1SemiPlanar:   return "Y_CBCR_422_H2V1";
+  case kFormatYCrCb422H2V1SemiPlanar:   return "Y_CRCB_422_H2V2";
+  case kFormatYCbCr420SPVenusUbwc:      return "Y_CBCR_420_VENUS_UBWC";
+  case kFormatYCbCr422H2V1Packed:       return "YCBYCR_422_H2V1";
+  default:                              return "UNKNOWN";
+  }
+}
+
+}  // namespace sdm
diff --git a/sdm/libs/core/display_base.h b/sdm/libs/core/display_base.h
new file mode 100644
index 0000000..56e6682
--- /dev/null
+++ b/sdm/libs/core/display_base.h
@@ -0,0 +1,98 @@
+/*
+* 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:
+*    * Redistributions of source code must retain the above copyright notice, this list of
+*      conditions and the following disclaimer.
+*    * Redistributions in binary form must reproduce the above copyright notice, this list of
+*      conditions and the following disclaimer in the documentation and/or other materials provided
+*      with the distribution.
+*    * Neither the name of The Linux Foundation nor the names of its contributors may be used to
+*      endorse or promote products derived from this software without specific prior written
+*      permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef __DISPLAY_BASE_H__
+#define __DISPLAY_BASE_H__
+
+#include <core/display_interface.h>
+#include <private/strategy_interface.h>
+#include <private/rotator_interface.h>
+#include <utils/locker.h>
+
+#include "hw_interface.h"
+#include "comp_manager.h"
+
+
+namespace sdm {
+
+class RotatorCtrl;
+
+class DisplayBase : public DisplayInterface {
+ public:
+  DisplayBase(DisplayType display_type, DisplayEventHandler *event_handler,
+              HWDeviceType hw_device_type, BufferSyncHandler *buffer_sync_handler,
+              CompManager *comp_manager, RotatorInterface *rotator_intf);
+  virtual ~DisplayBase() { }
+  virtual DisplayError Init();
+  virtual DisplayError Deinit();
+  virtual DisplayError Prepare(LayerStack *layer_stack);
+  virtual DisplayError Commit(LayerStack *layer_stack);
+  virtual DisplayError Flush();
+  virtual DisplayError GetDisplayState(DisplayState *state);
+  virtual DisplayError GetNumVariableInfoConfigs(uint32_t *count);
+  virtual DisplayError GetConfig(DisplayConfigFixedInfo *fixed_info);
+  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 SetActiveConfig(uint32_t index);
+  virtual DisplayError SetMaxMixerStages(uint32_t max_mixer_stages);
+  virtual DisplayError SetDisplayMode(uint32_t mode);
+  virtual DisplayError IsScalingValid(const LayerRect &crop, const LayerRect &dst, bool rotate90);
+  virtual bool IsUnderscanSupported();
+
+ protected:
+  // DumpImpl method
+  void AppendDump(char *buffer, uint32_t length);
+
+  virtual int GetBestConfig();
+  bool IsRotationRequired(HWLayers *hw_layers);
+  const char * GetName(const LayerComposition &composition);
+  const char * GetName(const LayerBufferFormat &format);
+
+  DisplayType display_type_;
+  DisplayEventHandler *event_handler_;
+  HWDeviceType hw_device_type_;
+  HWInterface *hw_intf_;
+  HWPanelInfo hw_panel_info_;
+  BufferSyncHandler *buffer_sync_handler_;
+  CompManager *comp_manager_;
+  RotatorInterface *rotator_intf_;
+  DisplayState state_;
+  Handle hw_device_;
+  Handle display_comp_ctx_;
+  Handle display_rotator_ctx_;
+  HWDisplayAttributes *display_attributes_;
+  uint32_t num_modes_;
+  uint32_t active_mode_index_;
+  HWLayers hw_layers_;
+  bool pending_commit_;
+  bool vsync_enable_;
+  bool underscan_supported_;
+};
+
+}  // namespace sdm
+
+#endif  // __DISPLAY_BASE_H__
+
diff --git a/sdm/libs/core/display_hdmi.cpp b/sdm/libs/core/display_hdmi.cpp
new file mode 100644
index 0000000..ef25b90
--- /dev/null
+++ b/sdm/libs/core/display_hdmi.cpp
@@ -0,0 +1,251 @@
+/*
+* 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:
+*    * 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 <utils/debug.h>
+
+#include "display_hdmi.h"
+#include "hw_hdmi_interface.h"
+#include "hw_info_interface.h"
+
+#define __CLASS__ "DisplayHDMI"
+
+namespace sdm {
+
+DisplayHDMI::DisplayHDMI(DisplayEventHandler *event_handler, HWInfoInterface *hw_info_intf,
+                         BufferSyncHandler *buffer_sync_handler, CompManager *comp_manager,
+                         RotatorInterface *rotator_intf)
+  : DisplayBase(kHDMI, event_handler, kDeviceHDMI, buffer_sync_handler, comp_manager,
+                rotator_intf), hw_info_intf_(hw_info_intf) {
+}
+
+DisplayError DisplayHDMI::Init() {
+  SCOPE_LOCK(locker_);
+
+  DisplayError error = HWHDMIInterface::Create(&hw_hdmi_intf_, hw_info_intf_,
+                                               DisplayBase::buffer_sync_handler_);
+  if (error != kErrorNone) {
+    return error;
+  }
+
+  DisplayBase::hw_intf_ = hw_hdmi_intf_;
+  error = hw_hdmi_intf_->Open(NULL);
+  if (error != kErrorNone) {
+    return error;
+  }
+
+  error = DisplayBase::Init();
+  if (error != kErrorNone) {
+    HWHDMIInterface::Destroy(hw_hdmi_intf_);
+  }
+
+  GetScanSupport();
+  underscan_supported_ = (scan_support_ == kScanAlwaysUnderscanned) || (scan_support_ == kScanBoth);
+
+  return error;
+}
+
+DisplayError DisplayHDMI::Deinit() {
+  SCOPE_LOCK(locker_);
+
+  DisplayError error = DisplayBase::Deinit();
+  if (error != kErrorNone) {
+    return error;
+  }
+  HWHDMIInterface::Destroy(hw_hdmi_intf_);
+
+  return error;
+}
+
+DisplayError DisplayHDMI::Prepare(LayerStack *layer_stack) {
+  SCOPE_LOCK(locker_);
+  return DisplayBase::Prepare(layer_stack);
+}
+
+DisplayError DisplayHDMI::Commit(LayerStack *layer_stack) {
+  SCOPE_LOCK(locker_);
+  return DisplayBase::Commit(layer_stack);
+}
+
+DisplayError DisplayHDMI::Flush() {
+  SCOPE_LOCK(locker_);
+  return DisplayBase::Flush();
+}
+
+DisplayError DisplayHDMI::GetDisplayState(DisplayState *state) {
+  SCOPE_LOCK(locker_);
+  return DisplayBase::GetDisplayState(state);
+}
+
+DisplayError DisplayHDMI::GetNumVariableInfoConfigs(uint32_t *count) {
+  SCOPE_LOCK(locker_);
+  return DisplayBase::GetNumVariableInfoConfigs(count);
+}
+
+DisplayError DisplayHDMI::GetConfig(DisplayConfigFixedInfo *fixed_info) {
+  SCOPE_LOCK(locker_);
+  return DisplayBase::GetConfig(fixed_info);
+}
+
+DisplayError DisplayHDMI::GetConfig(uint32_t index, DisplayConfigVariableInfo *variable_info) {
+  SCOPE_LOCK(locker_);
+  return DisplayBase::GetConfig(index, variable_info);
+}
+
+DisplayError DisplayHDMI::GetActiveConfig(uint32_t *index) {
+  SCOPE_LOCK(locker_);
+  return DisplayBase::GetActiveConfig(index);
+}
+
+DisplayError DisplayHDMI::GetVSyncState(bool *enabled) {
+  SCOPE_LOCK(locker_);
+  return DisplayBase::GetVSyncState(enabled);
+}
+
+DisplayError DisplayHDMI::SetDisplayState(DisplayState state) {
+  SCOPE_LOCK(locker_);
+  return DisplayBase::SetDisplayState(state);
+}
+
+DisplayError DisplayHDMI::SetActiveConfig(DisplayConfigVariableInfo *variable_info) {
+  SCOPE_LOCK(locker_);
+  return kErrorNotSupported;
+}
+
+DisplayError DisplayHDMI::SetActiveConfig(uint32_t index) {
+  SCOPE_LOCK(locker_);
+  return DisplayBase::SetActiveConfig(index);
+}
+
+DisplayError DisplayHDMI::SetVSyncState(bool enable) {
+  SCOPE_LOCK(locker_);
+  return kErrorNotSupported;
+}
+
+void DisplayHDMI::SetIdleTimeoutMs(uint32_t timeout_ms) { }
+
+DisplayError DisplayHDMI::SetMaxMixerStages(uint32_t max_mixer_stages) {
+  SCOPE_LOCK(locker_);
+  return DisplayBase::SetMaxMixerStages(max_mixer_stages);
+}
+
+DisplayError DisplayHDMI::SetDisplayMode(uint32_t mode) {
+  SCOPE_LOCK(locker_);
+  return DisplayBase::SetDisplayMode(mode);
+}
+
+DisplayError DisplayHDMI::IsScalingValid(const LayerRect &crop, const LayerRect &dst,
+                                         bool rotate90) {
+  SCOPE_LOCK(locker_);
+  return DisplayBase::IsScalingValid(crop, dst, rotate90);
+}
+
+DisplayError DisplayHDMI::SetRefreshRate(uint32_t refresh_rate) {
+  SCOPE_LOCK(locker_);
+  return kErrorNotSupported;
+}
+
+bool DisplayHDMI::IsUnderscanSupported() {
+  SCOPE_LOCK(locker_);
+  return DisplayBase::IsUnderscanSupported();
+}
+
+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(user_config, &config_index);
+    if (error == kErrorNone)
+      return config_index;
+  }
+
+  return best_config_mode;
+}
+
+void DisplayHDMI::GetScanSupport() {
+  DisplayError error = kErrorNone;
+  uint32_t video_format = -1;
+  uint32_t max_cea_format = -1;
+  HWScanInfo scan_info = HWScanInfo();
+  hw_hdmi_intf_->GetHWScanInfo(&scan_info);
+
+  error = hw_hdmi_intf_->GetVideoFormat(active_mode_index_, &video_format);
+  if (error != kErrorNone) {
+    return;
+  }
+
+  error = hw_hdmi_intf_->GetMaxCEAFormat(&max_cea_format);
+  if (error != kErrorNone) {
+    return;
+  }
+
+  // The scan support for a given HDMI TV must be read from scan info corresponding to
+  // Preferred Timing if the preferred timing of the display is currently active, and if it is
+  // valid. In all other cases, we must read the scan support from CEA scan info if
+  // the resolution is a CEA resolution, or from IT scan info for all other resolutions.
+  if (active_mode_index_ == 0 && scan_info.pt_scan_support != kScanNotSupported) {
+    scan_support_ = scan_info.pt_scan_support;
+  } else if (video_format < max_cea_format) {
+    scan_support_ = scan_info.cea_scan_support;
+  } else {
+    scan_support_ = scan_info.it_scan_support;
+  }
+}
+
+void DisplayHDMI::AppendDump(char *buffer, uint32_t length) {
+  SCOPE_LOCK(locker_);
+  DisplayBase::AppendDump(buffer, length);
+}
+
+}  // namespace sdm
+
diff --git a/sdm/libs/core/display_hdmi.h b/sdm/libs/core/display_hdmi.h
new file mode 100644
index 0000000..96b9eea
--- /dev/null
+++ b/sdm/libs/core/display_hdmi.h
@@ -0,0 +1,77 @@
+/*
+* 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:
+*    * Redistributions of source code must retain the above copyright notice, this list of
+*      conditions and the following disclaimer.
+*    * Redistributions in binary form must reproduce the above copyright notice, this list of
+*      conditions and the following disclaimer in the documentation and/or other materials provided
+*      with the distribution.
+*    * Neither the name of The Linux Foundation nor the names of its contributors may be used to
+*      endorse or promote products derived from this software without specific prior written
+*      permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef __DISPLAY_HDMI_H__
+#define __DISPLAY_HDMI_H__
+
+#include "display_base.h"
+#include "dump_impl.h"
+
+namespace sdm {
+
+class HWHDMIInterface;
+class HWInfoInterface;
+
+class DisplayHDMI : public DisplayBase, DumpImpl {
+ public:
+  DisplayHDMI(DisplayEventHandler *event_handler, HWInfoInterface *hw_info_intf,
+              BufferSyncHandler *buffer_sync_handler, CompManager *comp_manager,
+              RotatorInterface *rotator_intf);
+  virtual DisplayError Init();
+  virtual DisplayError Deinit();
+  virtual DisplayError Prepare(LayerStack *layer_stack);
+  virtual DisplayError Commit(LayerStack *layer_stack);
+  virtual DisplayError Flush();
+  virtual DisplayError GetDisplayState(DisplayState *state);
+  virtual DisplayError GetNumVariableInfoConfigs(uint32_t *count);
+  virtual DisplayError GetConfig(DisplayConfigFixedInfo *fixed_info);
+  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 SetActiveConfig(DisplayConfigVariableInfo *variable_info);
+  virtual DisplayError SetActiveConfig(uint32_t index);
+  virtual DisplayError SetVSyncState(bool enable);
+  virtual void SetIdleTimeoutMs(uint32_t timeout_ms);
+  virtual DisplayError SetMaxMixerStages(uint32_t max_mixer_stages);
+  virtual DisplayError SetDisplayMode(uint32_t mode);
+  virtual DisplayError IsScalingValid(const LayerRect &crop, const LayerRect &dst, bool rotate90);
+  virtual DisplayError SetRefreshRate(uint32_t refresh_rate);
+  virtual bool IsUnderscanSupported();
+  virtual void AppendDump(char *buffer, uint32_t length);
+
+ private:
+  virtual int GetBestConfig();
+  virtual void GetScanSupport();
+
+  Locker locker_;
+  HWHDMIInterface *hw_hdmi_intf_;
+  HWInfoInterface *hw_info_intf_;
+  HWScanSupport scan_support_;
+};
+
+}  // namespace sdm
+
+#endif  // __DISPLAY_HDMI_H__
+
diff --git a/sdm/libs/core/display_primary.cpp b/sdm/libs/core/display_primary.cpp
new file mode 100644
index 0000000..63ee78b
--- /dev/null
+++ b/sdm/libs/core/display_primary.cpp
@@ -0,0 +1,292 @@
+/*
+* 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:
+*    * 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 <utils/debug.h>
+
+#include "display_primary.h"
+#include "hw_primary_interface.h"
+#include "hw_info_interface.h"
+
+#define __CLASS__ "DisplayPrimary"
+
+namespace sdm {
+
+DisplayPrimary::DisplayPrimary(DisplayEventHandler *event_handler, HWInfoInterface *hw_info_intf,
+                               BufferSyncHandler *buffer_sync_handler, CompManager *comp_manager,
+                               RotatorInterface *rotator_intf)
+  : DisplayBase(kPrimary, event_handler, kDevicePrimary, buffer_sync_handler, comp_manager,
+                rotator_intf), hw_info_intf_(hw_info_intf) {
+}
+
+DisplayError DisplayPrimary::Init() {
+  SCOPE_LOCK(locker_);
+
+  DisplayError error = HWPrimaryInterface::Create(&hw_primary_intf_, hw_info_intf_,
+                                                  DisplayBase::buffer_sync_handler_);
+  if (error != kErrorNone) {
+    return error;
+  }
+  DisplayBase::hw_intf_ = hw_primary_intf_;
+
+  error = hw_primary_intf_->Open(this);
+  if (error != kErrorNone) {
+    return error;
+  }
+
+  error = DisplayBase::Init();
+  if (error != kErrorNone) {
+    HWPrimaryInterface::Destroy(hw_primary_intf_);
+  }
+
+  // Idle fallback feature is supported only for video mode panel.
+  if (hw_panel_info_.mode == kModeVideo) {
+    hw_primary_intf_->SetIdleTimeoutMs(Debug::GetIdleTimeoutMs());
+  }
+
+  return error;
+}
+
+DisplayError DisplayPrimary::Deinit() {
+  SCOPE_LOCK(locker_);
+
+  DisplayError error = DisplayBase::Deinit();
+  if (error != kErrorNone) {
+    return error;
+  }
+  HWPrimaryInterface::Destroy(hw_primary_intf_);
+
+  return error;
+}
+
+DisplayError DisplayPrimary::Prepare(LayerStack *layer_stack) {
+  SCOPE_LOCK(locker_);
+  return DisplayBase::Prepare(layer_stack);
+}
+
+DisplayError DisplayPrimary::Commit(LayerStack *layer_stack) {
+  SCOPE_LOCK(locker_);
+  DisplayError error = kErrorNone;
+  HWPanelInfo panel_info;
+  HWDisplayAttributes display_attributes;
+
+  error = DisplayBase::Commit(layer_stack);
+  if (error != kErrorNone) {
+    return error;
+  }
+
+  hw_primary_intf_->GetHWPanelInfo(&panel_info);
+
+  hw_primary_intf_->GetDisplayAttributes(&display_attributes, active_mode_index_);
+
+  if (panel_info != hw_panel_info_ ||
+      display_attributes != display_attributes_[active_mode_index_]) {
+    comp_manager_->ReconfigureDisplay(display_comp_ctx_, display_attributes, panel_info);
+
+    hw_panel_info_ = panel_info;
+    display_attributes_[active_mode_index_] = display_attributes;
+  }
+
+  return error;
+}
+
+DisplayError DisplayPrimary::Flush() {
+  SCOPE_LOCK(locker_);
+  return DisplayBase::Flush();
+}
+
+DisplayError DisplayPrimary::GetDisplayState(DisplayState *state) {
+  SCOPE_LOCK(locker_);
+  return DisplayBase::GetDisplayState(state);
+}
+
+DisplayError DisplayPrimary::GetNumVariableInfoConfigs(uint32_t *count) {
+  SCOPE_LOCK(locker_);
+  return DisplayBase::GetNumVariableInfoConfigs(count);
+}
+
+DisplayError DisplayPrimary::GetConfig(DisplayConfigFixedInfo *fixed_info) {
+  SCOPE_LOCK(locker_);
+  return DisplayBase::GetConfig(fixed_info);
+}
+
+DisplayError DisplayPrimary::GetConfig(uint32_t index, DisplayConfigVariableInfo *variable_info) {
+  SCOPE_LOCK(locker_);
+  return DisplayBase::GetConfig(index, variable_info);
+}
+
+DisplayError DisplayPrimary::GetActiveConfig(uint32_t *index) {
+  SCOPE_LOCK(locker_);
+  return DisplayBase::GetActiveConfig(index);
+}
+
+DisplayError DisplayPrimary::GetVSyncState(bool *enabled) {
+  SCOPE_LOCK(locker_);
+  return DisplayBase::GetVSyncState(enabled);
+}
+
+bool DisplayPrimary::IsUnderscanSupported() {
+  SCOPE_LOCK(locker_);
+  return DisplayBase::IsUnderscanSupported();
+}
+
+DisplayError DisplayPrimary::SetDisplayState(DisplayState state) {
+  SCOPE_LOCK(locker_);
+  return DisplayBase::SetDisplayState(state);
+}
+
+DisplayError DisplayPrimary::SetActiveConfig(DisplayConfigVariableInfo *variable_info) {
+  SCOPE_LOCK(locker_);
+  return kErrorNotSupported;
+}
+
+DisplayError DisplayPrimary::SetActiveConfig(uint32_t index) {
+  SCOPE_LOCK(locker_);
+  return DisplayBase::SetActiveConfig(index);
+}
+
+DisplayError DisplayPrimary::SetVSyncState(bool enable) {
+  SCOPE_LOCK(locker_);
+  DisplayError error = kErrorNone;
+  if (vsync_enable_ != enable) {
+    error = hw_primary_intf_->SetVSyncState(enable);
+    if (error == kErrorNone) {
+      vsync_enable_ = enable;
+    }
+  }
+
+  return error;
+}
+
+void DisplayPrimary::SetIdleTimeoutMs(uint32_t timeout_ms) {
+  SCOPE_LOCK(locker_);
+  // Idle fallback feature is supported only for video mode panel.
+  if (hw_panel_info_.mode == kModeVideo) {
+    hw_primary_intf_->SetIdleTimeoutMs(timeout_ms);
+  }
+}
+
+DisplayError DisplayPrimary::SetMaxMixerStages(uint32_t max_mixer_stages) {
+  SCOPE_LOCK(locker_);
+  return DisplayBase::SetMaxMixerStages(max_mixer_stages);
+}
+
+DisplayError DisplayPrimary::SetDisplayMode(uint32_t mode) {
+  SCOPE_LOCK(locker_);
+  DisplayError error = kErrorNone;
+  HWDisplayMode hw_display_mode = kModeDefault;
+
+  if (state_ != kStateOn) {
+    DLOGW("Invalid display state (%d). Panel must be on.", state_);
+    return kErrorNotSupported;
+  }
+
+  switch (mode) {
+  case kModeVideo:
+    hw_display_mode = kModeVideo;
+    break;
+  case kModeCommand:
+    hw_display_mode = kModeCommand;
+    break;
+  default:
+    DLOGW("Invalid panel mode parameters. Requested (%d)", mode);
+    return kErrorParameters;
+  }
+
+  if (hw_display_mode == hw_panel_info_.mode) {
+    DLOGW("Same display mode requested. Current (%d) Requested (%d)", hw_panel_info_.mode,
+          hw_display_mode);
+    return kErrorNone;
+  }
+
+  error = hw_primary_intf_->SetDisplayMode(hw_display_mode);
+  if (error != kErrorNone) {
+    DLOGW("Retaining current display mode. Current (%d), Requested (%d)", hw_panel_info_.mode,
+          hw_display_mode);
+    return error;
+  }
+
+  return error;
+}
+
+DisplayError DisplayPrimary::IsScalingValid(const LayerRect &crop, const LayerRect &dst,
+                                            bool rotate90) {
+  SCOPE_LOCK(locker_);
+  return DisplayBase::IsScalingValid(crop, dst, rotate90);
+}
+
+DisplayError DisplayPrimary::SetRefreshRate(uint32_t refresh_rate) {
+  SCOPE_LOCK(locker_);
+
+  DisplayError error = kErrorNone;
+
+  if (!hw_panel_info_.dynamic_fps) {
+    DLOGW("Dynamic fps feature is not supported");
+    return kErrorNotSupported;
+  }
+
+  if (refresh_rate > hw_panel_info_.max_fps) {
+    refresh_rate = hw_panel_info_.max_fps;
+  } else if (refresh_rate < hw_panel_info_.min_fps) {
+    refresh_rate = hw_panel_info_.min_fps;
+  }
+
+  return hw_primary_intf_->SetRefreshRate(refresh_rate);
+}
+
+void DisplayPrimary::AppendDump(char *buffer, uint32_t length) {
+  SCOPE_LOCK(locker_);
+  DisplayBase::AppendDump(buffer, length);
+}
+
+DisplayError DisplayPrimary::VSync(int64_t timestamp) {
+  if (vsync_enable_) {
+    DisplayEventVSync vsync;
+    vsync.timestamp = timestamp;
+    event_handler_->VSync(vsync);
+  }
+
+  return kErrorNone;
+}
+
+DisplayError DisplayPrimary::Blank(bool blank) {
+  SCOPE_LOCK(locker_);
+  return kErrorNone;
+}
+
+void DisplayPrimary::IdleTimeout() {
+  SCOPE_LOCK(locker_);
+  bool need_refresh = comp_manager_->ProcessIdleTimeout(display_comp_ctx_);
+  if (need_refresh) {
+    event_handler_->Refresh();
+  }
+}
+
+void DisplayPrimary::ThermalEvent(int64_t thermal_level) {
+  SCOPE_LOCK(locker_);
+  comp_manager_->ProcessThermalEvent(display_comp_ctx_, thermal_level);
+}
+
+}  // namespace sdm
+
diff --git a/sdm/libs/core/display_primary.h b/sdm/libs/core/display_primary.h
new file mode 100644
index 0000000..2cbae4b
--- /dev/null
+++ b/sdm/libs/core/display_primary.h
@@ -0,0 +1,79 @@
+/*
+* 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:
+*    * Redistributions of source code must retain the above copyright notice, this list of
+*      conditions and the following disclaimer.
+*    * Redistributions in binary form must reproduce the above copyright notice, this list of
+*      conditions and the following disclaimer in the documentation and/or other materials provided
+*      with the distribution.
+*    * Neither the name of The Linux Foundation nor the names of its contributors may be used to
+*      endorse or promote products derived from this software without specific prior written
+*      permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef __DISPLAY_PRIMARY_H__
+#define __DISPLAY_PRIMARY_H__
+
+#include "display_base.h"
+#include "dump_impl.h"
+
+namespace sdm {
+
+class HWPrimaryInterface;
+class HWInfoInterface;
+
+class DisplayPrimary : public DisplayBase, DumpImpl, HWEventHandler {
+ public:
+  DisplayPrimary(DisplayEventHandler *event_handler, HWInfoInterface *hw_info_intf,
+                 BufferSyncHandler *buffer_sync_handler, CompManager *comp_manager,
+                 RotatorInterface *rotator_intf);
+  virtual DisplayError Init();
+  virtual DisplayError Deinit();
+  virtual DisplayError Prepare(LayerStack *layer_stack);
+  virtual DisplayError Commit(LayerStack *layer_stack);
+  virtual DisplayError Flush();
+  virtual DisplayError GetDisplayState(DisplayState *state);
+  virtual DisplayError GetNumVariableInfoConfigs(uint32_t *count);
+  virtual DisplayError GetConfig(DisplayConfigFixedInfo *fixed_info);
+  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 SetActiveConfig(DisplayConfigVariableInfo *variable_info);
+  virtual DisplayError SetActiveConfig(uint32_t index);
+  virtual DisplayError SetVSyncState(bool enable);
+  virtual void SetIdleTimeoutMs(uint32_t timeout_ms);
+  virtual DisplayError SetMaxMixerStages(uint32_t max_mixer_stages);
+  virtual DisplayError SetDisplayMode(uint32_t mode);
+  virtual DisplayError IsScalingValid(const LayerRect &crop, const LayerRect &dst, bool rotate90);
+  virtual DisplayError SetRefreshRate(uint32_t refresh_rate);
+  virtual bool IsUnderscanSupported();
+  virtual void AppendDump(char *buffer, uint32_t length);
+
+  // Implement the HWEventHandlers
+  virtual DisplayError VSync(int64_t timestamp);
+  virtual DisplayError Blank(bool blank);
+  virtual void IdleTimeout();
+  virtual void ThermalEvent(int64_t thermal_level);
+
+ private:
+  Locker locker_;
+  HWPrimaryInterface *hw_primary_intf_;
+  HWInfoInterface *hw_info_intf_;
+};
+
+}  // namespace sdm
+
+#endif  // __DISPLAY_PRIMARY_H__
+
diff --git a/sdm/libs/core/display_virtual.cpp b/sdm/libs/core/display_virtual.cpp
new file mode 100644
index 0000000..262db7f
--- /dev/null
+++ b/sdm/libs/core/display_virtual.cpp
@@ -0,0 +1,203 @@
+/*
+* 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:
+*    * 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 <utils/debug.h>
+
+#include "display_virtual.h"
+#include "hw_virtual_interface.h"
+#include "hw_info_interface.h"
+
+#define __CLASS__ "DisplayVirtual"
+
+namespace sdm {
+
+DisplayVirtual::DisplayVirtual(DisplayEventHandler *event_handler, HWInfoInterface *hw_info_intf,
+                               BufferSyncHandler *buffer_sync_handler, CompManager *comp_manager,
+                               RotatorInterface *rotator_intf)
+  : DisplayBase(kVirtual, event_handler, kDeviceVirtual, buffer_sync_handler, comp_manager,
+                rotator_intf), hw_info_intf_(hw_info_intf) {
+}
+
+DisplayError DisplayVirtual::Init() {
+  SCOPE_LOCK(locker_);
+
+  DisplayError error = HWVirtualInterface::Create(&hw_virtual_intf_, hw_info_intf_,
+                                                  DisplayBase::buffer_sync_handler_);
+  if (error != kErrorNone) {
+    return error;
+  }
+
+  DisplayBase::hw_intf_ = hw_virtual_intf_;
+  error = hw_virtual_intf_->Open(NULL);
+  if (error != kErrorNone) {
+    return error;
+  }
+
+  error = DisplayBase::Init();
+  if (error != kErrorNone) {
+    HWVirtualInterface::Destroy(hw_virtual_intf_);
+  }
+
+  return error;
+}
+
+DisplayError DisplayVirtual::Deinit() {
+  SCOPE_LOCK(locker_);
+
+  DisplayError error = DisplayBase::Deinit();
+  if (error != kErrorNone) {
+    return error;
+  }
+  HWVirtualInterface::Destroy(hw_virtual_intf_);
+
+  return error;
+}
+
+DisplayError DisplayVirtual::Prepare(LayerStack *layer_stack) {
+  SCOPE_LOCK(locker_);
+  return DisplayBase::Prepare(layer_stack);
+}
+
+DisplayError DisplayVirtual::Commit(LayerStack *layer_stack) {
+  SCOPE_LOCK(locker_);
+  return DisplayBase::Commit(layer_stack);
+}
+
+DisplayError DisplayVirtual::Flush() {
+  SCOPE_LOCK(locker_);
+  return DisplayBase::Flush();
+}
+
+DisplayError DisplayVirtual::GetDisplayState(DisplayState *state) {
+  SCOPE_LOCK(locker_);
+  return DisplayBase::GetDisplayState(state);
+}
+
+DisplayError DisplayVirtual::GetNumVariableInfoConfigs(uint32_t *count) {
+  SCOPE_LOCK(locker_);
+  return DisplayBase::GetNumVariableInfoConfigs(count);
+}
+
+DisplayError DisplayVirtual::GetConfig(DisplayConfigFixedInfo *fixed_info) {
+  SCOPE_LOCK(locker_);
+  return DisplayBase::GetConfig(fixed_info);
+}
+
+DisplayError DisplayVirtual::GetConfig(uint32_t index, DisplayConfigVariableInfo *variable_info) {
+  SCOPE_LOCK(locker_);
+  return DisplayBase::GetConfig(index, variable_info);
+}
+
+DisplayError DisplayVirtual::GetActiveConfig(uint32_t *index) {
+  SCOPE_LOCK(locker_);
+  return DisplayBase::GetActiveConfig(index);
+}
+
+DisplayError DisplayVirtual::GetVSyncState(bool *enabled) {
+  SCOPE_LOCK(locker_);
+  return DisplayBase::GetVSyncState(enabled);
+}
+
+bool DisplayVirtual::IsUnderscanSupported() {
+  SCOPE_LOCK(locker_);
+  return DisplayBase::IsUnderscanSupported();
+}
+
+DisplayError DisplayVirtual::SetDisplayState(DisplayState state) {
+  SCOPE_LOCK(locker_);
+  return DisplayBase::SetDisplayState(state);
+}
+
+DisplayError DisplayVirtual::SetActiveConfig(DisplayConfigVariableInfo *variable_info) {
+  SCOPE_LOCK(locker_);
+  DisplayError error = kErrorNone;
+
+  if (!variable_info) {
+    return kErrorParameters;
+  }
+
+  HWDisplayAttributes display_attributes = display_attributes_[active_mode_index_];
+
+  display_attributes.x_pixels = variable_info->x_pixels;
+  display_attributes.y_pixels = variable_info->y_pixels;
+  display_attributes.fps = variable_info->fps;
+
+  // if display is already connected, unregister display from composition manager and register
+  // the display with new configuration.
+  if (display_comp_ctx_) {
+    comp_manager_->UnregisterDisplay(display_comp_ctx_);
+  }
+
+  error = comp_manager_->RegisterDisplay(display_type_, display_attributes, hw_panel_info_,
+                                         &display_comp_ctx_);
+  if (error != kErrorNone) {
+    return error;
+  }
+
+  display_attributes_[active_mode_index_] = display_attributes;
+
+  return error;
+}
+
+DisplayError DisplayVirtual::SetActiveConfig(uint32_t index) {
+  SCOPE_LOCK(locker_);
+  return DisplayBase::SetActiveConfig(index);
+}
+
+DisplayError DisplayVirtual::SetVSyncState(bool enable) {
+  SCOPE_LOCK(locker_);
+  return kErrorNotSupported;
+}
+
+void DisplayVirtual::SetIdleTimeoutMs(uint32_t timeout_ms) { }
+
+DisplayError DisplayVirtual::SetMaxMixerStages(uint32_t max_mixer_stages) {
+  SCOPE_LOCK(locker_);
+  return DisplayBase::SetMaxMixerStages(max_mixer_stages);
+}
+
+DisplayError DisplayVirtual::SetDisplayMode(uint32_t mode) {
+  SCOPE_LOCK(locker_);
+  return DisplayBase::SetDisplayMode(mode);
+}
+
+DisplayError DisplayVirtual::IsScalingValid(const LayerRect &crop, const LayerRect &dst,
+                                            bool rotate90) {
+  SCOPE_LOCK(locker_);
+  return DisplayBase::IsScalingValid(crop, dst, rotate90);
+}
+
+DisplayError DisplayVirtual::SetRefreshRate(uint32_t refresh_rate) {
+  SCOPE_LOCK(locker_);
+  return kErrorNotSupported;
+}
+
+void DisplayVirtual::AppendDump(char *buffer, uint32_t length) {
+  SCOPE_LOCK(locker_);
+  DisplayBase::AppendDump(buffer, length);
+}
+
+}  // namespace sdm
+
diff --git a/sdm/libs/core/display_virtual.h b/sdm/libs/core/display_virtual.h
new file mode 100644
index 0000000..2065534
--- /dev/null
+++ b/sdm/libs/core/display_virtual.h
@@ -0,0 +1,73 @@
+/*
+* 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:
+*    * Redistributions of source code must retain the above copyright notice, this list of
+*      conditions and the following disclaimer.
+*    * Redistributions in binary form must reproduce the above copyright notice, this list of
+*      conditions and the following disclaimer in the documentation and/or other materials provided
+*      with the distribution.
+*    * Neither the name of The Linux Foundation nor the names of its contributors may be used to
+*      endorse or promote products derived from this software without specific prior written
+*      permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef __DISPLAY_VIRTUAL_H__
+#define __DISPLAY_VIRTUAL_H__
+
+#include "display_base.h"
+#include "dump_impl.h"
+
+namespace sdm {
+
+class HWVirtualInterface;
+class HWInfoInterface;
+
+class DisplayVirtual : public DisplayBase, DumpImpl {
+ public:
+  DisplayVirtual(DisplayEventHandler *event_handler, HWInfoInterface *hw_info_intf,
+                 BufferSyncHandler *buffer_sync_handler, CompManager *comp_manager,
+                 RotatorInterface *rotator_intf);
+  virtual DisplayError Init();
+  virtual DisplayError Deinit();
+  virtual DisplayError Prepare(LayerStack *layer_stack);
+  virtual DisplayError Commit(LayerStack *layer_stack);
+  virtual DisplayError Flush();
+  virtual DisplayError GetDisplayState(DisplayState *state);
+  virtual DisplayError GetNumVariableInfoConfigs(uint32_t *count);
+  virtual DisplayError GetConfig(DisplayConfigFixedInfo *fixed_info);
+  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 SetActiveConfig(DisplayConfigVariableInfo *variable_info);
+  virtual DisplayError SetActiveConfig(uint32_t index);
+  virtual DisplayError SetVSyncState(bool enable);
+  virtual void SetIdleTimeoutMs(uint32_t timeout_ms);
+  virtual DisplayError SetMaxMixerStages(uint32_t max_mixer_stages);
+  virtual DisplayError SetDisplayMode(uint32_t mode);
+  virtual DisplayError IsScalingValid(const LayerRect &crop, const LayerRect &dst, bool rotate90);
+  virtual DisplayError SetRefreshRate(uint32_t refresh_rate);
+  virtual bool IsUnderscanSupported();
+  virtual void AppendDump(char *buffer, uint32_t length);
+
+ private:
+  Locker locker_;
+  HWVirtualInterface *hw_virtual_intf_;
+  HWInfoInterface *hw_info_intf_;
+};
+
+}  // namespace sdm
+
+#endif  // __DISPLAY_VIRTUAL_H__
+
diff --git a/sdm/libs/core/dump_impl.cpp b/sdm/libs/core/dump_impl.cpp
new file mode 100644
index 0000000..0d6c9b2
--- /dev/null
+++ b/sdm/libs/core/dump_impl.cpp
@@ -0,0 +1,93 @@
+/*
+* 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 <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+#include <utils/constants.h>
+
+#include "dump_impl.h"
+
+namespace sdm {
+
+DumpImpl* DumpImpl::dump_list_[] = { 0 };
+uint32_t DumpImpl::dump_count_ = 0;
+
+DisplayError DumpInterface::GetDump(char *buffer, uint32_t length) {
+  if (!buffer || !length) {
+    return kErrorParameters;
+  }
+
+  buffer[0] = '\0';
+  DumpImpl::AppendString(buffer, length, "\n-------- Snapdragon Display Manager --------");
+  for (uint32_t i = 0; i < DumpImpl::dump_count_; i++) {
+    DumpImpl::dump_list_[i]->AppendDump(buffer, length);
+  }
+  DumpImpl::AppendString(buffer, length, "\n\n");
+
+  return kErrorNone;
+}
+
+DumpImpl::DumpImpl() {
+  Register(this);
+}
+
+DumpImpl::~DumpImpl() {
+  Unregister(this);
+}
+
+void DumpImpl::AppendString(char *buffer, uint32_t length, const char *format, ...) {
+  uint32_t filled = UINT32(strlen(buffer));
+  if (filled >= length) {
+    return;
+  }
+  buffer += filled;
+
+  va_list list;
+  va_start(list, format);
+  vsnprintf(buffer, length - filled, format, list);
+}
+
+// Every object is created or destroyed through display core only, which itself protects the
+// the access, so no need to protect registration or de-registration.
+void DumpImpl::Register(DumpImpl *dump_impl) {
+  if (dump_count_ < kMaxDumpObjects) {
+    dump_list_[dump_count_] = dump_impl;
+    dump_count_++;
+  }
+}
+
+void DumpImpl::Unregister(DumpImpl *dump_impl) {
+  for (uint32_t i = 0; i < dump_count_; i++) {
+    if (dump_list_[i] == dump_impl) {
+      dump_count_--;
+      for (; i < dump_count_; i++) {
+        dump_list_[i] = dump_list_[i + 1];
+      }
+    }
+  }
+}
+
+}  // namespace sdm
+
diff --git a/sdm/libs/core/dump_impl.h b/sdm/libs/core/dump_impl.h
new file mode 100644
index 0000000..123c568
--- /dev/null
+++ b/sdm/libs/core/dump_impl.h
@@ -0,0 +1,58 @@
+/*
+* 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.
+*/
+
+#ifndef __DUMP_IMPL_H__
+#define __DUMP_IMPL_H__
+
+#include <core/dump_interface.h>
+
+namespace sdm {
+
+class DumpImpl {
+ public:
+  // To be implemented in the modules which will add dump information to final dump buffer.
+  // buffer address & length will be already adjusted before calling into these modules.
+  virtual void AppendDump(char *buffer, uint32_t length) = 0;
+  static void AppendString(char *buffer, uint32_t length, const char *format, ...);
+
+ protected:
+  DumpImpl();
+  virtual ~DumpImpl();
+
+ private:
+  static const uint32_t kMaxDumpObjects = 32;
+
+  static void Register(DumpImpl *dump_impl);
+  static void Unregister(DumpImpl *dump_impl);
+
+  static DumpImpl *dump_list_[kMaxDumpObjects];
+  static uint32_t dump_count_;
+
+  friend DumpInterface;
+};
+
+}  // namespace sdm
+
+#endif  // __DUMP_IMPL_H__
+
diff --git a/sdm/libs/core/fb/hw_device.cpp b/sdm/libs/core/fb/hw_device.cpp
new file mode 100644
index 0000000..b905c31
--- /dev/null
+++ b/sdm/libs/core/fb/hw_device.cpp
@@ -0,0 +1,946 @@
+/*
+* 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:
+*     * 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.
+*/
+
+#define __STDC_FORMAT_MACROS
+#include <ctype.h>
+#include <math.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <linux/fb.h>
+#include <utils/constants.h>
+#include <utils/debug.h>
+
+#include "hw_device.h"
+
+#define __CLASS__ "HWDevice"
+
+#ifdef DISPLAY_CORE_VIRTUAL_DRIVER
+extern int virtual_ioctl(int fd, int cmd, ...);
+extern int virtual_open(const char *file_name, int access, ...);
+extern int virtual_close(int fd);
+extern int virtual_poll(struct pollfd *fds,  nfds_t num, int timeout);
+extern ssize_t virtual_pread(int fd, void *data, size_t count, off_t offset);
+extern ssize_t virtual_pwrite(int fd, const void *data, size_t count, off_t offset);
+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);
+#endif
+
+namespace sdm {
+
+HWDevice::HWDevice(BufferSyncHandler *buffer_sync_handler)
+  : fb_node_index_(-1), fb_path_("/sys/devices/virtual/graphics/fb"), hotplug_enabled_(false),
+    buffer_sync_handler_(buffer_sync_handler), synchronous_commit_(false) {
+  // Pointer to actual driver interfaces.
+  ioctl_ = ::ioctl;
+  open_ = ::open;
+  close_ = ::close;
+  poll_ = ::poll;
+  pread_ = ::pread;
+  pwrite_ = ::pwrite;
+  fopen_ = ::fopen;
+  fclose_ = ::fclose;
+  getline_ = ::getline;
+
+#ifdef DISPLAY_CORE_VIRTUAL_DRIVER
+  // If debug property to use virtual driver is set, point to virtual driver interfaces.
+  if (Debug::IsVirtualDriver()) {
+    ioctl_ = virtual_ioctl;
+    open_ = virtual_open;
+    close_ = virtual_close;
+    poll_ = virtual_poll;
+    pread_ = virtual_pread;
+    pwrite_ = virtual_pwrite;
+    fopen_ = virtual_fopen;
+    fclose_ = virtual_fclose;
+    getline_ = virtual_getline;
+  }
+#endif
+}
+
+DisplayError HWDevice::Init() {
+  DisplayError error = kErrorNone;
+
+  // Read the fb node index
+  fb_node_index_ = GetFBNodeIndex(device_type_);
+  if (fb_node_index_ == -1) {
+    DLOGE("%s should be present", device_name_);
+    return kErrorHardware;
+  }
+
+  // Populate Panel Info (Used for Partial Update)
+  PopulateHWPanelInfo();
+  // Populate HW Capabilities
+  hw_resource_ = HWResourceInfo();
+  hw_info_intf_->GetHWResourceInfo(&hw_resource_);
+
+  return error;
+}
+
+DisplayError HWDevice::Open(HWEventHandler *eventhandler) {
+  DisplayError error = kErrorNone;
+
+  char device_name[64] = {0};
+
+  // Store EventHandlers for two Physical displays, i.e., Primary and HDMI
+  // TODO(user): Need to revisit for HDMI as Primary usecase
+  event_handler_ = eventhandler;
+  snprintf(device_name, sizeof(device_name), "%s%d", "/dev/graphics/fb", fb_node_index_);
+
+  device_fd_ = open_(device_name, O_RDWR);
+  if (device_fd_ < 0) {
+    DLOGE("open %s failed err = %d errstr = %s", device_name, errno,  strerror(errno));
+    return kErrorResources;
+  }
+
+  return error;
+}
+
+DisplayError HWDevice::Close() {
+  if (device_fd_ > 0) {
+    close_(device_fd_);
+  }
+
+  return kErrorNone;
+}
+
+DisplayError HWDevice::GetNumDisplayAttributes(uint32_t *count) {
+  *count = 1;
+  return kErrorNone;
+}
+
+DisplayError HWDevice::GetDisplayAttributes(HWDisplayAttributes *display_attributes,
+                                                 uint32_t index) {
+  return kErrorNone;
+}
+
+DisplayError HWDevice::GetHWPanelInfo(HWPanelInfo *panel_info) {
+  *panel_info = hw_panel_info_;
+  return kErrorNone;
+}
+
+DisplayError HWDevice::SetDisplayAttributes(uint32_t index) {
+  return kErrorNone;
+}
+
+DisplayError HWDevice::GetConfigIndex(uint32_t mode, uint32_t *index) {
+  return kErrorNone;
+}
+
+
+DisplayError HWDevice::PowerOn() {
+  DTRACE_SCOPED();
+
+  if (ioctl_(device_fd_, FBIOBLANK, FB_BLANK_UNBLANK) < 0) {
+    IOCTL_LOGE(FB_BLANK_UNBLANK, device_type_);
+    return kErrorHardware;
+  }
+
+  // Need to turn on HPD
+  if (!hotplug_enabled_) {
+    hotplug_enabled_ = EnableHotPlugDetection(1);
+  }
+
+  return kErrorNone;
+}
+
+DisplayError HWDevice::PowerOff() {
+  return kErrorNone;
+}
+
+DisplayError HWDevice::Doze() {
+  return kErrorNone;
+}
+
+DisplayError HWDevice::DozeSuspend() {
+  return kErrorNone;
+}
+
+DisplayError HWDevice::Standby() {
+  return kErrorNone;
+}
+
+DisplayError HWDevice::Validate(HWLayers *hw_layers) {
+  DTRACE_SCOPED();
+
+  DisplayError error = kErrorNone;
+
+  HWLayersInfo &hw_layer_info = hw_layers->info;
+  LayerStack *stack = hw_layer_info.stack;
+
+  DLOGV_IF(kTagDriverConfig, "************************** %s Validate Input ***********************",
+           device_name_);
+  DLOGV_IF(kTagDriverConfig, "SDE layer count is %d", hw_layer_info.count);
+
+  mdp_layer_commit_v1 &mdp_commit = mdp_disp_commit_.commit_v1;
+  uint32_t &mdp_layer_count = mdp_commit.input_layer_cnt;
+
+  DLOGI_IF(kTagDriverConfig, "left_roi: x = %d, y = %d, w = %d, h = %d", mdp_commit.left_roi.x,
+    mdp_commit.left_roi.y, mdp_commit.left_roi.w, mdp_commit.left_roi.h);
+  DLOGI_IF(kTagDriverConfig, "right_roi: x = %d, y = %d, w = %d, h = %d", mdp_commit.right_roi.x,
+    mdp_commit.right_roi.y, mdp_commit.right_roi.w, mdp_commit.right_roi.h);
+
+  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;
+    HWPipeInfo *left_pipe = &hw_layers->config[i].left_pipe;
+    HWPipeInfo *right_pipe = &hw_layers->config[i].right_pipe;
+    HWRotatorSession *hw_rotator_session = &hw_layers->config[i].hw_rotator_session;
+    bool is_rotator_used = (hw_rotator_session->hw_block_count != 0);
+    mdp_input_layer mdp_layer;
+
+    for (uint32_t count = 0; count < 2; count++) {
+      HWPipeInfo *pipe_info = (count == 0) ? left_pipe : right_pipe;
+      HWRotateInfo *hw_rotate_info = &hw_rotator_session->hw_rotate_info[count];
+
+      if (hw_rotate_info->valid) {
+        input_buffer = &hw_rotator_session->output_buffer;
+      }
+
+      if (pipe_info->valid) {
+        mdp_input_layer &mdp_layer = mdp_in_layers_[mdp_layer_count];
+        mdp_layer_buffer &mdp_buffer = mdp_layer.buffer;
+
+        mdp_buffer.width = input_buffer->width;
+        mdp_buffer.height = input_buffer->height;
+        mdp_buffer.comp_ratio.denom = 1000;
+        mdp_buffer.comp_ratio.numer = UINT32(hw_layers->config[i].compression * 1000);
+
+        error = SetFormat(input_buffer->format, &mdp_buffer.format);
+        if (error != kErrorNone) {
+          return error;
+        }
+
+        mdp_layer.alpha = layer.plane_alpha;
+        mdp_layer.z_order = UINT16(pipe_info->z_order);
+        mdp_layer.transp_mask = 0xffffffff;
+        SetBlending(layer.blending, &mdp_layer.blend_op);
+        mdp_layer.pipe_ndx = pipe_info->pipe_id;
+        mdp_layer.horz_deci = pipe_info->horizontal_decimation;
+        mdp_layer.vert_deci = pipe_info->vertical_decimation;
+
+        SetRect(pipe_info->src_roi, &mdp_layer.src_rect);
+        SetRect(pipe_info->dst_roi, &mdp_layer.dst_rect);
+        SetMDPFlags(layer, is_rotator_used, &mdp_layer.flags);
+
+        if (pipe_info->scale_data.enable_pixel_ext) {
+          if ((mdp_layer.flags & MDP_LAYER_DEINTERLACE) && (layer.transform.rotation == 90.0f)) {
+            mdp_buffer.width = pipe_info->scale_data.src_width;
+          }
+          SetHWScaleData(pipe_info->scale_data, mdp_layer_count);
+        }
+
+        // Send scale data to MDP driver
+        mdp_layer.scale = GetScaleDataRef(mdp_layer_count);
+        mdp_layer_count++;
+
+        DLOGV_IF(kTagDriverConfig, "******************* Layer[%d] %s pipe Input ******************",
+                 i, count ? "Right" : "Left");
+        DLOGV_IF(kTagDriverConfig, "in_w %d, in_h %d, in_f %d", mdp_buffer.width, mdp_buffer.height,
+                 mdp_buffer.format);
+        DLOGV_IF(kTagDriverConfig, "plane_alpha %d, zorder %d, blending %d, horz_deci %d, "
+                 "vert_deci %d, pipe_id = 0x%x, mdp_flags 0x%x", mdp_layer.alpha, mdp_layer.z_order,
+                 mdp_layer.blend_op, mdp_layer.horz_deci, mdp_layer.vert_deci, mdp_layer.pipe_ndx,
+                 mdp_layer.flags);
+        DLOGV_IF(kTagDriverConfig, "src_rect [%d, %d, %d, %d]", mdp_layer.src_rect.x,
+                 mdp_layer.src_rect.y, mdp_layer.src_rect.w, mdp_layer.src_rect.h);
+        DLOGV_IF(kTagDriverConfig, "dst_rect [%d, %d, %d, %d]", mdp_layer.dst_rect.x,
+                 mdp_layer.dst_rect.y, mdp_layer.dst_rect.w, mdp_layer.dst_rect.h);
+        for (int j = 0; j < 4; j++) {
+          DLOGV_IF(kTagDriverConfig, "Scale Data[%d]: Phase=[%x %x %x %x] Pixel_Ext=[%d %d %d %d]",
+                 j, mdp_layer.scale->init_phase_x[j], mdp_layer.scale->phase_step_x[j],
+                 mdp_layer.scale->init_phase_y[j], mdp_layer.scale->phase_step_y[j],
+                 mdp_layer.scale->num_ext_pxls_left[j], mdp_layer.scale->num_ext_pxls_top[j],
+                 mdp_layer.scale->num_ext_pxls_right[j], mdp_layer.scale->num_ext_pxls_btm[j]);
+          DLOGV_IF(kTagDriverConfig, "Fetch=[%d %d %d %d]  Repeat=[%d %d %d %d]  roi_width = %d",
+                 mdp_layer.scale->left_ftch[j], mdp_layer.scale->top_ftch[j],
+                 mdp_layer.scale->right_ftch[j], mdp_layer.scale->btm_ftch[j],
+                 mdp_layer.scale->left_rpt[j], mdp_layer.scale->top_rpt[j],
+                 mdp_layer.scale->right_rpt[j], mdp_layer.scale->btm_rpt[j],
+                 mdp_layer.scale->roi_w[j]);
+        }
+        DLOGV_IF(kTagDriverConfig, "*************************************************************");
+      }
+    }
+  }
+
+  if (device_type_ == kDeviceVirtual) {
+    LayerBuffer *output_buffer = hw_layers->info.stack->output_buffer;
+    // TODO(user): Need to assign the writeback id from the resource manager, since the support
+    // has not been added hard coding it to 2 for now.
+    mdp_out_layer_.writeback_ndx = 2;
+    mdp_out_layer_.buffer.width = output_buffer->width;
+    mdp_out_layer_.buffer.height = output_buffer->height;
+    mdp_out_layer_.buffer.comp_ratio.denom = 1000;
+    mdp_out_layer_.buffer.comp_ratio.numer = UINT32(hw_layers->output_compression * 1000);
+    SetFormat(output_buffer->format, &mdp_out_layer_.buffer.format);
+
+    DLOGI_IF(kTagDriverConfig, "********************* Output buffer Info ************************");
+    DLOGI_IF(kTagDriverConfig, "out_w %d, out_h %d, out_f %d, wb_id %d",
+             mdp_out_layer_.buffer.width, mdp_out_layer_.buffer.height,
+             mdp_out_layer_.buffer.format, mdp_out_layer_.writeback_ndx);
+    DLOGI_IF(kTagDriverConfig, "*****************************************************************");
+  }
+
+  mdp_commit.flags |= MDP_VALIDATE_LAYER;
+  if (ioctl_(device_fd_, MSMFB_ATOMIC_COMMIT, &mdp_disp_commit_) < 0) {
+    IOCTL_LOGE(MSMFB_ATOMIC_COMMIT, device_type_);
+    DumpLayerCommit(mdp_disp_commit_);
+    return kErrorHardware;
+  }
+
+  return kErrorNone;
+}
+
+void HWDevice::DumpLayerCommit(const mdp_layer_commit &layer_commit) {
+  const mdp_layer_commit_v1 &mdp_commit = layer_commit.commit_v1;
+  const mdp_input_layer *mdp_layers = mdp_commit.input_layers;
+
+  DLOGE("mdp_commit: flags = %x, release fence = %x", mdp_commit.flags, mdp_commit.release_fence);
+  DLOGE("left_roi: x = %d, y = %d, w = %d, h = %d", mdp_commit.left_roi.x, mdp_commit.left_roi.y,
+         mdp_commit.left_roi.w, mdp_commit.left_roi.h);
+  DLOGE("right_roi: x = %d, y = %d, w = %d, h = %d", mdp_commit.right_roi.x,
+         mdp_commit.right_roi.y, mdp_commit.right_roi.w, mdp_commit.right_roi.h);
+  for (uint32_t i = 0; i < mdp_commit.input_layer_cnt; i++) {
+    DLOGE("mdp_commit: layer_cnt = %d, pipe_ndx = %x, zorder = %d, flags = %x",
+          i, mdp_layers[i].pipe_ndx, mdp_layers[i].z_order, mdp_layers[i].flags);
+    const mdp_rect &src_rect = mdp_layers[i].src_rect;
+    DLOGE("src rect: x = %d, y = %d, w = %d, h = %d",
+          src_rect.x, src_rect.y, src_rect.w, src_rect.h);
+    const mdp_rect &dst_rect = mdp_layers[i].dst_rect;
+    DLOGE("dst rect: x = %d, y = %d, w = %d, h = %d",
+          dst_rect.x, dst_rect.y, dst_rect.w, dst_rect.h);
+  }
+}
+
+DisplayError HWDevice::Commit(HWLayers *hw_layers) {
+  DTRACE_SCOPED();
+
+  HWLayersInfo &hw_layer_info = hw_layers->info;
+  LayerStack *stack = hw_layer_info.stack;
+
+  DLOGV_IF(kTagDriverConfig, "*************************** %s Commit Input ************************",
+           device_name_);
+  DLOGV_IF(kTagDriverConfig, "SDE layer count is %d", hw_layer_info.count);
+
+  mdp_layer_commit_v1 &mdp_commit = mdp_disp_commit_.commit_v1;
+  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];
+    LayerBuffer *input_buffer = stack->layers[layer_index].input_buffer;
+    HWPipeInfo *left_pipe = &hw_layers->config[i].left_pipe;
+    HWPipeInfo *right_pipe = &hw_layers->config[i].right_pipe;
+    HWRotatorSession *hw_rotator_session = &hw_layers->config[i].hw_rotator_session;
+
+    for (uint32_t count = 0; count < 2; count++) {
+      HWPipeInfo *pipe_info = (count == 0) ? left_pipe : right_pipe;
+      HWRotateInfo *hw_rotate_info = &hw_rotator_session->hw_rotate_info[count];
+
+      if (hw_rotate_info->valid) {
+        input_buffer = &hw_rotator_session->output_buffer;
+      }
+
+      if (pipe_info->valid) {
+        mdp_layer_buffer &mdp_buffer = mdp_in_layers_[mdp_layer_index].buffer;
+        mdp_input_layer &mdp_layer = mdp_in_layers_[mdp_layer_index];
+        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;
+          SetStride(device_type_, input_buffer->format, input_buffer->planes[0].stride,
+                    &mdp_buffer.planes[0].stride);
+        } else {
+          DLOGW("Invalid buffer fd, setting plane count to 0");
+          mdp_buffer.plane_count = 0;
+        }
+
+        mdp_buffer.fence = input_buffer->acquire_fence_fd;
+        mdp_layer_index++;
+
+        DLOGV_IF(kTagDriverConfig, "****************** Layer[%d] %s pipe Input *******************",
+                 i, count ? "Right" : "Left");
+        DLOGI_IF(kTagDriverConfig, "in_w %d, in_h %d, in_f %d, horz_deci %d, vert_deci %d",
+                 mdp_buffer.width, mdp_buffer.height, mdp_buffer.format, mdp_layer.horz_deci,
+                 mdp_layer.vert_deci);
+        DLOGI_IF(kTagDriverConfig, "in_buf_fd %d, in_buf_offset %d, in_buf_stride %d, " \
+                 "in_plane_count %d, in_fence %d, layer count %d", mdp_buffer.planes[0].fd,
+                 mdp_buffer.planes[0].offset, mdp_buffer.planes[0].stride, mdp_buffer.plane_count,
+                 mdp_buffer.fence, mdp_commit.input_layer_cnt);
+        DLOGV_IF(kTagDriverConfig, "*************************************************************");
+      }
+    }
+  }
+  if (device_type_ == kDeviceVirtual) {
+    LayerBuffer *output_buffer = hw_layers->info.stack->output_buffer;
+
+    if (output_buffer->planes[0].fd >= 0) {
+      mdp_out_layer_.buffer.planes[0].fd = output_buffer->planes[0].fd;
+      mdp_out_layer_.buffer.planes[0].offset = output_buffer->planes[0].offset;
+      SetStride(device_type_, output_buffer->format, output_buffer->planes[0].stride,
+                &mdp_out_layer_.buffer.planes[0].stride);
+      mdp_out_layer_.buffer.plane_count = 1;
+    } else {
+      DLOGW("Invalid output buffer fd, setting plane count to 0");
+      mdp_out_layer_.buffer.plane_count = 0;
+    }
+
+    mdp_out_layer_.buffer.fence = output_buffer->acquire_fence_fd;
+
+    DLOGI_IF(kTagDriverConfig, "********************** Output buffer Info ***********************");
+    DLOGI_IF(kTagDriverConfig, "out_fd %d, out_offset %d, out_stride %d, acquire_fence %d",
+             mdp_out_layer_.buffer.planes[0].fd, mdp_out_layer_.buffer.planes[0].offset,
+             mdp_out_layer_.buffer.planes[0].stride,  mdp_out_layer_.buffer.fence);
+    DLOGI_IF(kTagDriverConfig, "*****************************************************************");
+  }
+
+  mdp_commit.release_fence = -1;
+  mdp_commit.flags &= ~MDP_VALIDATE_LAYER;
+  if (synchronous_commit_) {
+    mdp_commit.flags |= MDP_COMMIT_WAIT_FOR_FINISH;
+  }
+  if (ioctl_(device_fd_, MSMFB_ATOMIC_COMMIT, &mdp_disp_commit_) < 0) {
+    IOCTL_LOGE(MSMFB_ATOMIC_COMMIT, device_type_);
+    DumpLayerCommit(mdp_disp_commit_);
+    synchronous_commit_ = false;
+    return kErrorHardware;
+  }
+
+  stack->retire_fence_fd = mdp_commit.retire_fence;
+
+  // MDP returns only one release fence for the entire layer stack. Duplicate this fence into all
+  // layers being composed by MDP.
+  for (uint32_t i = 0; i < hw_layer_info.count; i++) {
+    uint32_t layer_index = hw_layer_info.index[i];
+    LayerBuffer *input_buffer = stack->layers[layer_index].input_buffer;
+    HWRotatorSession *hw_rotator_session = &hw_layers->config[i].hw_rotator_session;
+    HWRotateInfo *left_rotate = &hw_rotator_session->hw_rotate_info[0];
+    HWRotateInfo *right_rotate = &hw_rotator_session->hw_rotate_info[1];
+
+    if (!left_rotate->valid && !right_rotate->valid) {
+      input_buffer->release_fence_fd = dup(mdp_commit.release_fence);
+      continue;
+    }
+
+    for (uint32_t count = 0; count < 2; count++) {
+      HWRotateInfo *hw_rotate_info = &hw_rotator_session->hw_rotate_info[count];
+      if (hw_rotate_info->valid) {
+        input_buffer = &hw_rotator_session->output_buffer;
+        input_buffer->release_fence_fd = dup(mdp_commit.release_fence);
+        close_(input_buffer->acquire_fence_fd);
+        input_buffer->acquire_fence_fd = -1;
+      }
+    }
+  }
+  DLOGI_IF(kTagDriverConfig, "*************************** %s Commit Input ************************",
+           device_name_);
+  DLOGI_IF(kTagDriverConfig, "retire_fence_fd %d", stack->retire_fence_fd);
+  DLOGI_IF(kTagDriverConfig, "*******************************************************************");
+
+  close_(mdp_commit.release_fence);
+
+  if (synchronous_commit_) {
+    // A synchronous commit can be requested when changing the display mode so we need to update
+    // panel info.
+    PopulateHWPanelInfo();
+    synchronous_commit_ = false;
+  }
+
+  return kErrorNone;
+}
+
+DisplayError HWDevice::Flush() {
+  ResetDisplayParams();
+  mdp_layer_commit_v1 &mdp_commit = mdp_disp_commit_.commit_v1;
+  mdp_commit.input_layer_cnt = 0;
+  mdp_commit.output_layer = NULL;
+
+  mdp_commit.flags &= ~MDP_VALIDATE_LAYER;
+  if (ioctl_(device_fd_, MSMFB_ATOMIC_COMMIT, &mdp_disp_commit_) < 0) {
+    IOCTL_LOGE(MSMFB_ATOMIC_COMMIT, device_type_);
+    DumpLayerCommit(mdp_disp_commit_);
+    return kErrorHardware;
+  }
+  return kErrorNone;
+}
+
+DisplayError HWDevice::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 kFormatRGBA5551:                 *target = MDP_RGBA_5551;         break;
+  case kFormatRGBA4444:                 *target = MDP_RGBA_4444;         break;
+  case kFormatRGB888:                   *target = MDP_RGB_888;           break;
+  case kFormatBGR888:                   *target = MDP_BGR_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 kFormatYCbCr422H1V2SemiPlanar:   *target = MDP_Y_CBCR_H1V2;       break;
+  case kFormatYCrCb422H1V2SemiPlanar:   *target = MDP_Y_CRCB_H1V2;       break;
+  case kFormatYCbCr422H2V1SemiPlanar:   *target = MDP_Y_CBCR_H2V1;       break;
+  case kFormatYCrCb422H2V1SemiPlanar:   *target = MDP_Y_CRCB_H2V1;       break;
+  case kFormatYCbCr422H2V1Packed:       *target = MDP_YCBYCR_H2V1;       break;
+  case kFormatYCbCr420SemiPlanarVenus:  *target = MDP_Y_CBCR_H2V2_VENUS; break;
+  case kFormatRGBA8888Ubwc:             *target = MDP_RGBA_8888_UBWC;    break;
+  case kFormatRGBX8888Ubwc:             *target = MDP_RGBX_8888_UBWC;    break;
+  case kFormatRGB565Ubwc:               *target = MDP_RGB_565_UBWC;      break;
+  case kFormatYCbCr420SPVenusUbwc:      *target = MDP_Y_CBCR_H2V2_UBWC;  break;
+  default:
+    DLOGE("Unsupported format type %d", source);
+    return kErrorParameters;
+  }
+
+  return kErrorNone;
+}
+
+DisplayError HWDevice::SetStride(HWDeviceType device_type, LayerBufferFormat format,
+                                      uint32_t width, uint32_t *target) {
+  // TODO(user): This SetStride function is a workaround to satisfy the driver expectation for
+  // rotator and virtual devices. Eventually this will be taken care in the driver.
+  if (device_type != kDeviceRotator && device_type != kDeviceVirtual) {
+    *target = width;
+    return kErrorNone;
+  }
+
+  switch (format) {
+  case kFormatARGB8888:
+  case kFormatRGBA8888:
+  case kFormatBGRA8888:
+  case kFormatRGBX8888:
+  case kFormatBGRX8888:
+  case kFormatRGBA8888Ubwc:
+  case kFormatRGBX8888Ubwc:
+    *target = width * 4;
+    break;
+  case kFormatRGB888:
+  case kFormatBGR888:
+    *target = width * 3;
+    break;
+  case kFormatRGB565:
+  case kFormatRGB565Ubwc:
+    *target = width * 2;
+    break;
+  case kFormatYCbCr420SemiPlanarVenus:
+  case kFormatYCbCr420SPVenusUbwc:
+  case kFormatYCbCr420Planar:
+  case kFormatYCrCb420Planar:
+  case kFormatYCbCr420SemiPlanar:
+  case kFormatYCrCb420SemiPlanar:
+    *target = width;
+    break;
+  case kFormatYCbCr422H2V1Packed:
+  case kFormatYCrCb422H2V1SemiPlanar:
+  case kFormatYCrCb422H1V2SemiPlanar:
+  case kFormatYCbCr422H2V1SemiPlanar:
+  case kFormatYCbCr422H1V2SemiPlanar:
+  case kFormatRGBA5551:
+  case kFormatRGBA4444:
+    *target = width * 2;
+    break;
+  default:
+    DLOGE("Unsupported format type %d", format);
+    return kErrorParameters;
+  }
+
+  return kErrorNone;
+}
+
+void HWDevice::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 HWDevice::SetRect(const LayerRect &source, mdp_rect *target) {
+  target->x = UINT32(source.left);
+  target->y = UINT32(source.top);
+  target->w = UINT32(source.right) - target->x;
+  target->h = UINT32(source.bottom) - target->y;
+}
+
+void HWDevice::SetMDPFlags(const Layer &layer, const bool &is_rotator_used,
+                           uint32_t *mdp_flags) {
+  LayerBuffer *input_buffer = layer.input_buffer;
+
+  // Flips will be taken care by rotator, if layer uses rotator for downscale/rotation. So ignore
+  // flip flags for MDP.
+  if (!is_rotator_used) {
+    if (layer.transform.flip_vertical) {
+      *mdp_flags |= MDP_LAYER_FLIP_UD;
+    }
+
+    if (layer.transform.flip_horizontal) {
+      *mdp_flags |= MDP_LAYER_FLIP_LR;
+    }
+  }
+
+  if (input_buffer->flags.interlace) {
+    *mdp_flags |= MDP_LAYER_DEINTERLACE;
+  }
+
+  if (input_buffer->flags.secure) {
+    *mdp_flags |= MDP_LAYER_SECURE_SESSION;
+  }
+
+  if (input_buffer->flags.secure_display) {
+    *mdp_flags |= MDP_SECURE_DISPLAY_OVERLAY_SESSION;
+  }
+}
+
+void HWDevice::SyncMerge(const int &fd1, const int &fd2, int *target) {
+  if (fd1 >= 0 && fd2 >= 0) {
+    buffer_sync_handler_->SyncMerge(fd1, fd2, target);
+  } else if (fd1 >= 0) {
+    *target = fd1;
+  } else if (fd2 >= 0) {
+    *target = fd2;
+  }
+}
+
+int HWDevice::GetFBNodeIndex(HWDeviceType device_type) {
+  int fb_node_index = -1;
+  for (int i = 0; i < kDeviceMax; i++) {
+    HWPanelInfo *panel_info = new HWPanelInfo();
+    GetHWPanelInfoByNode(i, panel_info);
+    switch (device_type) {
+    case kDevicePrimary:
+      if (panel_info->is_primary_panel) {
+        fb_node_index = i;
+      }
+      break;
+    case kDeviceHDMI:
+      if (panel_info->port == kPortDTv) {
+        fb_node_index = i;
+      }
+      break;
+    case kDeviceVirtual:
+      if (panel_info->port == kPortWriteBack) {
+        fb_node_index = i;
+      }
+      break;
+    default:
+      break;
+    }
+  }
+  return fb_node_index;
+}
+
+void HWDevice::PopulateHWPanelInfo() {
+  hw_panel_info_ = HWPanelInfo();
+  GetHWPanelInfoByNode(fb_node_index_, &hw_panel_info_);
+  DLOGI("Device type = %d, Display Port = %d, Display Mode = %d, Device Node = %d, Is Primary = %d",
+        device_type_, hw_panel_info_.port, hw_panel_info_.mode, fb_node_index_,
+        hw_panel_info_.is_primary_panel);
+  DLOGI("Partial Update = %d, Dynamic FPS = %d",
+        hw_panel_info_.partial_update, hw_panel_info_.dynamic_fps);
+  DLOGI("Align: left = %d, width = %d, top = %d, height = %d",
+        hw_panel_info_.left_align, hw_panel_info_.width_align,
+        hw_panel_info_.top_align, hw_panel_info_.height_align);
+  DLOGI("ROI: min_width = %d, min_height = %d, need_merge = %d",
+        hw_panel_info_.min_roi_width, hw_panel_info_.min_roi_height,
+        hw_panel_info_.needs_roi_merge);
+  DLOGI("FPS: min = %d, max =%d", hw_panel_info_.min_fps, hw_panel_info_.max_fps);
+  DLOGI("Left Split = %d, Right Split = %d", hw_panel_info_.split_info.left_split,
+        hw_panel_info_.split_info.right_split);
+  DLOGI("Source Split Always = %d", hw_panel_info_.split_info.always_src_split);
+}
+
+void HWDevice::GetHWPanelInfoByNode(int device_node, HWPanelInfo *panel_info) {
+  if (!panel_info) {
+    DLOGE("PanelInfo pointer in invalid.");
+    return;
+  }
+  char stringbuffer[kMaxStringLength];
+  FILE *fileptr = NULL;
+  snprintf(stringbuffer, sizeof(stringbuffer), "%s%d/msm_fb_panel_info", fb_path_, device_node);
+  fileptr = fopen(stringbuffer, "r");
+  if (!fileptr) {
+    DLOGW("Failed to open msm_fb_panel_info node device node %d", device_node);
+    return;
+  }
+
+  size_t len = kMaxStringLength;
+  ssize_t read;
+  char *line = NULL;
+  while ((read = getline(&line, &len, fileptr)) != -1) {
+    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"))) {
+        panel_info->partial_update = atoi(tokens[1]);
+      } else if (!strncmp(tokens[0], "xstart", strlen("xstart"))) {
+        panel_info->left_align = atoi(tokens[1]);
+      } else if (!strncmp(tokens[0], "walign", strlen("walign"))) {
+        panel_info->width_align = atoi(tokens[1]);
+      } else if (!strncmp(tokens[0], "ystart", strlen("ystart"))) {
+        panel_info->top_align = atoi(tokens[1]);
+      } else if (!strncmp(tokens[0], "halign", strlen("halign"))) {
+        panel_info->height_align = atoi(tokens[1]);
+      } else if (!strncmp(tokens[0], "min_w", strlen("min_w"))) {
+        panel_info->min_roi_width = atoi(tokens[1]);
+      } else if (!strncmp(tokens[0], "min_h", strlen("min_h"))) {
+        panel_info->min_roi_height = atoi(tokens[1]);
+      } else if (!strncmp(tokens[0], "roi_merge", strlen("roi_merge"))) {
+        panel_info->needs_roi_merge = atoi(tokens[1]);
+      } else if (!strncmp(tokens[0], "dyn_fps_en", strlen("dyn_fps_en"))) {
+        panel_info->dynamic_fps = atoi(tokens[1]);
+      } else if (!strncmp(tokens[0], "min_fps", strlen("min_fps"))) {
+        panel_info->min_fps = atoi(tokens[1]);
+      } else if (!strncmp(tokens[0], "max_fps", strlen("max_fps"))) {
+        panel_info->max_fps= atoi(tokens[1]);
+      } else if (!strncmp(tokens[0], "primary_panel", strlen("primary_panel"))) {
+        panel_info->is_primary_panel = atoi(tokens[1]);
+      }
+    }
+  }
+  fclose(fileptr);
+  free(line);
+  panel_info->port = GetHWDisplayPort(device_node);
+  panel_info->mode = GetHWDisplayMode(device_node);
+  GetSplitInfo(device_node, panel_info);
+}
+
+HWDisplayPort HWDevice::GetHWDisplayPort(int device_node) {
+  char stringbuffer[kMaxStringLength];
+  DisplayError error = kErrorNone;
+  char *line = NULL;
+  size_t len = kMaxStringLength;
+  ssize_t read;
+  HWDisplayPort port = kPortDefault;
+
+  snprintf(stringbuffer, sizeof(stringbuffer), "%s%d/msm_fb_type", fb_path_, device_node);
+  FILE *fileptr = fopen(stringbuffer, "r");
+  if (!fileptr) {
+    DLOGW("File not found %s", stringbuffer);
+    return port;
+  }
+  read = getline(&line, &len, fileptr);
+  if (read == -1) {
+    fclose(fileptr);
+    return port;
+  }
+  if ((strncmp(line, "mipi dsi cmd panel", strlen("mipi dsi cmd panel")) == 0)) {
+    port = kPortDSI;
+  } else if ((strncmp(line, "mipi dsi video panel", strlen("mipi dsi video panel")) == 0)) {
+    port = kPortDSI;
+  } else if ((strncmp(line, "lvds panel", strlen("lvds panel")) == 0)) {
+    port = kPortLVDS;
+  } else if ((strncmp(line, "edp panel", strlen("edp panel")) == 0)) {
+    port = kPortEDP;
+  } else if ((strncmp(line, "dtv panel", strlen("dtv panel")) == 0)) {
+    port = kPortDTv;
+  } else if ((strncmp(line, "writeback panel", strlen("writeback panel")) == 0)) {
+    port = kPortWriteBack;
+  } else {
+    port = kPortDefault;
+  }
+  fclose(fileptr);
+  free(line);
+  return port;
+}
+
+HWDisplayMode HWDevice::GetHWDisplayMode(int device_node) {
+  char stringbuffer[kMaxStringLength];
+  DisplayError error = kErrorNone;
+  char *line = NULL;
+  size_t len = kMaxStringLength;
+  ssize_t read;
+  HWDisplayMode mode = kModeDefault;
+
+  snprintf(stringbuffer, sizeof(stringbuffer), "%s%d/msm_fb_type", fb_path_, device_node);
+  FILE *fileptr = fopen(stringbuffer, "r");
+  if (!fileptr) {
+    DLOGW("File not found %s", stringbuffer);
+    return mode;
+  }
+  read = getline(&line, &len, fileptr);
+  if (read == -1) {
+    fclose(fileptr);
+    return mode;
+  }
+  if ((strncmp(line, "mipi dsi cmd panel", strlen("mipi dsi cmd panel")) == 0)) {
+    mode = kModeCommand;
+  } else if ((strncmp(line, "mipi dsi video panel", strlen("mipi dsi video panel")) == 0)) {
+    mode = kModeVideo;
+  } else {
+    mode = kModeDefault;
+  }
+  fclose(fileptr);
+  free(line);
+  return mode;
+}
+
+void HWDevice::GetSplitInfo(int device_node, HWPanelInfo *panel_info) {
+  char stringbuffer[kMaxStringLength];
+  FILE *fileptr = NULL;
+  size_t len = kMaxStringLength;
+  ssize_t read;
+  char *line = NULL;
+  uint32_t token_count = 0;
+  const uint32_t max_count = 10;
+  char *tokens[max_count] = { NULL };
+
+  // Split info - for MDSS Version 5 - No need to check version here
+  snprintf(stringbuffer , sizeof(stringbuffer), "%s%d/msm_fb_split", fb_path_, device_node);
+  fileptr = fopen(stringbuffer, "r");
+  if (!fileptr) {
+    DLOGW("File not found %s", stringbuffer);
+    return;
+  }
+
+  // Format "left right" space as delimiter
+  read = getline(&line, &len, fileptr);
+  if (read != -1) {
+    if (!ParseLine(line, tokens, max_count, &token_count)) {
+      panel_info->split_info.left_split = atoi(tokens[0]);
+      panel_info->split_info.right_split = atoi(tokens[1]);
+    }
+  }
+  fclose(fileptr);
+
+  // SourceSplit enabled - Get More information
+  snprintf(stringbuffer , sizeof(stringbuffer), "%s%d/msm_fb_src_split_info", fb_path_,
+           device_node);
+  fileptr = fopen(stringbuffer, "r");
+  if (!fileptr) {
+    DLOGW("File not found %s", stringbuffer);
+    return;
+  }
+
+  read = getline(&line, &len, fileptr);
+  if (read != -1) {
+    if (!strncmp(line, "src_split_always", strlen("src_split_always"))) {
+      panel_info->split_info.always_src_split = true;
+    }
+  }
+  fclose(fileptr);
+  free(line);
+}
+
+int HWDevice::ParseLine(char *input, char *tokens[], const uint32_t max_token, uint32_t *count) {
+  char *tmp_token = NULL;
+  char *temp_ptr;
+  uint32_t index = 0;
+  const char *delim = ", =\n";
+  if (!input) {
+    return -1;
+  }
+  tmp_token = strtok_r(input, delim, &temp_ptr);
+  while (tmp_token && index < max_token) {
+    tokens[index++] = tmp_token;
+    tmp_token = strtok_r(NULL, delim, &temp_ptr);
+  }
+  *count = index;
+
+  return 0;
+}
+
+bool HWDevice::EnableHotPlugDetection(int enable) {
+  bool ret_value = true;
+  char hpdpath[kMaxStringLength];
+  int hdmi_node_index = GetFBNodeIndex(kDeviceHDMI);
+  snprintf(hpdpath , sizeof(hpdpath), "%s%d/hpd", fb_path_, hdmi_node_index);
+  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 = pwrite_(hpdfd, &value, 1, 0);
+  if (length <= 0) {
+    DLOGE("Write failed 'hpd' = %d", enable);
+    ret_value = false;
+  }
+  close_(hpdfd);
+
+  return ret_value;
+}
+
+void HWDevice::ResetDisplayParams() {
+  memset(&mdp_disp_commit_, 0, sizeof(mdp_disp_commit_));
+  memset(&mdp_in_layers_, 0, sizeof(mdp_in_layers_));
+  memset(&mdp_out_layer_, 0, sizeof(mdp_out_layer_));
+  memset(&scale_data_, 0, sizeof(scale_data_));
+
+  for (uint32_t i = 0; i < kMaxSDELayers * 2; i++) {
+    mdp_in_layers_[i].buffer.fence = -1;
+  }
+
+  mdp_disp_commit_.version = MDP_COMMIT_VERSION_1_0;
+  mdp_disp_commit_.commit_v1.input_layers = mdp_in_layers_;
+  mdp_disp_commit_.commit_v1.output_layer = &mdp_out_layer_;
+  mdp_disp_commit_.commit_v1.release_fence = -1;
+  mdp_disp_commit_.commit_v1.retire_fence = -1;
+}
+
+void HWDevice::SetHWScaleData(const ScaleData &scale, uint32_t index) {
+  mdp_scale_data *mdp_scale = GetScaleDataRef(index);
+  mdp_scale->enable_pxl_ext = scale.enable_pixel_ext;
+
+  for (int i = 0; i < 4; i++) {
+    const HWPlane &plane = scale.plane[i];
+    mdp_scale->init_phase_x[i] = plane.init_phase_x;
+    mdp_scale->phase_step_x[i] = plane.phase_step_x;
+    mdp_scale->init_phase_y[i] = plane.init_phase_y;
+    mdp_scale->phase_step_y[i] = plane.phase_step_y;
+
+    mdp_scale->num_ext_pxls_left[i] = plane.left.extension;
+    mdp_scale->left_ftch[i] = plane.left.overfetch;
+    mdp_scale->left_rpt[i] = plane.left.repeat;
+
+    mdp_scale->num_ext_pxls_top[i] = plane.top.extension;
+    mdp_scale->top_ftch[i] = plane.top.overfetch;
+    mdp_scale->top_rpt[i] = plane.top.repeat;
+
+    mdp_scale->num_ext_pxls_right[i] = plane.right.extension;
+    mdp_scale->right_ftch[i] = plane.right.overfetch;
+    mdp_scale->right_rpt[i] = plane.right.repeat;
+
+    mdp_scale->num_ext_pxls_btm[i] = plane.bottom.extension;
+    mdp_scale->btm_ftch[i] = plane.bottom.overfetch;
+    mdp_scale->btm_rpt[i] = plane.bottom.repeat;
+
+    mdp_scale->roi_w[i] = plane.roi_width;
+  }
+}
+
+}  // namespace sdm
+
diff --git a/sdm/libs/core/fb/hw_device.h b/sdm/libs/core/fb/hw_device.h
new file mode 100644
index 0000000..7d617f0
--- /dev/null
+++ b/sdm/libs/core/fb/hw_device.h
@@ -0,0 +1,131 @@
+/*
+* 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:
+*    * Redistributions of source code must retain the above copyright notice, this list of
+*      conditions and the following disclaimer.
+*    * Redistributions in binary form must reproduce the above copyright notice, this list of
+*      conditions and the following disclaimer in the documentation and/or other materials provided
+*      with the distribution.
+*    * Neither the name of The Linux Foundation nor the names of its contributors may be used to
+*      endorse or promote products derived from this software without specific prior written
+*      permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef __HW_DEVICE_H__
+#define __HW_DEVICE_H__
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <linux/msm_mdp_ext.h>
+#include <linux/mdss_rotator.h>
+#include <poll.h>
+#include <pthread.h>
+
+#include "hw_interface.h"
+#include "hw_info_interface.h"
+
+#define IOCTL_LOGE(ioctl, type) DLOGE("ioctl %s, device = %d errno = %d, desc = %s", #ioctl, \
+                                      type, errno, strerror(errno))
+
+namespace sdm {
+
+class HWDevice {
+ protected:
+  explicit HWDevice(BufferSyncHandler *buffer_sync_handler);
+  DisplayError Init();
+  DisplayError Open(HWEventHandler *eventhandler);
+  DisplayError Close();
+  DisplayError GetNumDisplayAttributes(uint32_t *count);
+  DisplayError GetDisplayAttributes(HWDisplayAttributes *display_attributes,
+                                    uint32_t index);
+  DisplayError GetHWPanelInfo(HWPanelInfo *panel_info);
+  DisplayError SetDisplayAttributes(uint32_t index);
+  DisplayError GetConfigIndex(uint32_t mode, uint32_t *index);
+  DisplayError PowerOn();
+  DisplayError PowerOff();
+  DisplayError Doze();
+  DisplayError DozeSuspend();
+  DisplayError Standby();
+  DisplayError Validate(HWLayers *hw_layers);
+  DisplayError Commit(HWLayers *hw_layers);
+  DisplayError Flush();
+
+  enum {
+    kHWEventVSync,
+    kHWEventBlank,
+  };
+
+  static const int kMaxStringLength = 1024;
+  static const int kNumPhysicalDisplays = 2;
+  static const int kNumDisplayEvents = 4;
+
+  void DumpLayerCommit(const mdp_layer_commit &layer_commit);
+  DisplayError SetFormat(const LayerBufferFormat &source, uint32_t *target);
+  DisplayError SetStride(HWDeviceType device_type, LayerBufferFormat format,
+                         uint32_t width, uint32_t *target);
+  void SetBlending(const LayerBlending &source, mdss_mdp_blend_op *target);
+  void SetRect(const LayerRect &source, mdp_rect *target);
+  void SetMDPFlags(const Layer &layer, const bool &is_rotator_used, uint32_t *mdp_flags);
+  void SyncMerge(const int &fd1, const int &fd2, int *target);
+
+  // Retrieves HW FrameBuffer Node Index
+  int GetFBNodeIndex(HWDeviceType device_type);
+  // Populates HWPanelInfo based on node index
+  void PopulateHWPanelInfo();
+  void GetHWPanelInfoByNode(int device_node, HWPanelInfo *panel_info);
+  HWDisplayPort GetHWDisplayPort(int device_node);
+  HWDisplayMode GetHWDisplayMode(int device_node);
+  void GetSplitInfo(int device_node, HWPanelInfo *panel_info);
+  int ParseLine(char *input, char *tokens[], const uint32_t max_token, uint32_t *count);
+  mdp_scale_data* GetScaleDataRef(uint32_t index) { return &scale_data_[index]; }
+  void SetHWScaleData(const ScaleData &scale, uint32_t index);
+  void ResetDisplayParams();
+
+  bool EnableHotPlugDetection(int enable);
+
+  // Pointers to system calls which are either mapped to actual system call or virtual driver.
+  int (*ioctl_)(int, int, ...);
+  int (*open_)(const char *, int, ...);
+  int (*close_)(int);
+  int (*poll_)(struct pollfd *, nfds_t, int);
+  ssize_t (*pread_)(int, void *, size_t, off_t);
+  ssize_t (*pwrite_)(int, const void *, size_t, off_t);
+  FILE* (*fopen_)( const char *fname, const char *mode);
+  int (*fclose_)(FILE* fileptr);
+  ssize_t (*getline_)(char **lineptr, size_t *linelen, FILE *stream);
+
+  // Store the Device EventHandler - used for callback
+  HWEventHandler *event_handler_;
+  HWResourceInfo hw_resource_;
+  HWPanelInfo hw_panel_info_;
+  HWInfoInterface *hw_info_intf_;
+  int fb_node_index_;
+  const char *fb_path_;
+  bool hotplug_enabled_;
+  BufferSyncHandler *buffer_sync_handler_;
+  int device_fd_;
+  HWDeviceType device_type_;
+  mdp_layer_commit mdp_disp_commit_;
+  mdp_input_layer mdp_in_layers_[kMaxSDELayers * 2];   // split panel (left + right)
+  mdp_scale_data scale_data_[kMaxSDELayers * 2];
+  mdp_output_layer mdp_out_layer_;
+  const char *device_name_;
+  bool synchronous_commit_;
+};
+
+}  // namespace sdm
+
+#endif  // __HW_DEVICE_H__
+
diff --git a/sdm/libs/core/fb/hw_hdmi.cpp b/sdm/libs/core/fb/hw_hdmi.cpp
new file mode 100644
index 0000000..1a5c538
--- /dev/null
+++ b/sdm/libs/core/fb/hw_hdmi.cpp
@@ -0,0 +1,421 @@
+/*
+* Copyright (c) 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:
+*     * 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 <sys/ioctl.h>
+#include <ctype.h>
+#include <utils/debug.h>
+#include <fcntl.h>
+#include "hw_hdmi.h"
+
+#define __CLASS__ "HWHDMI"
+
+namespace sdm {
+
+static int ParseLine(char *input, char *tokens[], const uint32_t max_token, uint32_t *count) {
+  char *tmp_token = NULL;
+  char *temp_ptr;
+  uint32_t index = 0;
+  const char *delim = ", =\n";
+  if (!input) {
+    return -1;
+  }
+  tmp_token = strtok_r(input, delim, &temp_ptr);
+  while (tmp_token && index < max_token) {
+    tokens[index++] = tmp_token;
+    tmp_token = strtok_r(NULL, delim, &temp_ptr);
+  }
+  *count = index;
+
+  return 0;
+}
+
+static bool 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;
+}
+
+DisplayError HWHDMIInterface::Create(HWHDMIInterface **intf, HWInfoInterface *hw_info_intf,
+                                     BufferSyncHandler *buffer_sync_handler) {
+  DisplayError error = kErrorNone;
+  HWHDMI *hw_fb_hdmi = NULL;
+
+  hw_fb_hdmi = new HWHDMI(buffer_sync_handler, hw_info_intf);
+  error = hw_fb_hdmi->Init();
+  if (error != kErrorNone) {
+    delete hw_fb_hdmi;
+  } else {
+    *intf = hw_fb_hdmi;
+  }
+  return error;
+}
+
+DisplayError HWHDMIInterface::Destroy(HWHDMIInterface *intf) {
+  HWHDMI *hw_fb_hdmi = static_cast<HWHDMI *>(intf);
+  hw_fb_hdmi->Deinit();
+  delete hw_fb_hdmi;
+
+  return kErrorNone;
+}
+
+HWHDMI::HWHDMI(BufferSyncHandler *buffer_sync_handler,  HWInfoInterface *hw_info_intf)
+  : HWDevice(buffer_sync_handler), hw_scan_info_() {
+  HWDevice::device_type_ = kDeviceHDMI;
+  HWDevice::device_name_ = "HDMI Display Device";
+  HWDevice::hw_info_intf_ = hw_info_intf;
+}
+
+DisplayError HWHDMI::Init() {
+  DisplayError error = kErrorNone;
+
+  error = HWDevice::Init();
+  if (error != kErrorNone) {
+    goto CleanupOnError;
+  }
+
+  // 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);
+
+  ReadScanInfo();
+  return kErrorNone;
+
+CleanupOnError:
+  if (supported_video_modes_) {
+    delete supported_video_modes_;
+  }
+
+  return error;
+}
+
+DisplayError HWHDMI::Deinit() {
+  hdmi_mode_count_ = 0;
+  if (supported_video_modes_) {
+    delete supported_video_modes_;
+  }
+
+  return kErrorNone;
+}
+
+DisplayError HWHDMI::Open(HWEventHandler *eventhandler) {
+  return HWDevice::Open(eventhandler);
+}
+
+DisplayError HWHDMI::Close() {
+  return HWDevice::Close();
+}
+
+DisplayError HWHDMI::GetNumDisplayAttributes(uint32_t *count) {
+  *count = GetHDMIModeCount();
+  if (*count <= 0) {
+    return kErrorHardware;
+  }
+
+  return kErrorNone;
+}
+
+int HWHDMI::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_);
+  int edid_file = open_(edid_path, O_RDONLY);
+  if (edid_file < 0) {
+    DLOGE("EDID file open failed.");
+    return -1;
+  }
+
+  length = pread_(edid_file, edid_str, sizeof(edid_str)-1, 0);
+  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;
+}
+
+DisplayError HWHDMI::GetDisplayAttributes(HWDisplayAttributes *display_attributes,
+                                                     uint32_t index) {
+  DTRACE_SCOPED();
+
+  // Variable screen info
+  STRUCT_VAR(fb_var_screeninfo, var_screeninfo);
+
+  // 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;
+  uint32_t h_blanking = timing_mode->front_porch_h + timing_mode->back_porch_h +
+      timing_mode->pulse_width_h;
+  display_attributes->h_total = timing_mode->active_h + h_blanking;
+  display_attributes->x_dpi = 0;
+  display_attributes->y_dpi = 0;
+  display_attributes->fps = timing_mode->refresh_rate / 1000;
+  display_attributes->vsync_period_ns = UINT32(1000000000L / display_attributes->fps);
+  display_attributes->split_left = display_attributes->x_pixels;
+  if (display_attributes->x_pixels > hw_resource_.max_mixer_width) {
+    display_attributes->is_device_split = true;
+    display_attributes->split_left = display_attributes->x_pixels / 2;
+    display_attributes->h_total += h_blanking;
+  }
+  return kErrorNone;
+}
+
+DisplayError HWHDMI::SetDisplayAttributes(uint32_t index) {
+  DTRACE_SCOPED();
+
+  DisplayError error = kErrorNone;
+
+  // Variable screen info
+  STRUCT_VAR(fb_var_screeninfo, vscreeninfo);
+  if (ioctl_(device_fd_, FBIOGET_VSCREENINFO, &vscreeninfo) < 0) {
+    IOCTL_LOGE(FBIOGET_VSCREENINFO, device_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);
+  metadata.op = metadata_op_vic;
+  metadata.data.video_info_code = timing_mode->video_format;
+  if (ioctl(device_fd_, MSMFB_METADATA_SET, &metadata) < 0) {
+    IOCTL_LOGE(MSMFB_METADATA_SET, device_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_(device_fd_, FBIOPUT_VSCREENINFO, &vscreeninfo) < 0) {
+    IOCTL_LOGE(FBIOGET_VSCREENINFO, device_type_);
+    return kErrorHardware;
+  }
+
+  return kErrorNone;
+}
+
+DisplayError HWHDMI::GetConfigIndex(uint32_t mode, uint32_t *index) {
+  // 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;
+    }
+  }
+
+  DLOGE("Config = %d not supported", mode);
+  return kErrorNotSupported;
+}
+
+DisplayError HWHDMI::PowerOn() {
+  return HWDevice::PowerOn();
+}
+
+DisplayError HWHDMI::PowerOff() {
+  return HWDevice::PowerOff();
+}
+
+DisplayError HWHDMI::Doze() {
+  return HWDevice::Doze();
+}
+
+DisplayError HWHDMI::DozeSuspend() {
+  return HWDevice::DozeSuspend();
+}
+
+DisplayError HWHDMI::Standby() {
+  return HWDevice::Standby();
+}
+
+DisplayError HWHDMI::Validate(HWLayers *hw_layers) {
+  HWDevice::ResetDisplayParams();
+  return HWDevice::Validate(hw_layers);
+}
+
+DisplayError HWHDMI::Commit(HWLayers *hw_layers) {
+  return HWDevice::Commit(hw_layers);
+}
+
+DisplayError HWHDMI::Flush() {
+  return HWDevice::Flush();
+}
+
+DisplayError HWHDMI::GetHWPanelInfo(HWPanelInfo *panel_info) {
+  return HWDevice::GetHWPanelInfo(panel_info);
+}
+
+DisplayError HWHDMI::GetHWScanInfo(HWScanInfo *scan_info) {
+  if (!scan_info) {
+    return kErrorParameters;
+  }
+  *scan_info = hw_scan_info_;
+  return kErrorNone;
+}
+
+DisplayError HWHDMI::GetVideoFormat(uint32_t config_index, uint32_t *video_format) {
+  *video_format = hdmi_modes_[config_index];
+
+  return kErrorNone;
+}
+
+DisplayError HWHDMI::GetMaxCEAFormat(uint32_t *max_cea_format) {
+  *max_cea_format = HDMI_VFRMT_END;
+
+  return kErrorNone;
+}
+
+HWScanSupport HWHDMI::MapHWScanSupport(uint32_t value) {
+  switch (value) {
+  // TODO(user): Read the scan type from driver defined values instead of hardcoding
+  case 0:
+    return kScanNotSupported;
+  case 1:
+    return kScanAlwaysOverscanned;
+  case 2:
+    return kScanAlwaysUnderscanned;
+  case 3:
+    return kScanBoth;
+  default:
+    return kScanNotSupported;
+    break;
+  }
+}
+
+void HWHDMI::ReadScanInfo() {
+  int scan_info_file = -1;
+  ssize_t len = -1;
+  char data[PAGE_SIZE] = {'\0'};
+
+  snprintf(data, sizeof(data), "%s%d/scan_info", fb_path_, fb_node_index_);
+  scan_info_file = open_(data, O_RDONLY);
+  if (scan_info_file < 0) {
+    DLOGW("File '%s' not found.", data);
+    return;
+  }
+
+  memset(&data[0], 0, sizeof(data));
+  len = read(scan_info_file, data, sizeof(data) - 1);
+  if (len <= 0) {
+    close_(scan_info_file);
+    DLOGW("File %s%d/scan_info is empty.", fb_path_, fb_node_index_);
+    return;
+  }
+  data[len] = '\0';
+  close_(scan_info_file);
+
+  const uint32_t scan_info_max_count = 3;
+  uint32_t scan_info_count = 0;
+  char *tokens[scan_info_max_count] = { NULL };
+  ParseLine(data, tokens, scan_info_max_count, &scan_info_count);
+  if (scan_info_count != scan_info_max_count) {
+    DLOGW("Failed to parse scan info string %s", data);
+    return;
+  }
+
+  hw_scan_info_.pt_scan_support = MapHWScanSupport(atoi(tokens[0]));
+  hw_scan_info_.it_scan_support = MapHWScanSupport(atoi(tokens[1]));
+  hw_scan_info_.cea_scan_support = MapHWScanSupport(atoi(tokens[2]));
+  DLOGI("PT %d IT %d CEA %d", hw_scan_info_.pt_scan_support, hw_scan_info_.it_scan_support,
+        hw_scan_info_.cea_scan_support);
+}
+
+}  // namespace sdm
+
diff --git a/sdm/libs/core/fb/hw_hdmi.h b/sdm/libs/core/fb/hw_hdmi.h
new file mode 100644
index 0000000..8ac491d
--- /dev/null
+++ b/sdm/libs/core/fb/hw_hdmi.h
@@ -0,0 +1,74 @@
+/*
+* Copyright (c) 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:
+*    * Redistributions of source code must retain the above copyright notice, this list of
+*      conditions and the following disclaimer.
+*    * Redistributions in binary form must reproduce the above copyright notice, this list of
+*      conditions and the following disclaimer in the documentation and/or other materials provided
+*      with the distribution.
+*    * Neither the name of The Linux Foundation nor the names of its contributors may be used to
+*      endorse or promote products derived from this software without specific prior written
+*      permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef __HW_HDMI_H__
+#define __HW_HDMI_H__
+
+#include <video/msm_hdmi_modes.h>
+#include "hw_device.h"
+#include "hw_hdmi_interface.h"
+
+namespace sdm {
+
+class HWHDMI : public HWDevice, public HWHDMIInterface {
+ public:
+  HWHDMI(BufferSyncHandler *buffer_sync_handler, HWInfoInterface *hw_info_intf);
+  virtual DisplayError Init();
+  virtual DisplayError Deinit();
+  virtual DisplayError Open(HWEventHandler *eventhandler);
+  virtual DisplayError Close();
+  virtual DisplayError GetNumDisplayAttributes(uint32_t *count);
+  virtual DisplayError GetDisplayAttributes(HWDisplayAttributes *display_attributes,
+                                            uint32_t index);
+  virtual DisplayError GetHWPanelInfo(HWPanelInfo *panel_info);
+  virtual DisplayError GetHWScanInfo(HWScanInfo *scan_info);
+  virtual DisplayError GetVideoFormat(uint32_t config_index, uint32_t *video_format);
+  virtual DisplayError GetMaxCEAFormat(uint32_t *max_cea_format);
+  virtual DisplayError SetDisplayAttributes(uint32_t index);
+  virtual DisplayError GetConfigIndex(uint32_t mode, uint32_t *index);
+  virtual DisplayError PowerOn();
+  virtual DisplayError PowerOff();
+  virtual DisplayError Doze();
+  virtual DisplayError DozeSuspend();
+  virtual DisplayError Standby();
+  virtual DisplayError Validate(HWLayers *hw_layers);
+  virtual DisplayError Commit(HWLayers *hw_layers);
+  virtual DisplayError Flush();
+
+ private:
+  int GetHDMIModeCount();
+  void ReadScanInfo();
+  HWScanSupport MapHWScanSupport(uint32_t value);
+
+  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_;
+  HWScanInfo hw_scan_info_;
+};
+
+}  // namespace sdm
+
+#endif  // __HW_HDMI_H__
+
diff --git a/sdm/libs/core/fb/hw_info.cpp b/sdm/libs/core/fb/hw_info.cpp
new file mode 100644
index 0000000..b998a46
--- /dev/null
+++ b/sdm/libs/core/fb/hw_info.cpp
@@ -0,0 +1,173 @@
+/*
+* Copyright (c) 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:
+*    * 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 "hw_info.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <utils/constants.h>
+#include <utils/debug.h>
+
+#define __CLASS__ "HWInfo"
+
+namespace sdm {
+
+int HWInfo::ParseLine(char *input, char *tokens[], const uint32_t max_token, uint32_t *count) {
+  char *tmp_token = NULL;
+  char *temp_ptr;
+  uint32_t index = 0;
+  const char *delim = ", =\n";
+  if (!input) {
+    return -1;
+  }
+  tmp_token = strtok_r(input, delim, &temp_ptr);
+  while (tmp_token && index < max_token) {
+    tokens[index++] = tmp_token;
+    tmp_token = strtok_r(NULL, delim, &temp_ptr);
+  }
+  *count = index;
+
+  return 0;
+}
+
+DisplayError HWInfoInterface::Create(HWInfoInterface **intf) {
+  DisplayError error = kErrorNone;
+  HWInfo *hw_info = NULL;
+
+  hw_info = new HWInfo();
+  if (!hw_info) {
+    error = kErrorMemory;
+  } else {
+    *intf = hw_info;
+  }
+
+  return error;
+}
+
+DisplayError HWInfoInterface::Destroy(HWInfoInterface *intf) {
+  HWInfo *hw_info = static_cast<HWInfo *>(intf);
+  delete hw_info;
+
+  return kErrorNone;
+}
+
+DisplayError HWInfo::GetHWResourceInfo(HWResourceInfo *hw_resource) {
+  if (!hw_resource) {
+    DLOGE("HWResourceInfo pointer in invalid.");
+    return kErrorParameters;
+  }
+  const char *kHWCapabilitiesPath = "/sys/devices/virtual/graphics/fb";
+  FILE *fileptr = NULL;
+  char stringbuffer[kMaxStringLength];
+  uint32_t token_count = 0;
+  const uint32_t max_count = 10;
+  char *tokens[max_count] = { NULL };
+  snprintf(stringbuffer , sizeof(stringbuffer), "%s%d/mdp/caps",
+           kHWCapabilitiesPath, kHWCapabilitiesNode);
+  fileptr = fopen(stringbuffer, "rb");
+
+  if (!fileptr) {
+    DLOGE("File '%s' not found", stringbuffer);
+    return kErrorHardware;
+  }
+
+  size_t len = kMaxStringLength;
+  ssize_t read;
+  char *line = stringbuffer;
+  hw_resource->hw_version = kHWMdssVersion5;
+  while ((read = getline(&line, &len, fileptr)) != -1) {
+    // parse the line and update information accordingly
+    if (!ParseLine(line, tokens, max_count, &token_count)) {
+      if (!strncmp(tokens[0], "hw_rev", strlen("hw_rev"))) {
+        hw_resource->hw_revision = atoi(tokens[1]);  // HW Rev, v1/v2
+      } else if (!strncmp(tokens[0], "rgb_pipes", strlen("rgb_pipes"))) {
+        hw_resource->num_rgb_pipe = UINT8(atoi(tokens[1]));
+      } else if (!strncmp(tokens[0], "vig_pipes", strlen("vig_pipes"))) {
+        hw_resource->num_vig_pipe = UINT8(atoi(tokens[1]));
+      } else if (!strncmp(tokens[0], "dma_pipes", strlen("dma_pipes"))) {
+        hw_resource->num_dma_pipe = UINT8(atoi(tokens[1]));
+      } else if (!strncmp(tokens[0], "cursor_pipes", strlen("cursor_pipes"))) {
+        hw_resource->num_cursor_pipe = UINT8(atoi(tokens[1]));
+      } else if (!strncmp(tokens[0], "blending_stages", strlen("blending_stages"))) {
+        hw_resource->num_blending_stages = UINT8(atoi(tokens[1]));
+      } else if (!strncmp(tokens[0], "max_downscale_ratio", strlen("max_downscale_ratio"))) {
+        hw_resource->max_scale_down = atoi(tokens[1]);
+      } else if (!strncmp(tokens[0], "max_upscale_ratio", strlen("max_upscale_ratio"))) {
+        hw_resource->max_scale_up = atoi(tokens[1]);
+      } else if (!strncmp(tokens[0], "max_bandwidth_low", strlen("max_bandwidth_low"))) {
+        hw_resource->max_bandwidth_low = atol(tokens[1]);
+      } else if (!strncmp(tokens[0], "max_bandwidth_high", strlen("max_bandwidth_high"))) {
+        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_width", strlen("max_pipe_width"))) {
+        hw_resource->max_pipe_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 (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"))) {
+            hw_resource->has_decimation = true;
+          } else if (!strncmp(tokens[i], "tile_format", strlen("tile_format"))) {
+            hw_resource->has_macrotile = true;
+          } else if (!strncmp(tokens[i], "src_split", strlen("src_split"))) {
+            hw_resource->is_src_split = true;
+          } else if (!strncmp(tokens[i], "non_scalar_rgb", strlen("non_scalar_rgb"))) {
+            hw_resource->has_non_scalar_rgb = true;
+          } else if (!strncmp(tokens[i], "rotator_downscale", strlen("rotator_downscale"))) {
+            hw_resource->has_rotator_downscale = true;
+          }
+        }
+      }
+    }
+  }
+  fclose(fileptr);
+
+  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,
+        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,
+        hw_resource->has_decimation, hw_resource->has_macrotile,
+        hw_resource->has_rotator_downscale);
+  DLOGI("SourceSplit = %d", hw_resource->is_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 kErrorNone;
+}
+
+}  // namespace sdm
+
diff --git a/sdm/libs/core/fb/hw_info.h b/sdm/libs/core/fb/hw_info.h
new file mode 100644
index 0000000..95f669f
--- /dev/null
+++ b/sdm/libs/core/fb/hw_info.h
@@ -0,0 +1,54 @@
+/*
+* Copyright (c) 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:
+*    * Redistributions of source code must retain the above copyright notice, this list of
+*      conditions and the following disclaimer.
+*    * Redistributions in binary form must reproduce the above copyright notice, this list of
+*      conditions and the following disclaimer in the documentation and/or other materials provided
+*      with the distribution.
+*    * Neither the name of The Linux Foundation nor the names of its contributors may be used to
+*      endorse or promote products derived from this software without specific prior written
+*      permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef __HW_INFO_H__
+#define __HW_INFO_H__
+
+#include <inttypes.h>
+#include <core/sdm_types.h>
+#include <private/hw_info_types.h>
+#include "hw_info_interface.h"
+
+namespace sdm {
+
+class HWInfo: public HWInfoInterface {
+ public:
+  virtual DisplayError GetHWResourceInfo(HWResourceInfo *hw_resource);
+
+ private:
+  // TODO(user): Read Mdss version from the driver
+  static const int kHWMdssVersion5 = 500;  // MDSS_V5
+  static const int kMaxStringLength = 1024;
+  // MDP Capabilities are replicated across all frame buffer devices.
+  // However, we rely on reading the capabalities from fbO since this
+  // is guaranteed to be available.
+  static const int kHWCapabilitiesNode = 0;
+
+  static int ParseLine(char *input, char *tokens[], const uint32_t max_token, uint32_t *count);
+};
+
+}  // namespace sdm
+
+#endif  // __HW_INFO_H__
+
diff --git a/sdm/libs/core/fb/hw_primary.cpp b/sdm/libs/core/fb/hw_primary.cpp
new file mode 100644
index 0000000..cb4d8b2
--- /dev/null
+++ b/sdm/libs/core/fb/hw_primary.cpp
@@ -0,0 +1,498 @@
+/*
+* Copyright (c) 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:
+*     * 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 <sys/prctl.h>
+#include <sys/ioctl.h>
+#include <pthread.h>
+#include <sys/resource.h>
+#include <fcntl.h>
+#include <utils/debug.h>
+#include "hw_primary.h"
+
+#define __CLASS__ "HWPrimary"
+
+namespace sdm {
+
+DisplayError HWPrimaryInterface::Create(HWPrimaryInterface **intf, HWInfoInterface *hw_info_intf,
+                                        BufferSyncHandler *buffer_sync_handler) {
+  DisplayError error = kErrorNone;
+  HWPrimary *hw_primary = NULL;
+
+  hw_primary = new HWPrimary(buffer_sync_handler, hw_info_intf);
+  error = hw_primary->Init();
+  if (error != kErrorNone) {
+    delete hw_primary;
+  } else {
+    *intf = hw_primary;
+  }
+
+  return error;
+}
+
+DisplayError HWPrimaryInterface::Destroy(HWPrimaryInterface *intf) {
+  HWPrimary *hw_primary = static_cast<HWPrimary *>(intf);
+  hw_primary->Deinit();
+  delete hw_primary;
+
+  return kErrorNone;
+}
+
+HWPrimary::HWPrimary(BufferSyncHandler *buffer_sync_handler, HWInfoInterface *hw_info_intf)
+  : HWDevice(buffer_sync_handler), event_thread_name_("SDM_EventThread"), fake_vsync_(false),
+    exit_threads_(false), config_changed_(true) {
+  HWDevice::device_type_ = kDevicePrimary;
+  HWDevice::device_name_ = "Primary Display Device";
+  HWDevice::hw_info_intf_ = hw_info_intf;
+}
+
+DisplayError HWPrimary::Init() {
+  DisplayError error = kErrorNone;
+  char node_path[kMaxStringLength] = {0};
+  char data[kMaxStringLength] = {0};
+  const char* event_name[kNumDisplayEvents] = {"vsync_event", "show_blank_event", "idle_notify",
+                                              "msm_fb_thermal_level"};
+
+  error = HWDevice::Init();
+  if (error != kErrorNone) {
+    goto CleanupOnError;
+  }
+
+  // Open nodes for polling
+  for (int event = 0; event < kNumDisplayEvents; event++) {
+    poll_fds_[event].fd = -1;
+  }
+
+  if (!fake_vsync_) {
+    for (int event = 0; event < kNumDisplayEvents; event++) {
+      pollfd &poll_fd = poll_fds_[event];
+
+      if ((hw_panel_info_.mode == kModeCommand) &&
+          (!strncmp(event_name[event], "idle_notify", strlen("idle_notify")))) {
+        continue;
+      }
+
+      snprintf(node_path, sizeof(node_path), "%s%d/%s", fb_path_, fb_node_index_,
+               event_name[event]);
+
+      poll_fd.fd = open_(node_path, O_RDONLY);
+      if (poll_fd.fd < 0) {
+        DLOGE("open failed for event=%d, error=%s", event, strerror(errno));
+        error = kErrorHardware;
+        goto CleanupOnError;
+      }
+
+      // Read once on all fds to clear data on all fds.
+      pread_(poll_fd.fd, data , kMaxStringLength, 0);
+      poll_fd.events = POLLPRI | POLLERR;
+    }
+  }
+
+  // Start the Event thread
+  if (pthread_create(&event_thread_, NULL, &DisplayEventThread, this) < 0) {
+    DLOGE("Failed to start %s, error = %s", event_thread_name_);
+    error = kErrorResources;
+    goto CleanupOnError;
+  }
+
+  // Disable HPD at start if HDMI is external, it will be enabled later when the display powers on
+  // This helps for framework reboot or adb shell stop/start
+  EnableHotPlugDetection(0);
+
+  return kErrorNone;
+
+CleanupOnError:
+  // Close all poll fds
+  for (int event = 0; event < kNumDisplayEvents; event++) {
+    int &fd = poll_fds_[event].fd;
+    if (fd >= 0) {
+      close_(fd);
+    }
+  }
+
+  return error;
+}
+
+DisplayError HWPrimary::Deinit() {
+  exit_threads_ = true;
+  pthread_join(event_thread_, NULL);
+
+  for (int event = 0; event < kNumDisplayEvents; event++) {
+    close_(poll_fds_[event].fd);
+  }
+
+  return kErrorNone;
+}
+
+DisplayError HWPrimary::Open(HWEventHandler *eventhandler) {
+  return HWDevice::Open(eventhandler);
+}
+
+DisplayError HWPrimary::Close() {
+  return HWDevice::Close();
+}
+
+DisplayError HWPrimary::GetNumDisplayAttributes(uint32_t *count) {
+  return HWDevice::GetNumDisplayAttributes(count);
+}
+
+DisplayError HWPrimary::GetDisplayAttributes(HWDisplayAttributes *display_attributes,
+                                             uint32_t index) {
+  if (!display_attributes) {
+    return kErrorParameters;
+  }
+
+  if (config_changed_) {
+    PopulateDisplayAttributes();
+    config_changed_ = false;
+  }
+
+  *display_attributes = display_attributes_;
+
+  return kErrorNone;
+}
+
+DisplayError HWPrimary::PopulateDisplayAttributes() {
+  DTRACE_SCOPED();
+
+  // Variable screen info
+  STRUCT_VAR(fb_var_screeninfo, var_screeninfo);
+
+  if (ioctl_(device_fd_, FBIOGET_VSCREENINFO, &var_screeninfo) < 0) {
+    IOCTL_LOGE(FBIOGET_VSCREENINFO, device_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) < 0) {
+    IOCTL_LOGE(MSMFB_METADATA_GET, device_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;
+  uint32_t h_blanking = var_screeninfo.right_margin + var_screeninfo.left_margin +
+      var_screeninfo.hsync_len;
+  display_attributes_.h_total = var_screeninfo.xres + var_screeninfo.right_margin +
+      var_screeninfo.left_margin + var_screeninfo.hsync_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 = meta_data.data.panel_frame_rate;
+  display_attributes_.vsync_period_ns = UINT32(1000000000L / display_attributes_.fps);
+  display_attributes_.is_device_split = (hw_panel_info_.split_info.left_split ||
+      (var_screeninfo.xres > hw_resource_.max_mixer_width)) ? true : false;
+  display_attributes_.split_left = hw_panel_info_.split_info.left_split ?
+      hw_panel_info_.split_info.left_split : display_attributes_.x_pixels / 2;
+  display_attributes_.always_src_split = hw_panel_info_.split_info.always_src_split;
+  display_attributes_.h_total += display_attributes_.is_device_split ? h_blanking : 0;
+
+  return kErrorNone;
+}
+
+DisplayError HWPrimary::SetDisplayAttributes(uint32_t index) {
+  return HWDevice::SetDisplayAttributes(index);
+}
+
+DisplayError HWPrimary::SetRefreshRate(uint32_t refresh_rate) {
+  char node_path[kMaxStringLength] = {0};
+
+  DLOGI("Setting refresh rate to = %d fps", refresh_rate);
+
+  snprintf(node_path, sizeof(node_path), "%s%d/dynamic_fps", fb_path_, fb_node_index_);
+
+  int fd = open_(node_path, O_WRONLY);
+  if (fd < 0) {
+    DLOGE("Failed to open %s with error %s", node_path, strerror(errno));
+    return kErrorFileDescriptor;
+  }
+
+  char refresh_rate_string[kMaxStringLength];
+  snprintf(refresh_rate_string, sizeof(refresh_rate_string), "%d", refresh_rate);
+  ssize_t len = pwrite_(fd, refresh_rate_string, strlen(refresh_rate_string), 0);
+  if (len < 0) {
+    DLOGE("Failed to write %d with error %s", refresh_rate, strerror(errno));
+    close_(fd);
+    return kErrorUndefined;
+  }
+  close_(fd);
+
+  config_changed_ = true;
+  synchronous_commit_ = true;
+
+  return kErrorNone;
+}
+
+DisplayError HWPrimary::GetConfigIndex(uint32_t mode, uint32_t *index) {
+  return HWDevice::GetConfigIndex(mode, index);
+}
+
+DisplayError HWPrimary::PowerOn() {
+  return HWDevice::PowerOn();
+}
+
+DisplayError HWPrimary::PowerOff() {
+  if (ioctl_(device_fd_, FBIOBLANK, FB_BLANK_POWERDOWN) < 0) {
+    IOCTL_LOGE(FB_BLANK_POWERDOWN, device_type_);
+    return kErrorHardware;
+  }
+
+  return kErrorNone;
+}
+
+DisplayError HWPrimary::Doze() {
+  if (ioctl_(device_fd_, FBIOBLANK, FB_BLANK_NORMAL) < 0) {
+    IOCTL_LOGE(FB_BLANK_NORMAL, device_type_);
+    return kErrorHardware;
+  }
+
+  return kErrorNone;
+}
+
+DisplayError HWPrimary::DozeSuspend() {
+  if (ioctl_(device_fd_, FBIOBLANK, FB_BLANK_VSYNC_SUSPEND) < 0) {
+    IOCTL_LOGE(FB_BLANK_VSYNC_SUSPEND, device_type_);
+    return kErrorHardware;
+  }
+
+  return kErrorNone;
+}
+
+DisplayError HWPrimary::Standby() {
+  return HWDevice::Standby();
+}
+
+DisplayError HWPrimary::Validate(HWLayers *hw_layers) {
+  HWDevice::ResetDisplayParams();
+
+  mdp_layer_commit_v1 &mdp_commit = mdp_disp_commit_.commit_v1;
+
+  LayerRect left_roi = hw_layers->info.left_partial_update;
+  LayerRect right_roi = hw_layers->info.right_partial_update;
+  mdp_commit.left_roi.x = INT(left_roi.left);
+  mdp_commit.left_roi.y = INT(left_roi.top);
+  mdp_commit.left_roi.w = INT(left_roi.right - left_roi.left);
+  mdp_commit.left_roi.h = INT(left_roi.bottom - left_roi.top);
+
+  // SDM treats ROI as one full coordinate system.
+  // In case source split is disabled, However, Driver assumes Mixer to operate in
+  // different co-ordinate system.
+  if (!hw_resource_.is_src_split) {
+    mdp_commit.right_roi.x = INT(right_roi.left) - hw_panel_info_.split_info.left_split;
+    mdp_commit.right_roi.y = INT(right_roi.top);
+    mdp_commit.right_roi.w = INT(right_roi.right - right_roi.left);
+    mdp_commit.right_roi.h = INT(right_roi.bottom - right_roi.top);
+  }
+
+  return HWDevice::Validate(hw_layers);
+}
+
+DisplayError HWPrimary::Commit(HWLayers *hw_layers) {
+  return HWDevice::Commit(hw_layers);
+}
+
+DisplayError HWPrimary::Flush() {
+  return HWDevice::Flush();
+}
+
+DisplayError HWPrimary::GetHWPanelInfo(HWPanelInfo *panel_info) {
+  return HWDevice::GetHWPanelInfo(panel_info);
+}
+
+void* HWPrimary::DisplayEventThread(void *context) {
+  if (context) {
+    return reinterpret_cast<HWPrimary *>(context)->DisplayEventThreadHandler();
+  }
+
+  return NULL;
+}
+
+void* HWPrimary::DisplayEventThreadHandler() {
+  char data[kMaxStringLength] = {0};
+
+  prctl(PR_SET_NAME, event_thread_name_, 0, 0, 0);
+  setpriority(PRIO_PROCESS, 0, kThreadPriorityUrgent);
+
+  if (fake_vsync_) {
+    while (!exit_threads_) {
+      // Fake vsync is used only when set explicitly through a property(todo) or when
+      // the vsync timestamp node cannot be opened at bootup. There is no
+      // fallback to fake vsync from the true vsync loop, ever, as the
+      // condition can easily escape detection.
+      // Also, fake vsync is delivered only for the primary display.
+      usleep(16666);
+      STRUCT_VAR(timeval, time_now);
+      gettimeofday(&time_now, NULL);
+      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_->VSync(ts);
+    }
+
+    pthread_exit(0);
+  }
+
+  typedef void (HWPrimary::*EventHandler)(char*);
+  EventHandler event_handler[kNumDisplayEvents] = { &HWPrimary::HandleVSync,
+                                                    &HWPrimary::HandleBlank,
+                                                    &HWPrimary::HandleIdleTimeout,
+                                                    &HWPrimary::HandleThermal };
+
+  while (!exit_threads_) {
+    int error = poll_(poll_fds_, kNumDisplayEvents, -1);
+    if (error < 0) {
+      DLOGW("poll failed. error = %s", strerror(errno));
+      continue;
+    }
+    for (int event = 0; event < kNumDisplayEvents; event++) {
+      pollfd &poll_fd = poll_fds_[event];
+
+      if (poll_fd.revents & POLLPRI) {
+        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.
+          DLOGW("pread failed. event = %d, error = %s", event, strerror(errno));
+          continue;
+        }
+
+        (this->*event_handler[event])(data);
+      }
+    }
+  }
+
+  pthread_exit(0);
+
+  return NULL;
+}
+
+void HWPrimary::HandleVSync(char *data) {
+  int64_t timestamp = 0;
+  if (!strncmp(data, "VSYNC=", strlen("VSYNC="))) {
+    timestamp = strtoull(data + strlen("VSYNC="), NULL, 0);
+  }
+  event_handler_->VSync(timestamp);
+}
+
+void HWPrimary::HandleBlank(char *data) {
+  // TODO(user): Need to send blank Event
+}
+
+void HWPrimary::HandleIdleTimeout(char *data) {
+  event_handler_->IdleTimeout();
+}
+
+void HWPrimary::HandleThermal(char *data) {
+  int64_t thermal_level = 0;
+  if (!strncmp(data, "thermal_level=", strlen("thermal_level="))) {
+    thermal_level = strtoull(data + strlen("thermal_level="), NULL, 0);
+  }
+
+  DLOGI("Received thermal notification with thermal level = %d", thermal_level);
+
+  event_handler_->ThermalEvent(thermal_level);
+}
+
+void HWPrimary::SetIdleTimeoutMs(uint32_t timeout_ms) {
+  char node_path[kMaxStringLength] = {0};
+
+  DLOGI("Setting idle timeout to = %d ms", timeout_ms);
+
+  snprintf(node_path, sizeof(node_path), "%s%d/idle_time", fb_path_, fb_node_index_);
+
+  // Open a sysfs node to send the timeout value to driver.
+  int fd = open_(node_path, O_WRONLY);
+  if (fd < 0) {
+    DLOGE("Unable to open %s, node %s", node_path, strerror(errno));
+    return;
+  }
+
+  char timeout_string[64];
+  snprintf(timeout_string, sizeof(timeout_string), "%d", timeout_ms);
+
+  // Notify driver about the timeout value
+  ssize_t length = pwrite_(fd, timeout_string, strlen(timeout_string), 0);
+  if (length < -1) {
+    DLOGE("Unable to write into %s, node %s", node_path, strerror(errno));
+  }
+
+  close_(fd);
+}
+
+DisplayError HWPrimary::SetVSyncState(bool enable) {
+  DTRACE_SCOPED();
+
+  int vsync_on = enable ? 1 : 0;
+  if (ioctl_(device_fd_, MSMFB_OVERLAY_VSYNC_CTRL, &vsync_on) < 0) {
+    IOCTL_LOGE(MSMFB_OVERLAY_VSYNC_CTRL, device_type_);
+    return kErrorHardware;
+  }
+
+  return kErrorNone;
+}
+
+DisplayError HWPrimary::SetDisplayMode(const HWDisplayMode hw_display_mode) {
+  DisplayError error = kErrorNone;
+  uint32_t mode = -1;
+
+  switch (hw_display_mode) {
+  case kModeVideo:
+    mode = kModeLPMVideo;
+    break;
+  case kModeCommand:
+    mode = kModeLPMCommand;
+    break;
+  default:
+    DLOGW("Failed to translate SDE display mode %d to a MSMFB_LPM_ENABLE mode",
+          hw_display_mode);
+    return kErrorParameters;
+  }
+
+  if (ioctl_(device_fd_, MSMFB_LPM_ENABLE, &mode) < 0) {
+    IOCTL_LOGE(MSMFB_LPM_ENABLE, device_type_);
+    return kErrorHardware;
+  }
+
+  DLOGI("Triggering display mode change to %d on next commit.", hw_display_mode);
+  synchronous_commit_ = true;
+
+  return kErrorNone;
+}
+
+}  // namespace sdm
+
diff --git a/sdm/libs/core/fb/hw_primary.h b/sdm/libs/core/fb/hw_primary.h
new file mode 100644
index 0000000..f7ccef2
--- /dev/null
+++ b/sdm/libs/core/fb/hw_primary.h
@@ -0,0 +1,88 @@
+/*
+* Copyright (c) 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:
+*    * Redistributions of source code must retain the above copyright notice, this list of
+*      conditions and the following disclaimer.
+*    * Redistributions in binary form must reproduce the above copyright notice, this list of
+*      conditions and the following disclaimer in the documentation and/or other materials provided
+*      with the distribution.
+*    * Neither the name of The Linux Foundation nor the names of its contributors may be used to
+*      endorse or promote products derived from this software without specific prior written
+*      permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef __HW_PRIMARY_H__
+#define __HW_PRIMARY_H__
+
+#include "hw_device.h"
+#include "hw_primary_interface.h"
+
+namespace sdm {
+
+class HWPrimary : public HWDevice, public HWPrimaryInterface {
+ public:
+  HWPrimary(BufferSyncHandler *buffer_sync_handler, HWInfoInterface *hw_info_intf);
+  virtual DisplayError Init();
+  virtual DisplayError Deinit();
+  virtual DisplayError Open(HWEventHandler *eventhandler);
+  virtual DisplayError Close();
+  virtual DisplayError GetNumDisplayAttributes(uint32_t *count);
+  virtual DisplayError GetDisplayAttributes(HWDisplayAttributes *display_attributes,
+                                            uint32_t index);
+  virtual DisplayError GetHWPanelInfo(HWPanelInfo *panel_info);
+  virtual DisplayError SetDisplayAttributes(uint32_t index);
+  virtual DisplayError GetConfigIndex(uint32_t mode, uint32_t *index);
+  virtual DisplayError PowerOn();
+  virtual DisplayError PowerOff();
+  virtual DisplayError Doze();
+  virtual DisplayError DozeSuspend();
+  virtual DisplayError Standby();
+  virtual DisplayError Validate(HWLayers *hw_layers);
+  virtual DisplayError Commit(HWLayers *hw_layers);
+  virtual DisplayError Flush();
+  virtual void SetIdleTimeoutMs(uint32_t timeout_ms);
+  virtual DisplayError SetVSyncState(bool enable);
+  virtual DisplayError SetDisplayMode(const HWDisplayMode hw_display_mode);
+  virtual DisplayError SetRefreshRate(uint32_t refresh_rate);
+
+ private:
+  // Panel modes for the MSMFB_LPM_ENABLE ioctl
+  enum {
+    kModeLPMVideo,
+    kModeLPMCommand,
+  };
+
+  // Event Thread to receive vsync/blank events
+  static void* DisplayEventThread(void *context);
+  void* DisplayEventThreadHandler();
+
+  void HandleVSync(char *data);
+  void HandleBlank(char *data);
+  void HandleIdleTimeout(char *data);
+  void HandleThermal(char *data);
+  DisplayError PopulateDisplayAttributes();
+
+  pollfd poll_fds_[kNumDisplayEvents];
+  pthread_t event_thread_;
+  const char *event_thread_name_;
+  bool fake_vsync_;
+  bool exit_threads_;
+  HWDisplayAttributes display_attributes_;
+  bool config_changed_;
+};
+
+}  // namespace sdm
+
+#endif  // __HW_PRIMARY_H__
+
diff --git a/sdm/libs/core/fb/hw_virtual.cpp b/sdm/libs/core/fb/hw_virtual.cpp
new file mode 100644
index 0000000..79c9537
--- /dev/null
+++ b/sdm/libs/core/fb/hw_virtual.cpp
@@ -0,0 +1,139 @@
+/*
+* Copyright (c) 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:
+*     * 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/debug.h>
+#include "hw_virtual.h"
+
+#define __CLASS__ "HWVirtual"
+
+namespace sdm {
+
+DisplayError HWVirtualInterface::Create(HWVirtualInterface **intf, HWInfoInterface *hw_info_intf,
+                                        BufferSyncHandler *buffer_sync_handler) {
+  DisplayError error = kErrorNone;
+  HWVirtual *hw_virtual = NULL;
+
+  hw_virtual = new HWVirtual(buffer_sync_handler, hw_info_intf);
+  error = hw_virtual->Init();
+  if (error != kErrorNone) {
+    delete hw_virtual;
+  } else {
+    *intf = hw_virtual;
+  }
+
+  return error;
+}
+
+DisplayError HWVirtualInterface::Destroy(HWVirtualInterface *intf) {
+  HWVirtual *hw_virtual = static_cast<HWVirtual *>(intf);
+  hw_virtual->Deinit();
+  delete hw_virtual;
+
+  return kErrorNone;
+}
+
+HWVirtual::HWVirtual(BufferSyncHandler *buffer_sync_handler, HWInfoInterface *hw_info_intf)
+  : HWDevice(buffer_sync_handler) {
+  HWDevice::device_type_ = kDeviceVirtual;
+  HWDevice::device_name_ = "Virtual Display Device";
+  HWDevice::hw_info_intf_ = hw_info_intf;
+}
+
+DisplayError HWVirtual::Init() {
+  return HWDevice::Init();
+}
+
+DisplayError HWVirtual::Deinit() {
+  return kErrorNone;
+}
+
+DisplayError HWVirtual::Open(HWEventHandler *eventhandler) {
+  return HWDevice::Open(eventhandler);
+}
+
+DisplayError HWVirtual::Close() {
+  return HWDevice::Close();
+}
+
+DisplayError HWVirtual::GetNumDisplayAttributes(uint32_t *count) {
+  return HWDevice::GetNumDisplayAttributes(count);
+}
+
+DisplayError HWVirtual::GetDisplayAttributes(HWDisplayAttributes *display_attributes,
+                                             uint32_t index) {
+  return HWDevice::GetDisplayAttributes(display_attributes, index);
+}
+
+DisplayError HWVirtual::SetDisplayAttributes(uint32_t index) {
+  return HWDevice::SetDisplayAttributes(index);
+}
+
+DisplayError HWVirtual::GetConfigIndex(uint32_t mode, uint32_t *index) {
+  return HWDevice::GetConfigIndex(mode, index);
+}
+
+DisplayError HWVirtual::PowerOn() {
+  return HWDevice::PowerOn();
+}
+
+DisplayError HWVirtual::PowerOff() {
+  return HWDevice::PowerOff();
+}
+
+DisplayError HWVirtual::Doze() {
+  return HWDevice::Doze();
+}
+
+DisplayError HWVirtual::DozeSuspend() {
+  return HWDevice::DozeSuspend();
+}
+
+DisplayError HWVirtual::Standby() {
+  return HWDevice::Standby();
+}
+
+DisplayError HWVirtual::Validate(HWLayers *hw_layers) {
+  HWDevice::ResetDisplayParams();
+  return HWDevice::Validate(hw_layers);
+}
+
+DisplayError HWVirtual::Commit(HWLayers *hw_layers) {
+  return HWDevice::Commit(hw_layers);
+}
+
+DisplayError HWVirtual::Flush() {
+  return HWDevice::Flush();
+}
+
+DisplayError HWVirtual::GetHWPanelInfo(HWPanelInfo *panel_info) {
+  return HWDevice::GetHWPanelInfo(panel_info);
+}
+
+}  // namespace sdm
+
diff --git a/sdm/libs/core/fb/hw_virtual.h b/sdm/libs/core/fb/hw_virtual.h
new file mode 100644
index 0000000..507de88
--- /dev/null
+++ b/sdm/libs/core/fb/hw_virtual.h
@@ -0,0 +1,59 @@
+/*
+* Copyright (c) 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:
+*    * Redistributions of source code must retain the above copyright notice, this list of
+*      conditions and the following disclaimer.
+*    * Redistributions in binary form must reproduce the above copyright notice, this list of
+*      conditions and the following disclaimer in the documentation and/or other materials provided
+*      with the distribution.
+*    * Neither the name of The Linux Foundation nor the names of its contributors may be used to
+*      endorse or promote products derived from this software without specific prior written
+*      permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef __HW_VIRTUAL_H__
+#define __HW_VIRTUAL_H__
+
+#include "hw_device.h"
+#include "hw_virtual_interface.h"
+
+namespace sdm {
+
+class HWVirtual : public HWDevice, public HWVirtualInterface {
+ public:
+  HWVirtual(BufferSyncHandler *buffer_sync_handler, HWInfoInterface *hw_info_intf);
+  virtual DisplayError Init();
+  virtual DisplayError Deinit();
+  virtual DisplayError Open(HWEventHandler *eventhandler);
+  virtual DisplayError Close();
+  virtual DisplayError GetNumDisplayAttributes(uint32_t *count);
+  virtual DisplayError GetDisplayAttributes(HWDisplayAttributes *display_attributes,
+                                            uint32_t index);
+  virtual DisplayError GetHWPanelInfo(HWPanelInfo *panel_info);
+  virtual DisplayError SetDisplayAttributes(uint32_t index);
+  virtual DisplayError GetConfigIndex(uint32_t mode, uint32_t *index);
+  virtual DisplayError PowerOn();
+  virtual DisplayError PowerOff();
+  virtual DisplayError Doze();
+  virtual DisplayError DozeSuspend();
+  virtual DisplayError Standby();
+  virtual DisplayError Validate(HWLayers *hw_layers);
+  virtual DisplayError Commit(HWLayers *hw_layers);
+  virtual DisplayError Flush();
+};
+
+}  // namespace sdm
+
+#endif  // __HW_VIRTUAL_H__
+
diff --git a/sdm/libs/core/hw_hdmi_interface.h b/sdm/libs/core/hw_hdmi_interface.h
new file mode 100644
index 0000000..0d3d800
--- /dev/null
+++ b/sdm/libs/core/hw_hdmi_interface.h
@@ -0,0 +1,50 @@
+/*
+* Copyright (c) 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:
+*    * Redistributions of source code must retain the above copyright notice, this list of
+*      conditions and the following disclaimer.
+*    * Redistributions in binary form must reproduce the above copyright notice, this list of
+*      conditions and the following disclaimer in the documentation and/or other materials provided
+*      with the distribution.
+*    * Neither the name of The Linux Foundation nor the names of its contributors may be used to
+*      endorse or promote products derived from this software without specific prior written
+*      permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef __HW_HDMI_INTERFACE_H__
+#define __HW_HDMI_INTERFACE_H__
+
+#include "hw_interface.h"
+
+namespace sdm {
+
+class HWInfoInterface;
+
+class HWHDMIInterface: virtual public HWInterface {
+ public:
+  static DisplayError Create(HWHDMIInterface **intf, HWInfoInterface *hw_info_intf,
+                             BufferSyncHandler *buffer_sync_handler);
+  static DisplayError Destroy(HWHDMIInterface *intf);
+  virtual DisplayError GetHWScanInfo(HWScanInfo *scan_info) = 0;
+  virtual DisplayError GetVideoFormat(uint32_t config_index, uint32_t *video_format) = 0;
+  virtual DisplayError GetMaxCEAFormat(uint32_t *max_cea_format) = 0;
+
+ protected:
+  virtual ~HWHDMIInterface() { }
+};
+
+}  // namespace sdm
+
+#endif  // __HW_HDMI_INTERFACE_H__
+
diff --git a/sdm/libs/core/hw_info_interface.h b/sdm/libs/core/hw_info_interface.h
new file mode 100644
index 0000000..014ab0d
--- /dev/null
+++ b/sdm/libs/core/hw_info_interface.h
@@ -0,0 +1,46 @@
+/*
+* 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:
+*    * Redistributions of source code must retain the above copyright notice, this list of
+*      conditions and the following disclaimer.
+*    * Redistributions in binary form must reproduce the above copyright notice, this list of
+*      conditions and the following disclaimer in the documentation and/or other materials provided
+*      with the distribution.
+*    * Neither the name of The Linux Foundation nor the names of its contributors may be used to
+*      endorse or promote products derived from this software without specific prior written
+*      permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef __HW_INFO_INTERFACE_H__
+#define __HW_INFO_INTERFACE_H__
+
+#include <inttypes.h>
+#include <private/hw_info_types.h>
+
+namespace sdm {
+
+class HWInfoInterface {
+ public:
+  static DisplayError Create(HWInfoInterface **intf);
+  static DisplayError Destroy(HWInfoInterface *intf);
+  virtual DisplayError GetHWResourceInfo(HWResourceInfo *hw_resource) = 0;
+
+ protected:
+  virtual ~HWInfoInterface() { }
+};
+
+}  // namespace sdm
+
+#endif  // __HW_INFO_INTERFACE_H__
+
diff --git a/sdm/libs/core/hw_interface.h b/sdm/libs/core/hw_interface.h
new file mode 100644
index 0000000..317e087
--- /dev/null
+++ b/sdm/libs/core/hw_interface.h
@@ -0,0 +1,90 @@
+/*
+* 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:
+*    * Redistributions of source code must retain the above copyright notice, this list of
+*      conditions and the following disclaimer.
+*    * Redistributions in binary form must reproduce the above copyright notice, this list of
+*      conditions and the following disclaimer in the documentation and/or other materials provided
+*      with the distribution.
+*    * Neither the name of The Linux Foundation nor the names of its contributors may be used to
+*      endorse or promote products derived from this software without specific prior written
+*      permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef __HW_INTERFACE_H__
+#define __HW_INTERFACE_H__
+
+#include <core/display_interface.h>
+#include <private/strategy_interface.h>
+#include <private/hw_info_types.h>
+#include <utils/constants.h>
+#include <core/buffer_allocator.h>
+#include <core/buffer_sync_handler.h>
+
+namespace sdm {
+
+enum HWScanSupport {
+  kScanNotSupported,
+  kScanAlwaysOverscanned,
+  kScanAlwaysUnderscanned,
+  kScanBoth,
+};
+
+struct HWScanInfo {
+  HWScanSupport pt_scan_support;    // Scan support for preferred timing
+  HWScanSupport it_scan_support;    // Scan support for digital monitor or industry timings
+  HWScanSupport cea_scan_support;   // Scan support for CEA resolution timings
+
+  HWScanInfo() : pt_scan_support(kScanNotSupported), it_scan_support(kScanNotSupported),
+                 cea_scan_support(kScanNotSupported) { }
+};
+
+// HWEventHandler - Implemented in DisplayBase and HWInterface implementation
+class HWEventHandler {
+ public:
+  virtual DisplayError VSync(int64_t timestamp) = 0;
+  virtual DisplayError Blank(bool blank) = 0;
+  virtual void IdleTimeout() = 0;
+  virtual void ThermalEvent(int64_t thermal_level) = 0;
+ protected:
+  virtual ~HWEventHandler() { }
+};
+
+class HWInterface {
+ public:
+  virtual DisplayError Open(HWEventHandler *eventhandler) = 0;
+  virtual DisplayError Close() = 0;
+  virtual DisplayError GetNumDisplayAttributes(uint32_t *count) = 0;
+  virtual DisplayError GetDisplayAttributes(HWDisplayAttributes *display_attributes,
+                                            uint32_t index) = 0;
+  virtual DisplayError GetHWPanelInfo(HWPanelInfo *panel_info) = 0;
+  virtual DisplayError SetDisplayAttributes(uint32_t index) = 0;
+  virtual DisplayError GetConfigIndex(uint32_t mode, uint32_t *index) = 0;
+  virtual DisplayError PowerOn() = 0;
+  virtual DisplayError PowerOff() = 0;
+  virtual DisplayError Doze() = 0;
+  virtual DisplayError DozeSuspend() = 0;
+  virtual DisplayError Standby() = 0;
+  virtual DisplayError Validate(HWLayers *hw_layers) = 0;
+  virtual DisplayError Commit(HWLayers *hw_layers) = 0;
+  virtual DisplayError Flush() = 0;
+
+ protected:
+  virtual ~HWInterface() { }
+};
+
+}  // namespace sdm
+
+#endif  // __HW_INTERFACE_H__
+
diff --git a/sdm/libs/core/hw_primary_interface.h b/sdm/libs/core/hw_primary_interface.h
new file mode 100644
index 0000000..9faa6e5
--- /dev/null
+++ b/sdm/libs/core/hw_primary_interface.h
@@ -0,0 +1,50 @@
+/*
+* Copyright (c) 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:
+*    * Redistributions of source code must retain the above copyright notice, this list of
+*      conditions and the following disclaimer.
+*    * Redistributions in binary form must reproduce the above copyright notice, this list of
+*      conditions and the following disclaimer in the documentation and/or other materials provided
+*      with the distribution.
+*    * Neither the name of The Linux Foundation nor the names of its contributors may be used to
+*      endorse or promote products derived from this software without specific prior written
+*      permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef __HW_PRIMARY_INTERFACE_H__
+#define __HW_PRIMARY_INTERFACE_H__
+
+namespace sdm {
+
+class BufferSyncHandler;
+class HWInfoInterface;
+
+class HWPrimaryInterface: virtual public HWInterface {
+ public:
+  static DisplayError Create(HWPrimaryInterface **intf, HWInfoInterface *hw_info_intf,
+                             BufferSyncHandler *buffer_sync_handler);
+  static DisplayError Destroy(HWPrimaryInterface *intf);
+  virtual DisplayError SetVSyncState(bool enable) = 0;
+  virtual void SetIdleTimeoutMs(uint32_t timeout_ms) = 0;
+  virtual DisplayError SetDisplayMode(const HWDisplayMode hw_display_mode) = 0;
+  virtual DisplayError SetRefreshRate(uint32_t refresh_rate) = 0;
+
+ protected:
+  virtual ~HWPrimaryInterface() { }
+};
+
+}  // namespace sdm
+
+#endif  // __HW_PRIMARY_INTERFACE_H__
+
diff --git a/sdm/libs/core/hw_virtual_interface.h b/sdm/libs/core/hw_virtual_interface.h
new file mode 100644
index 0000000..ba14ae6
--- /dev/null
+++ b/sdm/libs/core/hw_virtual_interface.h
@@ -0,0 +1,47 @@
+/*
+* Copyright (c) 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:
+*    * Redistributions of source code must retain the above copyright notice, this list of
+*      conditions and the following disclaimer.
+*    * Redistributions in binary form must reproduce the above copyright notice, this list of
+*      conditions and the following disclaimer in the documentation and/or other materials provided
+*      with the distribution.
+*    * Neither the name of The Linux Foundation nor the names of its contributors may be used to
+*      endorse or promote products derived from this software without specific prior written
+*      permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef __HW_VIRTUAL_INTERFACE_H__
+#define __HW_VIRTUAL_INTERFACE_H__
+
+#include "hw_interface.h"
+
+namespace sdm {
+
+class HWInfoInterface;
+
+class HWVirtualInterface: virtual public HWInterface {
+ public:
+  static DisplayError Create(HWVirtualInterface **intf, HWInfoInterface *hw_info_intf,
+                             BufferSyncHandler *buffer_sync_handler);
+  static DisplayError Destroy(HWVirtualInterface *intf);
+
+ protected:
+  virtual ~HWVirtualInterface() { }
+};
+
+}  // namespace sdm
+
+#endif  // __HW_VIRTUAL_INTERFACE_H__
+
diff --git a/sdm/libs/core/resource_default.cpp b/sdm/libs/core/resource_default.cpp
new file mode 100644
index 0000000..783b621
--- /dev/null
+++ b/sdm/libs/core/resource_default.cpp
@@ -0,0 +1,912 @@
+/*
+* 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:
+*    * 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 <math.h>
+#include <utils/constants.h>
+#include <utils/debug.h>
+#include <utils/rect.h>
+#include <dlfcn.h>
+
+#include "resource_default.h"
+
+#define __CLASS__ "ResourceDefault"
+
+namespace sdm {
+
+ResourceDefault::ResourceDefault()
+  : num_pipe_(0), vig_pipes_(NULL), rgb_pipes_(NULL), dma_pipes_(NULL) {
+}
+
+DisplayError ResourceDefault::Init(const HWResourceInfo &hw_res_info) {
+  DisplayError error = kErrorNone;
+  uint32_t num_pipe = 0;
+
+  num_pipe = hw_res_info.num_vig_pipe + hw_res_info.num_rgb_pipe + hw_res_info.num_dma_pipe;
+
+  if (num_pipe > kPipeIdMax) {
+    DLOGE("Number of pipe is over the limit! %d", num_pipe);
+    return kErrorParameters;
+  }
+
+  num_pipe_ = num_pipe;
+  hw_res_info_ = hw_res_info;
+  // Init pipe info
+  vig_pipes_ = &src_pipes_[0];
+  rgb_pipes_ = &src_pipes_[hw_res_info_.num_vig_pipe];
+  dma_pipes_ = &src_pipes_[hw_res_info_.num_vig_pipe + hw_res_info_.num_rgb_pipe];
+
+  for (uint32_t i = 0; i < hw_res_info_.num_vig_pipe; i++) {
+    vig_pipes_[i].type = kPipeTypeVIG;
+    vig_pipes_[i].index = i;
+    vig_pipes_[i].mdss_pipe_id = GetMdssPipeId(vig_pipes_[i].type, i);
+  }
+
+  for (uint32_t i = 0; i < hw_res_info_.num_rgb_pipe; i++) {
+    rgb_pipes_[i].type = kPipeTypeRGB;
+    rgb_pipes_[i].index = i + hw_res_info_.num_vig_pipe;
+    rgb_pipes_[i].mdss_pipe_id = GetMdssPipeId(rgb_pipes_[i].type, i);
+  }
+
+  for (uint32_t i = 0; i < hw_res_info_.num_dma_pipe; i++) {
+    dma_pipes_[i].type = kPipeTypeDMA;
+    dma_pipes_[i].index = i + hw_res_info_.num_vig_pipe + hw_res_info_.num_rgb_pipe;
+    dma_pipes_[i].mdss_pipe_id = GetMdssPipeId(dma_pipes_[i].type, i);
+  }
+
+  for (uint32_t i = 0; i < num_pipe_; i++) {
+    src_pipes_[i].priority = i;
+  }
+
+  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_.max_scale_down < 1 || hw_res_info_.max_scale_up < 1) {
+    DLOGE("Max scaling setting is invalid! max_scale_down = %d, max_scale_up = %d",
+          hw_res_info_.max_scale_down, hw_res_info_.max_scale_up);
+    hw_res_info_.max_scale_down = 1;
+    hw_res_info_.max_scale_up = 1;
+  }
+
+  rgb_pipes_[0].owner = kPipeOwnerKernelMode;
+  rgb_pipes_[1].owner = kPipeOwnerKernelMode;
+
+  return error;
+}
+
+DisplayError ResourceDefault::Deinit() {
+  return kErrorNone;
+}
+
+DisplayError ResourceDefault::RegisterDisplay(DisplayType type,
+                                              const HWDisplayAttributes &attributes,
+                                              const HWPanelInfo &hw_panel_info,
+                                              Handle *display_ctx) {
+  DisplayError error = kErrorNone;
+
+  HWBlockType hw_block_id = kHWBlockMax;
+  switch (type) {
+  case kPrimary:
+    if (!hw_block_ctx_[kHWPrimary].is_in_use) {
+      hw_block_id = kHWPrimary;
+    }
+    break;
+
+  case kHDMI:
+    if (!hw_block_ctx_[kHWHDMI].is_in_use) {
+      hw_block_id = kHWHDMI;
+    }
+    break;
+
+  default:
+    DLOGW("RegisterDisplay, invalid type %d", type);
+    return kErrorParameters;
+  }
+
+  if (hw_block_id == kHWBlockMax) {
+    return kErrorResources;
+  }
+
+  DisplayResourceContext *display_resource_ctx = new DisplayResourceContext();
+  if (!display_resource_ctx) {
+    return kErrorMemory;
+  }
+
+  hw_block_ctx_[hw_block_id].is_in_use = true;
+
+  display_resource_ctx->display_attributes = attributes;
+  display_resource_ctx->hw_block_id = hw_block_id;
+
+  if (!display_resource_ctx->display_attributes.is_device_split) {
+    display_resource_ctx->display_attributes.split_left = attributes.x_pixels;
+  }
+
+  *display_ctx = display_resource_ctx;
+  return error;
+}
+
+DisplayError ResourceDefault::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;
+
+  delete display_resource_ctx;
+
+  return kErrorNone;
+}
+
+void ResourceDefault::ReconfigureDisplay(Handle display_ctx, const HWDisplayAttributes &attributes,
+                                    const HWPanelInfo &hw_panel_info) {
+  SCOPE_LOCK(locker_);
+
+  DisplayResourceContext *display_resource_ctx =
+                          reinterpret_cast<DisplayResourceContext *>(display_ctx);
+
+  display_resource_ctx->display_attributes = attributes;
+}
+
+DisplayError ResourceDefault::Start(Handle display_ctx) {
+  locker_.Lock();
+
+  return kErrorNone;
+}
+
+DisplayError ResourceDefault::Stop(Handle display_ctx) {
+  locker_.Unlock();
+
+  return kErrorNone;
+}
+
+DisplayError ResourceDefault::Acquire(Handle display_ctx, HWLayers *hw_layers) {
+  DisplayResourceContext *display_resource_ctx =
+                          reinterpret_cast<DisplayResourceContext *>(display_ctx);
+
+  DisplayError error = kErrorNone;
+  const struct HWLayersInfo &layer_info = hw_layers->info;
+  HWBlockType hw_block_id = display_resource_ctx->hw_block_id;
+
+  DLOGV_IF(kTagResources, "==== Resource reserving start: hw_block = %d ====", hw_block_id);
+
+  if (layer_info.count > 1) {
+    DLOGV_IF(kTagResources, "More than one FB layers");
+    return kErrorResources;
+  }
+
+  Layer &layer = layer_info.stack->layers[layer_info.index[0]];
+
+  if (layer.composition != kCompositionGPUTarget) {
+    DLOGV_IF(kTagResources, "Not an FB layer");
+    return kErrorParameters;
+  }
+
+  error = Config(display_resource_ctx, hw_layers);
+  if (error != kErrorNone) {
+    DLOGV_IF(kTagResources, "Resource config failed");
+    return error;
+  }
+
+  for (uint32_t i = 0; i < num_pipe_; i++) {
+    if (src_pipes_[i].hw_block_id == hw_block_id && src_pipes_[i].owner == kPipeOwnerUserMode) {
+      src_pipes_[i].ResetState();
+    }
+  }
+
+  uint32_t left_index = kPipeIdMax;
+  uint32_t right_index = kPipeIdMax;
+  bool need_scale = false;
+
+  struct HWLayerConfig &layer_config = hw_layers->config[0];
+
+  HWPipeInfo *left_pipe = &layer_config.left_pipe;
+  HWPipeInfo *right_pipe = &layer_config.right_pipe;
+
+  // left pipe is needed
+  if (left_pipe->valid) {
+    need_scale = IsScalingNeeded(left_pipe);
+    left_index = GetPipe(hw_block_id, need_scale);
+    if (left_index >= num_pipe_) {
+      DLOGV_IF(kTagResources, "Get left pipe failed: hw_block_id = %d, need_scale = %d",
+               hw_block_id, need_scale);
+      ResourceStateLog();
+      goto CleanupOnError;
+    }
+  }
+
+  error = SetDecimationFactor(left_pipe);
+  if (error != kErrorNone) {
+    goto CleanupOnError;
+  }
+
+  if (!right_pipe->valid) {
+    // assign single pipe
+    if (left_index < num_pipe_) {
+      left_pipe->pipe_id = src_pipes_[left_index].mdss_pipe_id;
+    }
+    DLOGV_IF(kTagResources, "1 pipe acquired for FB layer, left_pipe = %x", left_pipe->pipe_id);
+    return kErrorNone;
+  }
+
+  need_scale = IsScalingNeeded(right_pipe);
+
+  right_index = GetPipe(hw_block_id, need_scale);
+  if (right_index >= num_pipe_) {
+    DLOGV_IF(kTagResources, "Get right pipe failed: hw_block_id = %d, need_scale = %d", hw_block_id,
+             need_scale);
+    ResourceStateLog();
+    goto CleanupOnError;
+  }
+
+  if (src_pipes_[right_index].priority < src_pipes_[left_index].priority) {
+    // Swap pipe based on priority
+    Swap(left_index, right_index);
+  }
+
+  // assign dual pipes
+  left_pipe->pipe_id = src_pipes_[left_index].mdss_pipe_id;
+  right_pipe->pipe_id = src_pipes_[right_index].mdss_pipe_id;
+
+  error = SetDecimationFactor(right_pipe);
+  if (error != kErrorNone) {
+    goto CleanupOnError;
+  }
+
+  DLOGV_IF(kTagResources, "2 pipes acquired for FB layer, left_pipe = %x, right_pipe = %x",
+           left_pipe->pipe_id,  right_pipe->pipe_id);
+
+  return kErrorNone;
+
+CleanupOnError:
+  DLOGV_IF(kTagResources, "Resource reserving failed! hw_block = %d", hw_block_id);
+
+  return kErrorResources;
+}
+
+DisplayError ResourceDefault::PostPrepare(Handle display_ctx, HWLayers *hw_layers) {
+  SCOPE_LOCK(locker_);
+
+  return kErrorNone;
+}
+
+DisplayError ResourceDefault::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;
+  DisplayError error = kErrorNone;
+
+  DLOGV_IF(kTagResources, "Resource for hw_block = %d, frame_count = %d", hw_block_id, frame_count);
+
+  // handoff pipes which are used by splash screen
+  if ((frame_count == 0) && (hw_block_id == kHWPrimary)) {
+    for (uint32_t i = 0; i < num_pipe_; i++) {
+      if (src_pipes_[i].hw_block_id == hw_block_id && src_pipes_[i].owner == kPipeOwnerKernelMode) {
+        src_pipes_[i].owner = kPipeOwnerUserMode;
+      }
+    }
+  }
+
+  display_resource_ctx->frame_count++;
+
+  return kErrorNone;
+}
+
+void ResourceDefault::Purge(Handle display_ctx) {
+  SCOPE_LOCK(locker_);
+
+  DisplayResourceContext *display_resource_ctx =
+                          reinterpret_cast<DisplayResourceContext *>(display_ctx);
+  HWBlockType hw_block_id = display_resource_ctx->hw_block_id;
+
+  for (uint32_t i = 0; i < num_pipe_; i++) {
+    if (src_pipes_[i].hw_block_id == hw_block_id && src_pipes_[i].owner == kPipeOwnerUserMode) {
+      src_pipes_[i].ResetState();
+    }
+  }
+  DLOGV_IF(kTagResources, "display id = %d", display_resource_ctx->hw_block_id);
+}
+
+DisplayError ResourceDefault::SetMaxMixerStages(Handle display_ctx, uint32_t max_mixer_stages) {
+  SCOPE_LOCK(locker_);
+
+  return kErrorNone;
+}
+
+uint32_t ResourceDefault::GetMdssPipeId(PipeType type, uint32_t index) {
+  uint32_t mdss_id = kPipeIdMax;
+  switch (type) {
+  case kPipeTypeVIG:
+    if (index < 3) {
+      mdss_id = kPipeIdVIG0 + index;
+    } else if (index == 3) {
+      mdss_id = kPipeIdVIG3;
+    } else {
+      DLOGE("vig pipe index is over the limit! %d", index);
+    }
+    break;
+  case kPipeTypeRGB:
+    if (index < 3) {
+      mdss_id = kPipeIdRGB0 + index;
+    } else if (index == 3) {
+      mdss_id = kPipeIdRGB3;
+    } else {
+      DLOGE("rgb pipe index is over the limit! %d", index);
+    }
+    break;
+  case kPipeTypeDMA:
+    if (index < 2) {
+      mdss_id = kPipeIdDMA0 + index;
+    } else {
+      DLOGE("dma pipe index is over the limit! %d", index);
+    }
+    break;
+  default:
+    DLOGE("wrong pipe type! %d", type);
+    break;
+  }
+
+  return (1 << mdss_id);
+}
+
+uint32_t ResourceDefault::SearchPipe(HWBlockType hw_block_id, SourcePipe *src_pipes,
+                                uint32_t num_pipe) {
+  uint32_t index = kPipeIdMax;
+  SourcePipe *src_pipe;
+
+  // search the pipe being used
+  for (uint32_t i = 0; i < num_pipe; i++) {
+    src_pipe = &src_pipes[i];
+    if (src_pipe->owner == kPipeOwnerUserMode && src_pipe->hw_block_id == kHWBlockMax) {
+      index = src_pipe->index;
+      src_pipe->hw_block_id = hw_block_id;
+      break;
+    }
+  }
+
+  return index;
+}
+
+uint32_t ResourceDefault::NextPipe(PipeType type, HWBlockType hw_block_id) {
+  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);
+}
+
+uint32_t ResourceDefault::GetPipe(HWBlockType hw_block_id, bool need_scale) {
+  uint32_t index = kPipeIdMax;
+
+  // The default behavior is to assume RGB and VG pipes have scalars
+  if (!need_scale) {
+    index = NextPipe(kPipeTypeDMA, hw_block_id);
+  }
+
+  if ((index >= num_pipe_) && (!need_scale || !hw_res_info_.has_non_scalar_rgb)) {
+    index = NextPipe(kPipeTypeRGB, hw_block_id);
+  }
+
+  if (index >= num_pipe_) {
+    index = NextPipe(kPipeTypeVIG, hw_block_id);
+  }
+
+  return index;
+}
+
+bool ResourceDefault::IsScalingNeeded(const HWPipeInfo *pipe_info) {
+  const LayerRect &src_roi = pipe_info->src_roi;
+  const LayerRect &dst_roi = pipe_info->dst_roi;
+
+  return ((dst_roi.right - dst_roi.left) != (src_roi.right - src_roi.left)) ||
+          ((dst_roi.bottom - dst_roi.top) != (src_roi.bottom - src_roi.top));
+}
+
+void ResourceDefault::ResourceStateLog() {
+  DLOGV_IF(kTagResources, "==== resource manager pipe state ====");
+  uint32_t i;
+  for (i = 0; i < num_pipe_; i++) {
+    SourcePipe *src_pipe = &src_pipes_[i];
+    DLOGV_IF(kTagResources, "index = %d, id = %x, hw_block = %d, owner = %s",
+                 src_pipe->index, src_pipe->mdss_pipe_id, src_pipe->hw_block_id,
+                 (src_pipe->owner == kPipeOwnerUserMode) ? "user mode" : "kernel mode");
+  }
+}
+
+DisplayError ResourceDefault::SrcSplitConfig(DisplayResourceContext *display_resource_ctx,
+                                        const LayerRect &src_rect, const LayerRect &dst_rect,
+                                        HWLayerConfig *layer_config) {
+  HWDisplayAttributes &display_attributes = display_resource_ctx->display_attributes;
+  HWPipeInfo *left_pipe = &layer_config->left_pipe;
+  HWPipeInfo *right_pipe = &layer_config->right_pipe;
+  float src_width = src_rect.right - src_rect.left;
+  float dst_width = dst_rect.right - dst_rect.left;
+  float src_height = src_rect.bottom - src_rect.top;
+  float dst_height = dst_rect.bottom - dst_rect.top;
+  float left_mixer_width = FLOAT(display_attributes.split_left);
+
+  // Layer cannot qualify for SrcSplit if source or destination width exceeds max pipe width.
+  // For perf/power optimization, even if "always_src_split" is enabled, use 2 pipes only if:
+  // Source width is greater than split_left (left_mixer_width)
+  if ((src_width > hw_res_info_.max_pipe_width) || (dst_width > hw_res_info_.max_pipe_width) ||
+      (display_resource_ctx->display_attributes.always_src_split && src_width > left_mixer_width)) {
+    SplitRect(src_rect, dst_rect, &left_pipe->src_roi, &left_pipe->dst_roi, &right_pipe->src_roi,
+              &right_pipe->dst_roi);
+    left_pipe->valid = true;
+    right_pipe->valid = true;
+  } else {
+    left_pipe->src_roi = src_rect;
+    left_pipe->dst_roi = dst_rect;
+    left_pipe->valid = true;
+    right_pipe->Reset();
+  }
+
+  return kErrorNone;
+}
+
+DisplayError ResourceDefault::DisplaySplitConfig(DisplayResourceContext *display_resource_ctx,
+                                            const LayerRect &src_rect, const LayerRect &dst_rect,
+                                            HWLayerConfig *layer_config) {
+  HWDisplayAttributes &display_attributes = display_resource_ctx->display_attributes;
+
+  // for display split case
+  HWPipeInfo *left_pipe = &layer_config->left_pipe;
+  HWPipeInfo *right_pipe = &layer_config->right_pipe;
+  LayerRect scissor_left, scissor_right, dst_left, crop_left, crop_right, dst_right;
+
+  scissor_left.right = FLOAT(display_attributes.split_left);
+  scissor_left.bottom = FLOAT(display_attributes.y_pixels);
+
+  scissor_right.left = FLOAT(display_attributes.split_left);
+  scissor_right.top = 0.0f;
+  scissor_right.right = FLOAT(display_attributes.x_pixels);
+  scissor_right.bottom = FLOAT(display_attributes.y_pixels);
+
+  crop_left = src_rect;
+  dst_left = dst_rect;
+  crop_right = crop_left;
+  dst_right = dst_left;
+
+  bool crop_left_valid = CalculateCropRects(scissor_left, &crop_left, &dst_left);
+  bool crop_right_valid = false;
+
+  if (IsValid(scissor_right)) {
+    crop_right_valid = CalculateCropRects(scissor_right, &crop_right, &dst_right);
+  }
+
+  // Reset left_pipe and right_pipe to invalid by default
+  left_pipe->Reset();
+  right_pipe->Reset();
+
+  if (crop_left_valid) {
+    // assign left pipe
+    left_pipe->src_roi = crop_left;
+    left_pipe->dst_roi = dst_left;
+    left_pipe->valid = true;
+  }
+
+  // assign right pipe if needed
+  if (crop_right_valid) {
+    right_pipe->src_roi = crop_right;
+    right_pipe->dst_roi = dst_right;
+    right_pipe->valid = true;
+  }
+
+  return kErrorNone;
+}
+
+DisplayError ResourceDefault::Config(DisplayResourceContext *display_resource_ctx,
+                                HWLayers *hw_layers) {
+  HWDisplayAttributes &display_attributes = display_resource_ctx->display_attributes;
+  HWLayersInfo &layer_info = hw_layers->info;
+  DisplayError error = kErrorNone;
+  uint32_t z_order = 0;
+
+  Layer& layer = layer_info.stack->layers[layer_info.index[0]];
+
+  error = ValidateLayerDimensions(layer);
+  if (error != kErrorNone) {
+    return error;
+  }
+
+  struct HWLayerConfig *layer_config = &hw_layers->config[0];
+  HWPipeInfo &left_pipe = layer_config->left_pipe;
+  HWPipeInfo &right_pipe = layer_config->right_pipe;
+
+  LayerRect src_rect = layer.src_rect;
+  LayerRect dst_rect = layer.dst_rect;
+
+  error = ValidateDimensions(src_rect, dst_rect);
+  if (error != kErrorNone) {
+    return error;
+  }
+
+  error = ValidateScaling(src_rect, dst_rect, false);
+  if (error != kErrorNone) {
+    return error;
+  }
+
+  if (hw_res_info_.is_src_split) {
+    error = SrcSplitConfig(display_resource_ctx, src_rect, dst_rect, layer_config);
+  } else {
+    error = DisplaySplitConfig(display_resource_ctx, src_rect, dst_rect, layer_config);
+  }
+
+  if (error != kErrorNone) {
+    return error;
+  }
+
+  error = AlignPipeConfig(layer, &left_pipe, &right_pipe);
+  if (error != kErrorNone) {
+    return error;
+  }
+
+  // set z_order, left_pipe should always be valid
+  left_pipe.z_order = 0;
+
+  DLOGV_IF(kTagResources, "==== FB layer Config ====");
+  Log(kTagResources, "input layer src_rect", layer.src_rect);
+  Log(kTagResources, "input layer dst_rect", layer.dst_rect);
+  Log(kTagResources, "cropped src_rect", src_rect);
+  Log(kTagResources, "cropped dst_rect", dst_rect);
+  Log(kTagResources, "left pipe src", layer_config->left_pipe.src_roi);
+  Log(kTagResources, "left pipe dst", layer_config->left_pipe.dst_roi);
+  if (right_pipe.valid) {
+    right_pipe.z_order = 0;
+    Log(kTagResources, "right pipe src", layer_config->right_pipe.src_roi);
+    Log(kTagResources, "right pipe dst", layer_config->right_pipe.dst_roi);
+  }
+
+  return error;
+}
+
+bool ResourceDefault::CalculateCropRects(const LayerRect &scissor, 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_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_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;
+  bool need_cut = false;
+
+  if (dst_left < sci_left) {
+    left_cut_ratio = (sci_left - dst_left) / dst_width;
+    dst_left = sci_left;
+    need_cut = true;
+  }
+
+  if (dst_right > sci_right) {
+    right_cut_ratio = (dst_right - sci_right) / dst_width;
+    dst_right = sci_right;
+    need_cut = true;
+  }
+
+  if (dst_top < sci_top) {
+    top_cut_ratio = (sci_top - dst_top) / (dst_height);
+    dst_top = sci_top;
+    need_cut = true;
+  }
+
+  if (dst_bottom > sci_bottom) {
+    bottom_cut_ratio = (dst_bottom - sci_bottom) / (dst_height);
+    dst_bottom = sci_bottom;
+    need_cut = true;
+  }
+
+  if (!need_cut)
+    return true;
+
+  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;
+  Normalize(1, 1, crop);
+  Normalize(1, 1, dst);
+  if (IsValid(*crop) && IsValid(*dst))
+    return true;
+  else
+    return false;
+}
+
+DisplayError ResourceDefault::ValidateLayerDimensions(const Layer &layer) {
+  const LayerRect &src = layer.src_rect;
+  const LayerRect &dst = layer.dst_rect;
+  LayerBuffer *input_buffer = layer.input_buffer;
+
+  if (!IsValid(src) || !IsValid(dst)) {
+    Log(kTagResources, "input layer src_rect", src);
+    Log(kTagResources, "input layer dst_rect", dst);
+    return kErrorNotSupported;
+  }
+
+  // Make sure source in integral only if it is a non secure layer.
+  if (!input_buffer->flags.secure && (src.left - roundf(src.left) || src.top - roundf(src.top) ||
+      src.right - roundf(src.right) || src.bottom - roundf(src.bottom))) {
+    DLOGV_IF(kTagResources, "Input ROI is not integral");
+    return kErrorNotSupported;
+  }
+
+  return kErrorNone;
+}
+
+DisplayError ResourceDefault::ValidateDimensions(const LayerRect &crop, const LayerRect &dst) {
+  if (!IsValid(crop)) {
+    Log(kTagResources, "Invalid crop rect", crop);
+    return kErrorNotSupported;
+  }
+
+  if (!IsValid(dst)) {
+    Log(kTagResources, "Invalid dst rect", dst);
+    return kErrorNotSupported;
+  }
+
+  float crop_width = crop.right - crop.left;
+  float crop_height = crop.bottom - crop.top;
+  float dst_width = dst.right - dst.left;
+  float dst_height = dst.bottom - dst.top;
+
+  if ((UINT32(crop_width - dst_width) == 1) || (UINT32(crop_height - dst_height) == 1)) {
+    DLOGV_IF(kTagResources, "One pixel downscaling detected crop_w = %.0f, dst_w = %.0f, " \
+             "crop_h = %.0f, dst_h = %.0f", crop_width, dst_width, crop_height, dst_height);
+    return kErrorNotSupported;
+  }
+
+  return kErrorNone;
+}
+
+DisplayError ResourceDefault::ValidatePipeParams(HWPipeInfo *pipe_info) {
+  DisplayError error = kErrorNone;
+
+  const LayerRect &src_rect = pipe_info->src_roi;
+  const LayerRect &dst_rect = pipe_info->dst_roi;
+
+  error = ValidateDimensions(src_rect, dst_rect);
+  if (error != kErrorNone) {
+    return error;
+  }
+
+  error = ValidateScaling(src_rect, dst_rect, false);
+  if (error != kErrorNone) {
+    return error;
+  }
+
+  return kErrorNone;
+}
+
+DisplayError ResourceDefault::ValidateScaling(const LayerRect &crop, const LayerRect &dst,
+                                         bool rotate90) {
+  DisplayError error = kErrorNone;
+
+  float scale_x = 1.0f;
+  float scale_y = 1.0f;
+
+  error = GetScaleFactor(crop, dst, &scale_x, &scale_y);
+  if (error != kErrorNone) {
+    return error;
+  }
+
+  error = ValidateDownScaling(scale_x, scale_y);
+  if (error != kErrorNone) {
+    return error;
+  }
+
+  error = ValidateUpScaling(scale_x, scale_y);
+  if (error != kErrorNone) {
+    return error;
+  }
+
+  return kErrorNone;
+}
+
+DisplayError ResourceDefault::ValidateDownScaling(float scale_x, float scale_y) {
+  if ((UINT32(scale_x) > 1) || (UINT32(scale_y) > 1)) {
+    float max_scale_down = FLOAT(hw_res_info_.max_scale_down);
+
+    if (hw_res_info_.has_decimation) {
+      max_scale_down *= FLOAT(kMaxDecimationDownScaleRatio);
+    }
+
+    if (scale_x > max_scale_down || scale_y > max_scale_down) {
+      DLOGV_IF(kTagResources,
+               "Scaling down is over the limit: scale_x = %.0f, scale_y = %.0f, " \
+               "has_deci = %d", scale_x, scale_y, hw_res_info_.has_decimation);
+      return kErrorNotSupported;
+    }
+  }
+
+  DLOGV_IF(kTagResources, "scale_x = %.4f, scale_y = %.4f", scale_x, scale_y);
+
+  return kErrorNone;
+}
+
+DisplayError ResourceDefault::ValidateUpScaling(float scale_x, float scale_y) {
+  float max_scale_up = FLOAT(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 = %f", 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 = %f", 1.0f / scale_y);
+      return kErrorNotSupported;
+    }
+  }
+
+  DLOGV_IF(kTagResources, "scale_x = %.4f, scale_y = %.4f", scale_x, scale_y);
+
+  return kErrorNone;
+}
+
+DisplayError ResourceDefault::GetScaleFactor(const LayerRect &crop, const LayerRect &dst,
+                                        float *scale_x, float *scale_y) {
+  float crop_width = crop.right - crop.left;
+  float crop_height = crop.bottom - crop.top;
+  float dst_width = dst.right - dst.left;
+  float dst_height = dst.bottom - dst.top;
+
+  *scale_x = crop_width / dst_width;
+  *scale_y = crop_height / dst_height;
+
+  return kErrorNone;
+}
+
+DisplayError ResourceDefault::SetDecimationFactor(HWPipeInfo *pipe) {
+  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_h = src_h / dst_h;
+
+  float src_w = pipe->src_roi.right - pipe->src_roi.left;
+  float dst_w = pipe->dst_roi.right - pipe->dst_roi.left;
+  float down_scale_w = src_w / dst_w;
+
+  pipe->horizontal_decimation = 0;
+  pipe->vertical_decimation = 0;
+
+  if (CalculateDecimation(down_scale_w, &pipe->horizontal_decimation) != kErrorNone) {
+    return kErrorNotSupported;
+  }
+
+  if (CalculateDecimation(down_scale_h, &pipe->vertical_decimation) != kErrorNone) {
+    return kErrorNotSupported;
+  }
+
+  DLOGI_IF(kTagResources, "horizontal_decimation %d, vertical_decimation %d",
+           pipe->horizontal_decimation, pipe->vertical_decimation);
+
+  return kErrorNone;
+}
+
+void ResourceDefault::SplitRect(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;
+  float src_width_ori = src_width;
+  src_width = ROUND_UP_ALIGN_DOWN(src_width / 2, 1);
+  dst_width = ROUND_UP_ALIGN_DOWN(dst_width * src_width / src_width_ori, 1);
+
+  src_left->left = src_rect.left;
+  src_left->right = src_rect.left + src_width;
+  src_right->left = src_left->right;
+  src_right->right = src_rect.right;
+
+  src_left->top = src_rect.top;
+  src_left->bottom = src_rect.bottom;
+  src_right->top = src_rect.top;
+  src_right->bottom = src_rect.bottom;
+
+  dst_left->top = dst_rect.top;
+  dst_left->bottom = dst_rect.bottom;
+  dst_right->top = dst_rect.top;
+  dst_right->bottom = dst_rect.bottom;
+
+  dst_left->left = dst_rect.left;
+  dst_left->right = dst_rect.left + dst_width;
+  dst_right->left = dst_left->right;
+  dst_right->right = dst_rect.right;
+}
+
+DisplayError ResourceDefault::AlignPipeConfig(const Layer &layer, HWPipeInfo *left_pipe,
+                                         HWPipeInfo *right_pipe) {
+  DisplayError error = kErrorNone;
+  if (!left_pipe->valid) {
+    DLOGE_IF(kTagResources, "left_pipe should not be invalid");
+    return kErrorNotSupported;
+  }
+
+  error = ValidatePipeParams(left_pipe);
+  if (error != kErrorNone) {
+    goto PipeConfigExit;
+  }
+
+  if (right_pipe->valid) {
+    // Make sure the  left and right ROI are conjunct
+    right_pipe->src_roi.left = left_pipe->src_roi.right;
+    right_pipe->dst_roi.left = left_pipe->dst_roi.right;
+    error = ValidatePipeParams(right_pipe);
+  }
+
+PipeConfigExit:
+  if (error != kErrorNone) {
+    DLOGV_IF(kTagResources, "AlignPipeConfig failed");
+  }
+  return error;
+}
+
+DisplayError ResourceDefault::CalculateDecimation(float downscale, uint8_t *decimation) {
+  float max_down_scale = FLOAT(hw_res_info_.max_scale_down);
+
+  if (downscale <= max_down_scale) {
+    *decimation = 0;
+    return kErrorNone;
+  } else if (!hw_res_info_.has_decimation) {
+    DLOGE("Downscaling exceeds the maximum MDP downscale limit but decimation not enabled");
+    return kErrorNotSupported;
+  }
+
+  // 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 / 4))) = powf(2.0, 1.0) = 2
+  *decimation = UINT8(ceilf(log2f(downscale / max_down_scale)));
+  return kErrorNone;
+}
+
+}  // namespace sdm
+
diff --git a/sdm/libs/core/resource_default.h b/sdm/libs/core/resource_default.h
new file mode 100644
index 0000000..14174d1
--- /dev/null
+++ b/sdm/libs/core/resource_default.h
@@ -0,0 +1,156 @@
+/*
+* 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:
+*    * Redistributions of source code must retain the above copyright notice, this list of
+*      conditions and the following disclaimer.
+*    * Redistributions in binary form must reproduce the above copyright notice, this list of
+*      conditions and the following disclaimer in the documentation and/or other materials provided
+*      with the distribution.
+*    * Neither the name of The Linux Foundation nor the names of its contributors may be used to
+*      endorse or promote products derived from this software without specific prior written
+*      permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef __RESOURCE_DEFAULT_H__
+#define __RESOURCE_DEFAULT_H__
+
+#include <core/display_interface.h>
+#include <private/resource_interface.h>
+#include <utils/locker.h>
+
+#include "hw_interface.h"
+
+namespace sdm {
+
+class ResourceDefault : public ResourceInterface {
+ public:
+  ResourceDefault();
+  DisplayError Init(const HWResourceInfo &hw_resource_info);
+  DisplayError Deinit();
+  virtual DisplayError RegisterDisplay(DisplayType type, const HWDisplayAttributes &attributes,
+                                       const HWPanelInfo &hw_panel_info, Handle *display_ctx);
+  virtual DisplayError UnregisterDisplay(Handle display_ctx);
+  virtual void ReconfigureDisplay(Handle display_ctx, const HWDisplayAttributes &attributes,
+                                  const HWPanelInfo &hw_panel_info);
+  virtual DisplayError Start(Handle display_ctx);
+  virtual DisplayError Stop(Handle display_ctx);
+  virtual DisplayError Acquire(Handle display_ctx, HWLayers *hw_layers);
+  virtual DisplayError PostPrepare(Handle display_ctx, HWLayers *hw_layers);
+  virtual DisplayError PostCommit(Handle display_ctx, HWLayers *hw_layers);
+  virtual void Purge(Handle display_ctx);
+  virtual DisplayError SetMaxMixerStages(Handle display_ctx, uint32_t max_mixer_stages);
+  virtual DisplayError ValidateScaling(const LayerRect &crop, const LayerRect &dst,
+                                       bool rotate90);
+
+ private:
+  enum PipeId {
+    kPipeIdVIG0,
+    kPipeIdVIG1,
+    kPipeIdVIG2,
+    kPipeIdRGB0,
+    kPipeIdRGB1,
+    kPipeIdRGB2,
+    kPipeIdDMA0,
+    kPipeIdDMA1,
+    kPipeIdVIG3,
+    kPipeIdRGB3,
+    kPipeIdMax,
+  };
+
+  enum PipeType {
+    kPipeTypeUnused,
+    kPipeTypeVIG,
+    kPipeTypeRGB,
+    kPipeTypeDMA,
+    kPipeTypeMax,
+  };
+
+  enum PipeOwner {
+    kPipeOwnerUserMode,       // Pipe state when it is available for reservation
+    kPipeOwnerKernelMode,  // Pipe state when pipe is owned by kernel
+  };
+
+  // todo: retrieve all these from kernel
+  enum {
+    kMaxDecimationDownScaleRatio = 8,
+  };
+
+  struct SourcePipe {
+    PipeType type;
+    PipeOwner owner;
+    uint32_t mdss_pipe_id;
+    uint32_t index;
+    HWBlockType hw_block_id;
+    int priority;
+
+    SourcePipe() : type(kPipeTypeUnused), owner(kPipeOwnerUserMode), mdss_pipe_id(kPipeIdMax),
+                  index(0), hw_block_id(kHWBlockMax), priority(0) { }
+
+    inline void ResetState() { hw_block_id = kHWBlockMax;}
+  };
+
+  struct DisplayResourceContext {
+    HWDisplayAttributes display_attributes;
+    HWBlockType hw_block_id;
+    uint64_t frame_count;
+
+    DisplayResourceContext() : hw_block_id(kHWBlockMax), frame_count(0) { }
+  };
+
+  struct HWBlockContext {
+    bool is_in_use;
+    HWBlockContext() : is_in_use(false) { }
+  };
+
+  uint32_t GetMdssPipeId(PipeType pipe_type, uint32_t index);
+  uint32_t NextPipe(PipeType pipe_type, HWBlockType hw_block_id);
+  uint32_t SearchPipe(HWBlockType hw_block_id, SourcePipe *src_pipes, uint32_t num_pipe);
+  uint32_t GetPipe(HWBlockType hw_block_id, bool need_scale);
+  bool IsScalingNeeded(const HWPipeInfo *pipe_info);
+  DisplayError Config(DisplayResourceContext *display_resource_ctx, HWLayers *hw_layers);
+  DisplayError DisplaySplitConfig(DisplayResourceContext *display_resource_ctx,
+                                 const LayerRect &src_rect, const LayerRect &dst_rect,
+                                 HWLayerConfig *layer_config);
+  DisplayError SrcSplitConfig(DisplayResourceContext *display_resource_ctx,
+                             const LayerRect &src_rect, const LayerRect &dst_rect,
+                             HWLayerConfig *layer_config);
+  bool CalculateCropRects(const LayerRect &scissor, LayerRect *crop, LayerRect *dst);
+  DisplayError ValidateLayerDimensions(const Layer &layer);
+  DisplayError ValidateDimensions(const LayerRect &crop, const LayerRect &dst);
+  DisplayError ValidatePipeParams(HWPipeInfo *pipe_info);
+  DisplayError ValidateDownScaling(float scale_x, float scale_y);
+  DisplayError ValidateUpScaling(float scale_x, float scale_y);
+  DisplayError GetScaleFactor(const LayerRect &crop, const LayerRect &dst, float *scale_x,
+                             float *scale_y);
+  DisplayError SetDecimationFactor(HWPipeInfo *pipe);
+  void SplitRect(const LayerRect &src_rect, const LayerRect &dst_rect, LayerRect *src_left,
+                LayerRect *dst_left, LayerRect *src_right, LayerRect *dst_right);
+  DisplayError AlignPipeConfig(const Layer &layer, HWPipeInfo *left_pipe, HWPipeInfo *right_pipe);
+  void ResourceStateLog(void);
+  DisplayError CalculateDecimation(float downscale, uint8_t *decimation);
+
+  Locker locker_;
+  HWResourceInfo hw_res_info_;
+  HWBlockContext hw_block_ctx_[kHWBlockMax];
+  SourcePipe src_pipes_[kPipeIdMax];
+  uint32_t num_pipe_;
+  SourcePipe *vig_pipes_;
+  SourcePipe *rgb_pipes_;
+  SourcePipe *dma_pipes_;
+};
+
+}  // namespace sdm
+
+#endif  // __RESOURCE_DEFAULT_H__
+
diff --git a/sdm/libs/core/strategy.cpp b/sdm/libs/core/strategy.cpp
new file mode 100644
index 0000000..16e3f63
--- /dev/null
+++ b/sdm/libs/core/strategy.cpp
@@ -0,0 +1,185 @@
+/*
+* 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:
+*    * 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 <utils/debug.h>
+
+#include "strategy.h"
+
+#define __CLASS__ "Strategy"
+
+namespace sdm {
+
+Strategy::Strategy(ExtensionInterface *extension_intf, DisplayType type,
+                   const HWResourceInfo &hw_resource_info, const HWPanelInfo &hw_panel_info)
+  : extension_intf_(extension_intf), strategy_intf_(NULL), partial_update_intf_(NULL),
+    display_type_(type),hw_resource_info_(hw_resource_info), hw_panel_info_(hw_panel_info),
+    hw_layers_info_(NULL), fb_layer_index_(0), extn_start_success_(false), tried_default_(false) {
+}
+
+DisplayError Strategy::Init() {
+  DisplayError error = kErrorNone;
+
+  if (extension_intf_) {
+    error = extension_intf_->CreateStrategyExtn(display_type_, &strategy_intf_);
+    if (error != kErrorNone) {
+      DLOGE("Failed to create strategy");
+      return error;
+    }
+
+    error = extension_intf_->CreatePartialUpdate(display_type_, hw_resource_info_,
+                                                 hw_panel_info_, &partial_update_intf_);
+    if (error != kErrorNone) {
+      DLOGW("Partial Update creation failed, Continue without partial update.");
+    }
+  }
+
+  return kErrorNone;
+}
+
+DisplayError Strategy::Deinit() {
+  if (strategy_intf_) {
+    if (partial_update_intf_) {
+      extension_intf_->DestroyPartialUpdate(partial_update_intf_);
+    }
+
+    extension_intf_->DestroyStrategyExtn(strategy_intf_);
+  }
+
+  return kErrorNone;
+}
+
+DisplayError Strategy::Start(HWLayersInfo *hw_layers_info, uint32_t *max_attempts) {
+  DisplayError error = kErrorNone;
+
+  hw_layers_info_ = hw_layers_info;
+  extn_start_success_ = false;
+  tried_default_ = false;
+
+  uint32_t i = 0;
+  LayerStack *layer_stack = hw_layers_info_->stack;
+  for (; i < layer_stack->layer_count; i++) {
+    if (layer_stack->layers[i].composition == kCompositionGPUTarget) {
+      fb_layer_index_ = i;
+      break;
+    }
+  }
+
+  if (i == layer_stack->layer_count) {
+    return kErrorUndefined;
+  }
+
+  GenerateROI();
+
+  if (strategy_intf_) {
+    error = strategy_intf_->Start(hw_layers_info_, max_attempts);
+    if (error == kErrorNone) {
+      extn_start_success_ = true;
+      return kErrorNone;
+    }
+  }
+
+  *max_attempts = 1;
+
+  return kErrorNone;
+}
+
+DisplayError Strategy::Stop() {
+  if (extn_start_success_) {
+    return strategy_intf_->Stop();
+  }
+
+  return kErrorNone;
+}
+
+DisplayError Strategy::GetNextStrategy(StrategyConstraints *constraints) {
+  DisplayError error = kErrorNone;
+
+  if (extn_start_success_) {
+    error = strategy_intf_->GetNextStrategy(constraints);
+    if (error == kErrorNone) {
+      return kErrorNone;
+    }
+  }
+
+  // Default composition is already tried.
+  if (tried_default_) {
+    return kErrorUndefined;
+  }
+
+  // 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;
+  hw_layer_count = 0;
+  for (uint32_t i = 0; i < layer_stack->layer_count; i++) {
+    LayerComposition &composition = layer_stack->layers[i].composition;
+    if (composition == kCompositionGPUTarget) {
+      hw_layers_info_->index[hw_layer_count++] = i;
+    } else {
+      composition = kCompositionGPU;
+    }
+  }
+
+  tried_default_ = true;
+
+  // There can be one and only one GPU target buffer.
+  if (hw_layer_count != 1) {
+    return kErrorParameters;
+  }
+
+  return kErrorNone;
+}
+
+void Strategy::GenerateROI() {
+  bool split_display = false;
+
+  if (partial_update_intf_ && partial_update_intf_->GenerateROI(hw_layers_info_) == kErrorNone) {
+    return;
+  }
+
+  LayerStack *layer_stack = hw_layers_info_->stack;
+  LayerRect &src_rect = layer_stack->layers[fb_layer_index_].src_rect;
+  // TODO(user): read panels x_pixels and y_pixels instead of fb_x_res and fb_y_res
+  float fb_x_res = src_rect.right - src_rect.left;
+  float fb_y_res = src_rect.bottom - src_rect.top;
+
+  if (!hw_resource_info_.is_src_split &&
+     ((fb_x_res > hw_resource_info_.max_mixer_width) ||
+     ((display_type_ == kPrimary) && hw_panel_info_.split_info.right_split))) {
+    split_display = true;
+  }
+
+  if (split_display) {
+    float left_split = FLOAT(hw_panel_info_.split_info.left_split);
+    hw_layers_info_->left_partial_update = (LayerRect) {0.0f, 0.0f, left_split, fb_y_res};
+    hw_layers_info_->right_partial_update = (LayerRect) {left_split, 0.0f, fb_x_res, fb_y_res};
+  } else {
+    hw_layers_info_->left_partial_update = (LayerRect) {0.0f, 0.0f, fb_x_res, fb_y_res};
+    hw_layers_info_->right_partial_update = (LayerRect) {0.0f, 0.0f, 0.0f, 0.0f};
+  }
+}
+
+}  // namespace sdm
+
diff --git a/sdm/libs/core/strategy.h b/sdm/libs/core/strategy.h
new file mode 100644
index 0000000..c7a67d9
--- /dev/null
+++ b/sdm/libs/core/strategy.h
@@ -0,0 +1,63 @@
+/*
+* 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:
+*    * Redistributions of source code must retain the above copyright notice, this list of
+*      conditions and the following disclaimer.
+*    * Redistributions in binary form must reproduce the above copyright notice, this list of
+*      conditions and the following disclaimer in the documentation and/or other materials provided
+*      with the distribution.
+*    * Neither the name of The Linux Foundation nor the names of its contributors may be used to
+*      endorse or promote products derived from this software without specific prior written
+*      permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef __STRATEGY_H__
+#define __STRATEGY_H__
+
+#include <core/display_interface.h>
+#include <private/extension_interface.h>
+
+namespace sdm {
+
+class Strategy {
+ public:
+  Strategy(ExtensionInterface *extension_intf, DisplayType type,
+           const HWResourceInfo &hw_resource_info, const HWPanelInfo &hw_panel_info);
+
+  DisplayError Init();
+  DisplayError Deinit();
+
+  DisplayError Start(HWLayersInfo *hw_layers_info, uint32_t *max_attempts);
+  DisplayError GetNextStrategy(StrategyConstraints *constraints);
+  DisplayError Stop();
+
+ private:
+  void GenerateROI();
+
+  ExtensionInterface *extension_intf_;
+  StrategyInterface *strategy_intf_;
+  PartialUpdateInterface *partial_update_intf_;
+  DisplayType display_type_;
+  HWResourceInfo hw_resource_info_;
+  HWPanelInfo hw_panel_info_;
+  HWLayersInfo *hw_layers_info_;
+  uint32_t fb_layer_index_;
+  bool extn_start_success_;
+  bool tried_default_;
+};
+
+}  // namespace sdm
+
+#endif  // __STRATEGY_H__
+
diff --git a/sdm/libs/hwc/Android.mk b/sdm/libs/hwc/Android.mk
new file mode 100644
index 0000000..f233557
--- /dev/null
+++ b/sdm/libs/hwc/Android.mk
@@ -0,0 +1,31 @@
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE                  := hwcomposer.$(TARGET_BOARD_PLATFORM)
+LOCAL_MODULE_RELATIVE_PATH    := hw
+LOCAL_MODULE_TAGS             := optional
+LOCAL_C_INCLUDES              := hardware/qcom/display/sdm/include/ \
+                                 hardware/qcom/display/libgralloc/ \
+                                 hardware/qcom/display/libqservice/ \
+                                 hardware/qcom/display/libqdutils/
+LOCAL_CFLAGS                  := -Wno-missing-field-initializers -Wno-unused-parameter \
+                                 -Wconversion -Wall -Werror \
+                                 -DLOG_TAG=\"SDM\"
+
+# TODO: Move this to the common makefile
+ifeq ($(call is-board-platform-in-list, $(MASTER_SIDE_CP_TARGET_LIST)), true)
+    LOCAL_CFLAGS += -DMASTER_SIDE_CP
+endif
+
+LOCAL_SHARED_LIBRARIES        := libsdmcore libqservice libbinder libhardware libhardware_legacy \
+                                 libutils libcutils libsync libmemalloc libqdutils
+LOCAL_SRC_FILES               := hwc_session.cpp \
+                                 hwc_display.cpp \
+                                 hwc_display_primary.cpp \
+                                 hwc_display_external.cpp \
+                                 hwc_display_virtual.cpp \
+                                 hwc_debugger.cpp \
+                                 hwc_buffer_allocator.cpp \
+                                 hwc_buffer_sync_handler.cpp
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/sdm/libs/hwc/hwc_buffer_allocator.cpp b/sdm/libs/hwc/hwc_buffer_allocator.cpp
new file mode 100644
index 0000000..2d79f0d
--- /dev/null
+++ b/sdm/libs/hwc/hwc_buffer_allocator.cpp
@@ -0,0 +1,187 @@
+/*
+* Copyright (c) 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:
+*  * 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 <gralloc_priv.h>
+#include <memalloc.h>
+#include <gr.h>
+#include <alloc_controller.h>
+#include <utils/constants.h>
+#include <core/buffer_allocator.h>
+
+#include "hwc_debugger.h"
+#include "hwc_buffer_allocator.h"
+
+#define __CLASS__ "HWCBufferAllocator"
+
+namespace sdm {
+
+HWCBufferAllocator::HWCBufferAllocator() {
+  alloc_controller_ = gralloc::IAllocController::getInstance();
+}
+
+DisplayError HWCBufferAllocator::AllocateBuffer(BufferInfo *buffer_info) {
+  gralloc::alloc_data data;
+
+  const BufferConfig &buffer_config = buffer_info->buffer_config;
+  AllocatedBufferInfo *alloc_buffer_info = &buffer_info->alloc_buffer_info;
+  MetaBufferInfo *meta_buffer_info = new MetaBufferInfo();
+
+  if (!meta_buffer_info) {
+    return kErrorMemory;
+  }
+
+  int alloc_flags = GRALLOC_USAGE_PRIVATE_IOMMU_HEAP;
+  int error = 0;
+
+  int width = INT(buffer_config.width);
+  int height = INT(buffer_config.height);
+  int format;
+
+  if (buffer_config.secure) {
+    alloc_flags = GRALLOC_USAGE_PRIVATE_MM_HEAP;
+    alloc_flags |= GRALLOC_USAGE_PROTECTED;
+    data.align = SECURE_ALIGN;
+  } else {
+    data.align = getpagesize();
+  }
+
+  if (buffer_config.cache == false) {
+    // Allocate uncached buffers
+    alloc_flags |= GRALLOC_USAGE_PRIVATE_UNCACHED;
+  }
+
+  error = SetBufferInfo(buffer_config.format, &format, &alloc_flags);
+  if (error != 0) {
+    return kErrorParameters;
+  }
+
+  int aligned_width = 0, aligned_height = 0;
+  uint32_t buffer_size = getBufferSizeAndDimensions(width, height, format, alloc_flags,
+                                                    aligned_width, aligned_height);
+
+  buffer_size = ROUND_UP(buffer_size, data.align) * buffer_config.buffer_count;
+
+  data.base = 0;
+  data.fd = -1;
+  data.offset = 0;
+  data.size = buffer_size;
+  data.uncached = !buffer_config.cache;
+
+  error = alloc_controller_->allocate(data, alloc_flags);
+  if (error != 0) {
+    DLOGE("Error allocating memory size %d uncached %d", data.size, data.uncached);
+    return kErrorMemory;
+  }
+
+  alloc_buffer_info->fd = data.fd;
+  alloc_buffer_info->stride = aligned_width;
+  alloc_buffer_info->size = buffer_size;
+
+  meta_buffer_info->base_addr = data.base;
+  meta_buffer_info->alloc_type = data.allocType;
+
+  buffer_info->private_data = meta_buffer_info;
+
+  return kErrorNone;
+}
+
+DisplayError HWCBufferAllocator::FreeBuffer(BufferInfo *buffer_info) {
+  int ret = 0;
+
+  AllocatedBufferInfo *alloc_buffer_info = &buffer_info->alloc_buffer_info;
+  MetaBufferInfo *meta_buffer_info = static_cast<MetaBufferInfo *> (buffer_info->private_data);
+  if (alloc_buffer_info->fd < 0) {
+    DLOGE("Invalid parameters: fd %d", alloc_buffer_info->fd);
+    return kErrorParameters;
+  }
+
+  gralloc::IMemAlloc *memalloc = alloc_controller_->getAllocator(meta_buffer_info->alloc_type);
+  if (memalloc == NULL) {
+    DLOGE("Memalloc handle is NULL, alloc type %d", meta_buffer_info->alloc_type);
+    return kErrorResources;
+  }
+
+  ret = memalloc->free_buffer(meta_buffer_info->base_addr, alloc_buffer_info->size, 0,
+                              alloc_buffer_info->fd);
+  if (ret != 0) {
+    DLOGE("Error freeing buffer base_addr %p size %d fd %d", meta_buffer_info->base_addr,
+          alloc_buffer_info->size, alloc_buffer_info->fd);
+    return kErrorMemory;
+  }
+
+  alloc_buffer_info->fd = -1;
+  alloc_buffer_info->stride = 0;
+  alloc_buffer_info->size = 0;
+
+  meta_buffer_info->base_addr = NULL;
+  meta_buffer_info->alloc_type = 0;
+
+  delete meta_buffer_info;
+  meta_buffer_info = NULL;
+
+  return kErrorNone;
+}
+
+int HWCBufferAllocator::SetBufferInfo(LayerBufferFormat format, int *target, int *flags) {
+  switch (format) {
+  case kFormatRGBA8888:                 *target = HAL_PIXEL_FORMAT_RGBA_8888;             break;
+  case kFormatRGBX8888:                 *target = HAL_PIXEL_FORMAT_RGBX_8888;             break;
+  case kFormatRGB888:                   *target = HAL_PIXEL_FORMAT_RGB_888;               break;
+  case kFormatRGB565:                   *target = HAL_PIXEL_FORMAT_RGB_565;               break;
+  case kFormatBGRA8888:                 *target = HAL_PIXEL_FORMAT_BGRA_8888;             break;
+  case kFormatYCrCb420Planar:           *target = HAL_PIXEL_FORMAT_YV12;                  break;
+  case kFormatYCrCb420SemiPlanar:       *target = HAL_PIXEL_FORMAT_YCrCb_420_SP;          break;
+  case kFormatYCbCr420SemiPlanar:       *target = HAL_PIXEL_FORMAT_YCbCr_420_SP;          break;
+  case kFormatYCbCr422H2V1Packed:       *target = HAL_PIXEL_FORMAT_YCbCr_422_I;           break;
+  case kFormatYCbCr422H2V1SemiPlanar:   *target = HAL_PIXEL_FORMAT_YCbCr_422_SP;          break;
+  case kFormatYCbCr420SemiPlanarVenus:  *target = HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS;    break;
+  case kFormatYCbCr420SPVenusUbwc:    *target = HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS_UBWC; break;
+  case kFormatRGBA5551:                 *target = HAL_PIXEL_FORMAT_RGBA_5551;             break;
+  case kFormatRGBA4444:                 *target = HAL_PIXEL_FORMAT_RGBA_4444;             break;
+  case kFormatRGBA8888Ubwc:
+    *target = HAL_PIXEL_FORMAT_RGBA_8888;
+    *flags |= GRALLOC_USAGE_PRIVATE_ALLOC_UBWC;
+    break;
+  case kFormatRGBX8888Ubwc:
+    *target = HAL_PIXEL_FORMAT_RGBX_8888;
+    *flags |= GRALLOC_USAGE_PRIVATE_ALLOC_UBWC;
+    break;
+  case kFormatRGB565Ubwc:
+    *target = HAL_PIXEL_FORMAT_RGB_565;
+    *flags |= GRALLOC_USAGE_PRIVATE_ALLOC_UBWC;
+    break;
+  default:
+    DLOGE("Unsupported format = 0x%x", format);
+    return -EINVAL;
+  }
+
+  return 0;
+}
+
+}  // namespace sdm
diff --git a/sdm/libs/hwc/hwc_buffer_allocator.h b/sdm/libs/hwc/hwc_buffer_allocator.h
new file mode 100644
index 0000000..b3f8add
--- /dev/null
+++ b/sdm/libs/hwc/hwc_buffer_allocator.h
@@ -0,0 +1,65 @@
+/*
+* Copyright (c) 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:
+*  * Redistributions of source code must retain the above copyright
+*    notice, this list of conditions and the following disclaimer.
+*  * Redistributions in binary form must reproduce the above
+*    copyright notice, this list of conditions and the following
+*    disclaimer in the documentation and/or other materials provided
+*    with the distribution.
+*  * Neither the name of The Linux Foundation nor the names of its
+*    contributors may be used to endorse or promote products derived
+*    from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+* ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+#ifndef __HWC_BUFFER_ALLOCATOR_H__
+#define __HWC_BUFFER_ALLOCATOR_H__
+
+#include <sys/mman.h>
+#include <fcntl.h>
+
+namespace gralloc {
+
+class IAllocController;
+
+}  // namespace gralloc
+
+namespace sdm {
+
+class HWCBufferAllocator : public BufferAllocator {
+ public:
+  HWCBufferAllocator();
+
+  DisplayError AllocateBuffer(BufferInfo *buffer_info);
+  DisplayError FreeBuffer(BufferInfo *buffer_info);
+
+ private:
+  struct MetaBufferInfo {
+    int alloc_type;              //!< Specifies allocation type set by the buffer allocator.
+    void *base_addr;             //!< Specifies the base address of the allocated output buffer.
+  };
+
+  int SetBufferInfo(LayerBufferFormat format, int *target, int *flags);
+
+  gralloc::IAllocController *alloc_controller_;
+};
+
+}  // namespace sdm
+#endif  // __HWC_BUFFER_ALLOCATOR_H__
+
diff --git a/sdm/libs/hwc/hwc_buffer_sync_handler.cpp b/sdm/libs/hwc/hwc_buffer_sync_handler.cpp
new file mode 100644
index 0000000..9bc4ec9
--- /dev/null
+++ b/sdm/libs/hwc/hwc_buffer_sync_handler.cpp
@@ -0,0 +1,71 @@
+/*
+* Copyright (c) 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:
+*  * 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 <sync/sync.h>
+#include <utils/constants.h>
+
+#include "hwc_debugger.h"
+#include "hwc_buffer_sync_handler.h"
+
+#define __CLASS__ "HWCBufferSyncHandler"
+
+namespace sdm {
+
+DisplayError HWCBufferSyncHandler::SyncWait(int fd) {
+  int error = 0;
+
+  if (fd >= 0) {
+    error = sync_wait(fd, 1000);
+    if (error < 0) {
+      DLOGE("sync_wait error errno = %d, desc = %s", errno,  strerror(errno));
+      close(fd);
+      return kErrorTimeOut;
+    }
+    close(fd);
+  }
+
+  return kErrorNone;
+}
+
+DisplayError HWCBufferSyncHandler::SyncMerge(int fd1, int fd2, int *merged_fd) {
+  DisplayError error = kErrorNone;
+
+  *merged_fd = sync_merge("SyncMerge", fd1, fd2);
+  if (*merged_fd == -1) {
+    DLOGE(" Sync merge error! fd1 %d fd2 %d", fd1, fd2);
+    error = kErrorFileDescriptor;
+  }
+  close(fd1);
+  close(fd2);
+
+  return error;
+}
+
+}  // namespace sdm
+
diff --git a/sdm/libs/hwc/hwc_buffer_sync_handler.h b/sdm/libs/hwc/hwc_buffer_sync_handler.h
new file mode 100644
index 0000000..da94650
--- /dev/null
+++ b/sdm/libs/hwc/hwc_buffer_sync_handler.h
@@ -0,0 +1,52 @@
+/*
+* Copyright (c) 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:
+*  * Redistributions of source code must retain the above copyright
+*    notice, this list of conditions and the following disclaimer.
+*  * Redistributions in binary form must reproduce the above
+*    copyright notice, this list of conditions and the following
+*    disclaimer in the documentation and/or other materials provided
+*    with the distribution.
+*  * Neither the name of The Linux Foundation nor the names of its
+*    contributors may be used to endorse or promote products derived
+*    from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+* ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+#ifndef __HWC_BUFFER_SYNC_HANDLER_H__
+#define __HWC_BUFFER_SYNC_HANDLER_H__
+
+#include <sys/mman.h>
+#include <fcntl.h>
+#include <core/sdm_types.h>
+#include <core/buffer_sync_handler.h>
+
+namespace sdm {
+
+class HWCBufferSyncHandler : public BufferSyncHandler {
+ public:
+  HWCBufferSyncHandler() { }
+
+  virtual DisplayError SyncWait(int fd);
+  virtual DisplayError SyncMerge(int fd1, int fd2, int *merged_fd);
+};
+
+}  // namespace sdm
+#endif  // __HWC_BUFFER_SYNC_HANDLER_H__
+
+
diff --git a/sdm/libs/hwc/hwc_debugger.cpp b/sdm/libs/hwc/hwc_debugger.cpp
new file mode 100644
index 0000000..ab9309e
--- /dev/null
+++ b/sdm/libs/hwc/hwc_debugger.cpp
@@ -0,0 +1,127 @@
+/*
+* 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:
+*     * 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_debugger.h"
+
+namespace sdm {
+
+HWCDebugHandler HWCDebugHandler::debug_handler_;
+uint32_t HWCDebugHandler::debug_flags_ = 0x1;
+
+void HWCDebugHandler::DebugAll(bool enable) {
+  if (enable) {
+    debug_flags_ = 0xFFFFFFFF;
+  } else {
+    debug_flags_ = 0x1;   // kTagNone should always be printed.
+  }
+}
+
+void HWCDebugHandler::DebugResources(bool enable) {
+  if (enable) {
+    SET_BIT(debug_flags_, kTagResources);
+  } else {
+    CLEAR_BIT(debug_flags_, kTagResources);
+  }
+}
+
+void HWCDebugHandler::DebugStrategy(bool enable) {
+  if (enable) {
+    SET_BIT(debug_flags_, kTagStrategy);
+  } else {
+    CLEAR_BIT(debug_flags_, kTagStrategy);
+  }
+}
+
+void HWCDebugHandler::DebugCompManager(bool enable) {
+  if (enable) {
+    SET_BIT(debug_flags_, kTagCompManager);
+  } else {
+    CLEAR_BIT(debug_flags_, kTagCompManager);
+  }
+}
+
+void HWCDebugHandler::DebugDriverConfig(bool enable) {
+  if (enable) {
+    SET_BIT(debug_flags_, kTagDriverConfig);
+  } else {
+    CLEAR_BIT(debug_flags_, kTagDriverConfig);
+  }
+}
+
+void HWCDebugHandler::DebugRotator(bool enable) {
+  if (enable) {
+    SET_BIT(debug_flags_, kTagRotator);
+  } else {
+    CLEAR_BIT(debug_flags_, kTagRotator);
+  }
+}
+
+void HWCDebugHandler::Error(DebugTag /*tag*/, const char *format, ...) {
+  va_list list;
+  va_start(list, format);
+  __android_log_vprint(ANDROID_LOG_ERROR, LOG_TAG, format, list);
+}
+
+void HWCDebugHandler::Warning(DebugTag /*tag*/, const char *format, ...) {
+  va_list list;
+  va_start(list, format);
+  __android_log_vprint(ANDROID_LOG_WARN, LOG_TAG, format, list);
+}
+
+void HWCDebugHandler::Info(DebugTag tag, const char *format, ...) {
+  if (IS_BIT_SET(debug_flags_, tag)) {
+    va_list list;
+    va_start(list, format);
+    __android_log_vprint(ANDROID_LOG_INFO, LOG_TAG, format, list);
+  }
+}
+
+void HWCDebugHandler::Verbose(DebugTag tag, const char *format, ...) {
+  if (IS_BIT_SET(debug_flags_, tag)) {
+    va_list list;
+    va_start(list, format);
+    __android_log_vprint(ANDROID_LOG_VERBOSE, LOG_TAG, format, list);
+  }
+}
+
+void HWCDebugHandler::BeginTrace(const char *class_name, const char *function_name,
+                                 const char *custom_string) {
+  char name[PATH_MAX] = {0};
+  snprintf(name, sizeof(name), "%s::%s::%s", class_name, function_name, custom_string);
+  atrace_begin(ATRACE_TAG, name);
+}
+
+void HWCDebugHandler::EndTrace() {
+  atrace_end(ATRACE_TAG);
+}
+
+}  // namespace sdm
+
diff --git a/sdm/libs/hwc/hwc_debugger.h b/sdm/libs/hwc/hwc_debugger.h
new file mode 100644
index 0000000..61a1b6f
--- /dev/null
+++ b/sdm/libs/hwc/hwc_debugger.h
@@ -0,0 +1,80 @@
+/*
+* 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:
+*     * Redistributions of source code must retain the above copyright
+*       notice, this list of conditions and the following disclaimer.
+*     * Redistributions in binary form must reproduce the above
+*       copyright notice, this list of conditions and the following
+*       disclaimer in the documentation and/or other materials provided
+*       with the distribution.
+*     * Neither the name of The Linux Foundation nor the names of its
+*       contributors may be used to endorse or promote products derived
+*       from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+* ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef __HWC_DEBUGGER_H__
+#define __HWC_DEBUGGER_H__
+
+#define ATRACE_TAG (ATRACE_TAG_GRAPHICS | ATRACE_TAG_HAL)
+
+#include <core/sdm_types.h>
+#include <core/debug_interface.h>
+#include <cutils/log.h>
+#include <utils/Trace.h>
+
+#define DLOG(Macro, format, ...) Macro(__CLASS__ "::%s: " format, __FUNCTION__, ##__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__)
+
+#define DTRACE_BEGIN(custom_string) HWCDebugHandler::Get()->BeginTrace(__CLASS__, __FUNCTION__, \
+                                                                       custom_string)
+#define DTRACE_END() HWCDebugHandler::Get()->EndTrace()
+#define DTRACE_SCOPED() ScopeTracer<HWCDebugHandler> scope_tracer(__CLASS__, __FUNCTION__)
+
+namespace sdm {
+
+class HWCDebugHandler : public DebugHandler {
+ public:
+  static inline DebugHandler* Get() { return &debug_handler_; }
+  static void DebugAll(bool enable);
+  static void DebugResources(bool enable);
+  static void DebugStrategy(bool enable);
+  static void DebugCompManager(bool enable);
+  static void DebugDriverConfig(bool enable);
+  static void DebugRotator(bool enable);
+
+  virtual void Error(DebugTag tag, const char *format, ...);
+  virtual void Warning(DebugTag tag, const char *format, ...);
+  virtual void Info(DebugTag tag, const char *format, ...);
+  virtual void Verbose(DebugTag tag, const char *format, ...);
+  virtual void BeginTrace(const char *class_name, const char *function_name,
+                          const char *custom_string);
+  virtual void EndTrace();
+
+ private:
+  static HWCDebugHandler debug_handler_;
+  static uint32_t debug_flags_;
+};
+
+}  // namespace sdm
+
+#endif  // __HWC_DEBUGGER_H__
+
diff --git a/sdm/libs/hwc/hwc_display.cpp b/sdm/libs/hwc/hwc_display.cpp
new file mode 100644
index 0000000..0278c90
--- /dev/null
+++ b/sdm/libs/hwc/hwc_display.cpp
@@ -0,0 +1,1008 @@
+/*
+* 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:
+*     * 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 <math.h>
+#include <errno.h>
+#include <gralloc_priv.h>
+#include <utils/constants.h>
+#include <qdMetaData.h>
+#include <sync/sync.h>
+#include <cutils/properties.h>
+
+#include "hwc_display.h"
+#include "hwc_debugger.h"
+
+#define __CLASS__ "HWCDisplay"
+
+namespace sdm {
+
+HWCDisplay::HWCDisplay(CoreInterface *core_intf, hwc_procs_t const **hwc_procs, DisplayType type,
+                       int id)
+  : core_intf_(core_intf), hwc_procs_(hwc_procs), type_(type), id_(id), display_intf_(NULL),
+    flush_(false), output_buffer_(NULL), dump_frame_count_(0), dump_frame_index_(0),
+    dump_input_layers_(false), swap_interval_zero_(false), framebuffer_config_(NULL),
+    display_paused_(false), use_metadata_refresh_rate_(false), metadata_refresh_rate_(0) {
+}
+
+int HWCDisplay::Init() {
+  DisplayError error = core_intf_->CreateDisplay(type_, this, &display_intf_);
+  if (error != kErrorNone) {
+    DLOGE("Display create failed. Error = %d display_type %d event_handler %p disp_intf %p",
+      error, type_, this, &display_intf_);
+    return -EINVAL;
+  }
+
+  char property[PROPERTY_VALUE_MAX];
+  if (property_get("debug.egl.swapinterval", property, "1") > 0) {
+    if (atoi(property) == 0) {
+      swap_interval_zero_ = true;
+    }
+  }
+
+  framebuffer_config_ = new DisplayConfigVariableInfo();
+  if (!framebuffer_config_) {
+    DLOGV("Failed to allocate memory for custom framebuffer config.");
+    core_intf_->DestroyDisplay(display_intf_);
+    return -EINVAL;
+  }
+
+  return 0;
+}
+
+int HWCDisplay::Deinit() {
+  DisplayError error = core_intf_->DestroyDisplay(display_intf_);
+  if (error != kErrorNone) {
+    DLOGE("Display destroy failed. Error = %d", error);
+    return -EINVAL;
+  }
+
+  if (layer_stack_memory_.raw) {
+    delete[] layer_stack_memory_.raw;
+    layer_stack_memory_.raw = NULL;
+  }
+
+  delete framebuffer_config_;
+
+  return 0;
+}
+
+int HWCDisplay::EventControl(int event, int enable) {
+  DisplayError error = kErrorNone;
+
+  switch (event) {
+  case HWC_EVENT_VSYNC:
+    error = display_intf_->SetVSyncState(enable);
+    break;
+  case HWC_EVENT_ORIENTATION:
+    // TODO(user): Need to handle this case
+    break;
+  default:
+    DLOGW("Unsupported event = %d", event);
+  }
+
+  if (error != kErrorNone) {
+    DLOGE("Failed. event = %d, enable = %d, error = %d", event, enable, error);
+    return -EINVAL;
+  }
+
+  return 0;
+}
+
+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;
+    last_power_mode_ = HWC_POWER_MODE_NORMAL;
+    break;
+  case HWC_POWER_MODE_DOZE:
+    state = kStateDoze;
+    last_power_mode_ = HWC_POWER_MODE_DOZE;
+    break;
+  case HWC_POWER_MODE_DOZE_SUSPEND:
+    state = kStateDozeSuspend;
+    last_power_mode_ = HWC_POWER_MODE_DOZE_SUSPEND;
+    break;
+  default:
+    return -EINVAL;
+  }
+
+  DisplayError error = display_intf_->SetDisplayState(state);
+  if (error != kErrorNone) {
+    DLOGE("Set state failed. Error = %d", error);
+    return -EINVAL;
+  }
+
+  return 0;
+}
+
+int HWCDisplay::GetDisplayConfigs(uint32_t *configs, size_t *num_configs) {
+  if (*num_configs > 0) {
+    configs[0] = 0;
+    *num_configs = 1;
+  }
+
+  return 0;
+}
+
+int HWCDisplay::GetDisplayAttributes(uint32_t config, const uint32_t *attributes, int32_t *values) {
+  DisplayError error = kErrorNone;
+
+  DisplayConfigVariableInfo variable_config;
+  uint32_t active_config = UINT32(GetActiveConfig());
+  if (IsFrameBufferScaled() && config == active_config) {
+    variable_config = *framebuffer_config_;
+  } else {
+    error = display_intf_->GetConfig(config, &variable_config);
+    if (error != kErrorNone) {
+      DLOGE("GetConfig variable info failed. Error = %d", error);
+      return -EINVAL;
+    }
+  }
+
+  for (int i = 0; attributes[i] != HWC_DISPLAY_NO_ATTRIBUTE; i++) {
+    switch (attributes[i]) {
+    case HWC_DISPLAY_VSYNC_PERIOD:
+      values[i] = variable_config.vsync_period_ns;
+      break;
+    case HWC_DISPLAY_WIDTH:
+      values[i] = variable_config.x_pixels;
+      break;
+    case HWC_DISPLAY_HEIGHT:
+      values[i] = variable_config.y_pixels;
+      break;
+    case HWC_DISPLAY_DPI_X:
+      values[i] = INT32(variable_config.x_dpi * 1000.0f);
+      break;
+    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:
+      DLOGW("Spurious attribute type = %d", attributes[i]);
+      return -EINVAL;
+    }
+  }
+
+  return 0;
+}
+
+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(hwc_display_contents_1_t *content_list) {
+  return 0;
+}
+
+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;
+}
+
+void HWCDisplay::SetFrameDumpConfig(uint32_t count, uint32_t bit_mask_layer_type) {
+  dump_frame_count_ = count;
+  dump_frame_index_ = 0;
+  dump_input_layers_ = ((bit_mask_layer_type & (1 << INPUT_LAYER_DUMP)) != 0);
+
+  DLOGI("num_frame_dump %d, input_layer_dump_enable %d", dump_frame_count_, dump_input_layers_);
+}
+
+uint32_t HWCDisplay::GetLastPowerMode() {
+  return last_power_mode_;
+}
+
+DisplayError HWCDisplay::VSync(const DisplayEventVSync &vsync) {
+  if (*hwc_procs_) {
+    (*hwc_procs_)->vsync(*hwc_procs_, id_, vsync.timestamp);
+  }
+
+  return kErrorNone;
+}
+
+DisplayError HWCDisplay::Refresh() {
+  if (*hwc_procs_) {
+    (*hwc_procs_)->invalidate(*hwc_procs_);
+  }
+
+  return kErrorNone;
+}
+
+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
+  // visible rectangles in each layer d) dirty rectangle for each layer
+  size_t required_size = num_hw_layers * (sizeof(Layer) + sizeof(LayerBuffer));
+  for (size_t i = 0; i < num_hw_layers; i++) {
+    // visible rectangles + 1 dirty rectangle
+    size_t num_rects = content_list->hwLayers[i].visibleRegionScreen.numRects + 1;
+    required_size += num_rects * sizeof(LayerRect);
+  }
+
+  // Layer array may be large enough to hold current number of layers.
+  // If not, re-allocate it now.
+  if (layer_stack_memory_.size < required_size) {
+    if (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_memory_.kSizeSteps);
+
+    layer_stack_memory_.raw = new uint8_t[required_size];
+    if (!layer_stack_memory_.raw) {
+      return -ENOMEM;
+    }
+
+    layer_stack_memory_.size = required_size;
+  }
+
+  // Assign memory addresses now.
+  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);
+
+  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);
+  }
+
+  return 0;
+}
+
+int HWCDisplay::PrepareLayerStack(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;
+  if (num_hw_layers <= 1) {
+    flush_ = true;
+    return 0;
+  }
+
+  DisplayConfigVariableInfo active_config;
+  uint32_t active_config_index = 0;
+  display_intf_->GetActiveConfig(&active_config_index);
+
+  display_intf_->GetConfig(active_config_index, &active_config);
+
+  // Configure each layer
+  for (size_t i = 0; i < num_hw_layers; i++) {
+    hwc_layer_1_t &hwc_layer = content_list->hwLayers[i];
+    const private_handle_t *pvt_handle = static_cast<const private_handle_t *>(hwc_layer.handle);
+
+    Layer &layer = layer_stack_.layers[i];
+    LayerBuffer *layer_buffer = layer.input_buffer;
+
+    if (pvt_handle) {
+      layer_buffer->format = GetSDMFormat(pvt_handle->format, pvt_handle->flags);
+      if (layer_buffer->format == kFormatInvalid) {
+        return -EINVAL;
+      }
+
+      layer_buffer->width = pvt_handle->width;
+      layer_buffer->height = pvt_handle->height;
+      if (pvt_handle->bufferType == BUFFER_TYPE_VIDEO) {
+        layer_stack_.flags.video_present = true;
+        layer_buffer->flags.video = true;
+      }
+      if (pvt_handle->flags & private_handle_t::PRIV_FLAGS_SECURE_BUFFER) {
+        layer_stack_.flags.secure_present = true;
+        layer_buffer->flags.secure = true;
+      }
+
+      layer.frame_rate = UINT32(active_config.fps);
+      MetaData_t *meta_data = reinterpret_cast<MetaData_t *>(pvt_handle->base_metadata);
+      if (meta_data && meta_data->operation & UPDATE_REFRESH_RATE) {
+        layer.frame_rate = RoundToStandardFPS(meta_data->refreshrate);
+      }
+
+      if (meta_data && meta_data->operation == PP_PARAM_INTERLACED && meta_data->interlaced) {
+        layer_buffer->flags.interlace = true;
+      }
+
+      if (pvt_handle->flags & private_handle_t::PRIV_FLAGS_SECURE_DISPLAY) {
+        layer_buffer->flags.secure_display = true;
+      }
+    }
+
+    hwc_rect_t scaled_display_frame = hwc_layer.displayFrame;
+    ScaleDisplayFrame(&scaled_display_frame);
+    ApplyScanAdjustment(&scaled_display_frame);
+
+    SetRect(scaled_display_frame, &layer.dst_rect);
+    SetRect(hwc_layer.sourceCropf, &layer.src_rect);
+    for (size_t j = 0; j < hwc_layer.visibleRegionScreen.numRects; j++) {
+        SetRect(hwc_layer.visibleRegionScreen.rects[j], &layer.visible_regions.rect[j]);
+    }
+    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.plane_alpha = hwc_layer.planeAlpha;
+    layer.flags.skip = ((hwc_layer.flags & HWC_SKIP_LAYER) > 0);
+    layer.flags.updating = (layer_stack_cache_.layer_cache[i].handle != hwc_layer.handle);
+
+    if (hwc_layer.flags & HWC_SCREENSHOT_ANIMATOR_LAYER) {
+      layer_stack_.flags.animating = true;
+    }
+
+    if (layer.flags.skip) {
+      layer_stack_.flags.skip_present = true;
+    }
+  }
+
+  // Configure layer stack
+  layer_stack_.flags.geometry_changed = ((content_list->flags & HWC_GEOMETRY_CHANGED) > 0);
+
+  DisplayError error = display_intf_->Prepare(&layer_stack_);
+  if (error != kErrorNone) {
+    DLOGE("Prepare failed. Error = %d", error);
+
+    // To prevent surfaceflinger infinite wait, flush the previous frame during Commit() so that
+    // previous buffer and fences are released, and override the error.
+    flush_ = true;
+
+    return 0;
+  }
+
+  bool needs_fb_refresh = NeedsFrameBufferRefresh(content_list);
+
+  metadata_refresh_rate_ = 0;
+
+  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];
+    LayerComposition composition = layer.composition;
+
+    if (composition == kCompositionSDE) {
+      hwc_layer.hints |= HWC_HINT_CLEAR_FB;
+
+      if (use_metadata_refresh_rate_ && layer.frame_rate > metadata_refresh_rate_) {
+        metadata_refresh_rate_ = layer.frame_rate;
+      }
+    }
+
+    // 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);
+
+  return 0;
+}
+
+int HWCDisplay::CommitLayerStack(hwc_display_contents_1_t *content_list) {
+  if (!content_list || !content_list->numHwLayers) {
+    DLOGW("Invalid content list");
+    return -EINVAL;
+  }
+
+  int status = 0;
+
+  size_t num_hw_layers = content_list->numHwLayers;
+
+  DumpInputBuffers(content_list);
+
+  if (!flush_) {
+    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;
+      }
+
+      // if swapinterval property is set to 0 then close and reset the acquireFd
+      if (swap_interval_zero_ && hwc_layer.acquireFenceFd >= 0) {
+        close(hwc_layer.acquireFenceFd);
+        hwc_layer.acquireFenceFd = -1;
+      }
+      layer_buffer->acquire_fence_fd = hwc_layer.acquireFenceFd;
+    }
+
+    DisplayError error = display_intf_->Commit(&layer_stack_);
+    if (error != kErrorNone) {
+      DLOGE("Commit failed. Error = %d", error);
+
+      // To prevent surfaceflinger infinite wait, flush the previous frame during Commit() so that
+      // previous buffer and fences are released, and override the error.
+      flush_ = true;
+    }
+  }
+
+  return status;
+}
+
+int HWCDisplay::PostCommitLayerStack(hwc_display_contents_1_t *content_list) {
+  size_t num_hw_layers = content_list->numHwLayers;
+  int status = 0;
+
+  if (flush_) {
+    DisplayError error = display_intf_->Flush();
+    if (error != kErrorNone) {
+      DLOGE("Flush failed. Error = %d", error);
+    }
+  }
+
+  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 (!flush_) {
+      // if swapinterval property is set to 0 then do not update f/w release fences with driver
+      // values
+      if (swap_interval_zero_) {
+        hwc_layer.releaseFenceFd = -1;
+        close(layer_buffer->release_fence_fd);
+        layer_buffer->release_fence_fd = -1;
+      }
+
+      if (layer.composition != kCompositionGPU) {
+        hwc_layer.releaseFenceFd = layer_buffer->release_fence_fd;
+      }
+
+      // During animation on external/virtual display, SDM will use the cached
+      // framebuffer layer throughout animation and do not allow framework to do eglswapbuffer on
+      // framebuffer target. So graphics doesn't close the release fence fd of framebuffer target,
+      // Hence close the release fencefd of framebuffer target here.
+      if (layer.composition == kCompositionGPUTarget && layer_stack_cache_.animating) {
+        close(hwc_layer.releaseFenceFd);
+        hwc_layer.releaseFenceFd = -1;
+      }
+    }
+
+    if (hwc_layer.acquireFenceFd >= 0) {
+      close(hwc_layer.acquireFenceFd);
+      hwc_layer.acquireFenceFd = -1;
+    }
+  }
+
+
+  if (!flush_) {
+    layer_stack_cache_.animating = layer_stack_.flags.animating;
+
+    // if swapinterval property is set to 0 then close and reset the list retire fence
+    if (swap_interval_zero_) {
+      close(layer_stack_.retire_fence_fd);
+      layer_stack_.retire_fence_fd = -1;
+    }
+    content_list->retireFenceFd = layer_stack_.retire_fence_fd;
+
+    if (dump_frame_count_) {
+      dump_frame_count_--;
+      dump_frame_index_++;
+    }
+  }
+
+  flush_ = false;
+
+  return status;
+}
+
+
+bool HWCDisplay::NeedsFrameBufferRefresh(hwc_display_contents_1_t *content_list) {
+  uint32_t layer_count = layer_stack_.layer_count;
+
+  // Frame buffer needs to be refreshed for the following reasons:
+  // 1. Any layer is marked skip in the current layer stack.
+  // 2. Any layer is added/removed/layer properties changes in the current layer stack.
+  // 3. Any layer handle is changed and it is marked for GPU composition
+  // 4. Any layer's current composition is different from previous composition.
+  if (((layer_stack_cache_.layer_count != layer_count) || layer_stack_.flags.skip_present ||
+      layer_stack_.flags.geometry_changed) && !layer_stack_cache_.animating) {
+    return true;
+  }
+
+  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) &&
+        !layer_stack_cache_.animating) {
+      return true;
+    }
+  }
+
+  return false;
+}
+
+void HWCDisplay::CacheLayerStackInfo(hwc_display_contents_1_t *content_list) {
+  uint32_t layer_count = layer_stack_.layer_count;
+
+  for (uint32_t i = 0; i < layer_count; i++) {
+    Layer &layer = layer_stack_.layers[i];
+
+    if (layer.composition == kCompositionGPUTarget) {
+      continue;
+    }
+
+    layer_stack_cache_.layer_cache[i].handle = content_list->hwLayers[i].handle;
+    layer_stack_cache_.layer_cache[i].composition = layer.composition;
+  }
+
+  layer_stack_cache_.layer_count = layer_count;
+}
+
+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(const hwc_frect_t &source, LayerRect *target) {
+  target->left = floorf(source.left);
+  target->top = floorf(source.top);
+  target->right = ceilf(source.right);
+  target->bottom = ceilf(source.bottom);
+}
+
+void HWCDisplay::SetComposition(const int32_t &source, LayerComposition *target) {
+  switch (source) {
+  case HWC_FRAMEBUFFER_TARGET:  *target = kCompositionGPUTarget;  break;
+  default:                      *target = kCompositionSDE;        break;
+  }
+}
+
+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;
+  }
+}
+
+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 = kBlendingOpaque;          break;
+  }
+}
+
+void HWCDisplay::SetIdleTimeoutMs(uint32_t timeout_ms) {
+  if (display_intf_) {
+    display_intf_->SetIdleTimeoutMs(timeout_ms);
+  }
+}
+
+DisplayError HWCDisplay::SetMaxMixerStages(uint32_t max_mixer_stages) {
+  DisplayError error = kErrorNone;
+
+  if (display_intf_) {
+    error = display_intf_->SetMaxMixerStages(max_mixer_stages);
+  }
+
+  return error;
+}
+
+LayerBufferFormat HWCDisplay::GetSDMFormat(const int32_t &source, const int flags) {
+  LayerBufferFormat format = kFormatInvalid;
+  if (flags & private_handle_t::PRIV_FLAGS_UBWC_ALIGNED) {
+    switch (source) {
+    case HAL_PIXEL_FORMAT_RGBA_8888:          format = kFormatRGBA8888Ubwc;            break;
+    case HAL_PIXEL_FORMAT_RGBX_8888:          format = kFormatRGBX8888Ubwc;            break;
+    case HAL_PIXEL_FORMAT_RGB_565:            format = kFormatRGB565Ubwc;              break;
+    case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS:
+    case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS_UBWC:
+    case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:    format = kFormatYCbCr420SPVenusUbwc;     break;
+    default:
+      DLOGE("Unsupported format type for UBWC %d", source);
+      return kFormatInvalid;
+    }
+    return format;
+  }
+
+  switch (source) {
+  case HAL_PIXEL_FORMAT_RGBA_8888:                format = kFormatRGBA8888;                 break;
+  case HAL_PIXEL_FORMAT_RGBA_5551:                format = kFormatRGBA5551;                 break;
+  case HAL_PIXEL_FORMAT_RGBA_4444:                format = kFormatRGBA4444;                 break;
+  case HAL_PIXEL_FORMAT_BGRA_8888:                format = kFormatBGRA8888;                 break;
+  case HAL_PIXEL_FORMAT_RGBX_8888:                format = kFormatRGBX8888;                 break;
+  case HAL_PIXEL_FORMAT_BGRX_8888:                format = kFormatBGRX8888;                 break;
+  case HAL_PIXEL_FORMAT_RGB_888:                  format = kFormatRGB888;                   break;
+  case HAL_PIXEL_FORMAT_RGB_565:                  format = kFormatRGB565;                   break;
+  case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:
+  case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS:       format = kFormatYCbCr420SemiPlanarVenus;  break;
+  case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS_UBWC:  format = kFormatYCbCr420SPVenusUbwc;      break;
+  case HAL_PIXEL_FORMAT_YCrCb_420_SP:             format = kFormatYCrCb420SemiPlanar;       break;
+  case HAL_PIXEL_FORMAT_YCbCr_422_SP:             format = kFormatYCbCr422H2V1SemiPlanar;   break;
+  case HAL_PIXEL_FORMAT_YCbCr_422_I:              format = kFormatYCbCr422H2V1Packed;       break;
+  default:
+    DLOGW("Unsupported format type = %d", source);
+    return kFormatInvalid;
+  }
+
+  return format;
+}
+
+void HWCDisplay::DumpInputBuffers(hwc_display_contents_1_t *content_list) {
+  size_t num_hw_layers = content_list->numHwLayers;
+  char dir_path[PATH_MAX];
+
+  if (!dump_frame_count_ || flush_ || !dump_input_layers_) {
+    return;
+  }
+
+  snprintf(dir_path, sizeof(dir_path), "/data/misc/display/frame_dump_%s", GetDisplayString());
+
+  if (mkdir(dir_path, 0777) != 0 && errno != EEXIST) {
+    DLOGW("Failed to create %s directory errno = %d, desc = %s", dir_path, errno, strerror(errno));
+    return;
+  }
+
+  // if directory exists already, need to explicitly change the permission.
+  if (errno == EEXIST && chmod(dir_path, 0777) != 0) {
+    DLOGW("Failed to change permissions on %s directory", dir_path);
+    return;
+  }
+
+  for (uint32_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);
+
+    if (hwc_layer.acquireFenceFd >= 0) {
+      int error = sync_wait(hwc_layer.acquireFenceFd, 1000);
+      if (error < 0) {
+        DLOGW("sync_wait error errno = %d, desc = %s", errno, strerror(errno));
+        return;
+      }
+    }
+
+    if (pvt_handle && pvt_handle->base) {
+      char dump_file_name[PATH_MAX];
+      size_t result = 0;
+
+      snprintf(dump_file_name, sizeof(dump_file_name), "%s/input_layer%d_%dx%d_%s_frame%d.raw",
+               dir_path, i, pvt_handle->width, pvt_handle->height,
+               GetHALPixelFormatString(pvt_handle->format), dump_frame_index_);
+
+      FILE* fp = fopen(dump_file_name, "w+");
+      if (fp) {
+        result = fwrite(reinterpret_cast<void *>(pvt_handle->base), pvt_handle->size, 1, fp);
+        fclose(fp);
+      }
+
+      DLOGI("Frame Dump %s: is %s", dump_file_name, result ? "Successful" : "Failed");
+    }
+  }
+}
+
+const char *HWCDisplay::GetHALPixelFormatString(int format) {
+  switch (format) {
+  case HAL_PIXEL_FORMAT_RGBA_8888:
+    return "RGBA_8888";
+  case HAL_PIXEL_FORMAT_RGBX_8888:
+    return "RGBX_8888";
+  case HAL_PIXEL_FORMAT_RGB_888:
+    return "RGB_888";
+  case HAL_PIXEL_FORMAT_RGB_565:
+    return "RGB_565";
+  case HAL_PIXEL_FORMAT_BGRA_8888:
+    return "BGRA_8888";
+  case HAL_PIXEL_FORMAT_RGBA_5551:
+    return "RGBA_5551";
+  case HAL_PIXEL_FORMAT_RGBA_4444:
+    return "RGBA_4444";
+  case HAL_PIXEL_FORMAT_YV12:
+    return "YV12";
+  case HAL_PIXEL_FORMAT_YCbCr_422_SP:
+    return "YCbCr_422_SP_NV16";
+  case HAL_PIXEL_FORMAT_YCrCb_420_SP:
+    return "YCrCb_420_SP_NV21";
+  case HAL_PIXEL_FORMAT_YCbCr_422_I:
+    return "YCbCr_422_I_YUY2";
+  case HAL_PIXEL_FORMAT_YCrCb_422_I:
+    return "YCrCb_422_I_YVYU";
+  case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:
+    return "NV12_ENCODEABLE";
+  case HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED:
+    return "YCbCr_420_SP_TILED_TILE_4x2";
+  case HAL_PIXEL_FORMAT_YCbCr_420_SP:
+    return "YCbCr_420_SP";
+  case HAL_PIXEL_FORMAT_YCrCb_420_SP_ADRENO:
+    return "YCrCb_420_SP_ADRENO";
+  case HAL_PIXEL_FORMAT_YCrCb_422_SP:
+    return "YCrCb_422_SP";
+  case HAL_PIXEL_FORMAT_R_8:
+    return "R_8";
+  case HAL_PIXEL_FORMAT_RG_88:
+    return "RG_88";
+  case HAL_PIXEL_FORMAT_INTERLACE:
+    return "INTERLACE";
+  case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS:
+    return "YCbCr_420_SP_VENUS";
+  case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS_UBWC:
+    return "YCbCr_420_SP_VENUS_UBWC";
+  default:
+    return "Unknown pixel format";
+  }
+}
+
+const char *HWCDisplay::GetDisplayString() {
+  switch (type_) {
+  case kPrimary:
+    return "primary";
+  case kHDMI:
+    return "hdmi";
+  case kVirtual:
+    return "virtual";
+  default:
+    return "invalid";
+  }
+}
+
+int HWCDisplay::SetFrameBufferResolution(uint32_t x_pixels, uint32_t y_pixels) {
+  if (x_pixels <= 0 || y_pixels <= 0) {
+    DLOGV("Unsupported config: x_pixels=%d, y_pixels=%d", x_pixels, y_pixels);
+    return -EINVAL;
+  }
+
+  if (framebuffer_config_->x_pixels == x_pixels && framebuffer_config_->y_pixels == y_pixels) {
+    return 0;
+  }
+
+  DisplayConfigVariableInfo active_config;
+  int active_config_index = GetActiveConfig();
+  DisplayError error = display_intf_->GetConfig(active_config_index, &active_config);
+  if (error != kErrorNone) {
+    DLOGV("GetConfig variable info failed. Error = %d", error);
+    return -EINVAL;
+  }
+
+  if (active_config.x_pixels <= 0 || active_config.y_pixels <= 0) {
+    DLOGV("Invalid panel resolution (%dx%d)", active_config.x_pixels, active_config.y_pixels);
+    return -EINVAL;
+  }
+
+  // Create rects to represent the new source and destination crops
+  LayerRect crop = LayerRect(0, 0, FLOAT(x_pixels), FLOAT(y_pixels));
+  LayerRect dst = LayerRect(0, 0, FLOAT(active_config.x_pixels), FLOAT(active_config.y_pixels));
+  // Set rotate90 to false since this is taken care of during regular composition.
+  bool rotate90 = false;
+  error = display_intf_->IsScalingValid(crop, dst, rotate90);
+  if (error != kErrorNone) {
+    DLOGV("Unsupported resolution: (%dx%d)", x_pixels, y_pixels);
+    return -EINVAL;
+  }
+
+  uint32_t panel_width =
+          UINT32((FLOAT(active_config.x_pixels) * 25.4f) / FLOAT(active_config.x_dpi));
+  uint32_t panel_height =
+          UINT32((FLOAT(active_config.y_pixels) * 25.4f) / FLOAT(active_config.y_dpi));
+  framebuffer_config_->x_pixels = x_pixels;
+  framebuffer_config_->y_pixels = y_pixels;
+  framebuffer_config_->vsync_period_ns = active_config.vsync_period_ns;
+  framebuffer_config_->x_dpi =
+          (FLOAT(framebuffer_config_->x_pixels) * 25.4f) / FLOAT(panel_width);
+  framebuffer_config_->y_dpi =
+          (FLOAT(framebuffer_config_->y_pixels) * 25.4f) / FLOAT(panel_height);
+
+  DLOGI("New framebuffer resolution (%dx%d)", framebuffer_config_->x_pixels,
+        framebuffer_config_->y_pixels);
+
+  return 0;
+}
+
+void HWCDisplay::GetFrameBufferResolution(uint32_t *x_pixels, uint32_t *y_pixels) {
+  *x_pixels = framebuffer_config_->x_pixels;
+  *y_pixels = framebuffer_config_->y_pixels;
+}
+
+void HWCDisplay::ScaleDisplayFrame(hwc_rect_t *display_frame) {
+  if (!IsFrameBufferScaled()) {
+    return;
+  }
+
+  int active_config_index = GetActiveConfig();
+  DisplayConfigVariableInfo active_config;
+  DisplayError error = display_intf_->GetConfig(active_config_index, &active_config);
+  if (error != kErrorNone) {
+    DLOGE("GetConfig variable info failed. Error = %d", error);
+    return;
+  }
+
+  float custom_x_pixels = FLOAT(framebuffer_config_->x_pixels);
+  float custom_y_pixels = FLOAT(framebuffer_config_->y_pixels);
+  float active_x_pixels = FLOAT(active_config.x_pixels);
+  float active_y_pixels = FLOAT(active_config.y_pixels);
+  float x_pixels_ratio = active_x_pixels / custom_x_pixels;
+  float y_pixels_ratio = active_y_pixels / custom_y_pixels;
+  float layer_width = FLOAT(display_frame->right - display_frame->left);
+  float layer_height = FLOAT(display_frame->bottom - display_frame->top);
+
+  display_frame->left = INT(x_pixels_ratio * FLOAT(display_frame->left));
+  display_frame->top = INT(y_pixels_ratio * FLOAT(display_frame->top));
+  display_frame->right = INT(FLOAT(display_frame->left) + layer_width * x_pixels_ratio);
+  display_frame->bottom = INT(FLOAT(display_frame->top) + layer_height * y_pixels_ratio);
+}
+
+bool HWCDisplay::IsFrameBufferScaled() {
+  if (framebuffer_config_->x_pixels == 0 || framebuffer_config_->y_pixels == 0) {
+    return false;
+  }
+  uint32_t panel_x_pixels = 0;
+  uint32_t panel_y_pixels = 0;
+  GetPanelResolution(&panel_x_pixels, &panel_y_pixels);
+  return (framebuffer_config_->x_pixels != panel_x_pixels) ||
+          (framebuffer_config_->y_pixels != panel_y_pixels);
+}
+
+void HWCDisplay::GetPanelResolution(uint32_t *x_pixels, uint32_t *y_pixels) {
+  DisplayConfigVariableInfo active_config;
+  int active_config_index = GetActiveConfig();
+  DisplayError error = display_intf_->GetConfig(active_config_index, &active_config);
+  if (error != kErrorNone) {
+    DLOGE("GetConfig variable info failed. Error = %d", error);
+    return;
+  }
+  *x_pixels = active_config.x_pixels;
+  *y_pixels = active_config.y_pixels;
+}
+
+int HWCDisplay::SetDisplayStatus(uint32_t display_status) {
+  int status = 0;
+
+  switch (display_status) {
+  case kDisplayStatusResume:
+    display_paused_ = false;
+  case kDisplayStatusOnline:
+    status = SetPowerMode(HWC_POWER_MODE_NORMAL);
+    break;
+  case kDisplayStatusPause:
+    display_paused_ = true;
+  case kDisplayStatusOffline:
+    status = SetPowerMode(HWC_POWER_MODE_OFF);
+    break;
+  default:
+    DLOGW("Invalid display status %d", display_status);
+    return -EINVAL;
+  }
+
+  return status;
+}
+
+void HWCDisplay::MarkLayersForGPUBypass(hwc_display_contents_1_t *content_list) {
+  for (size_t i = 0 ; i < (content_list->numHwLayers - 1); i++) {
+    hwc_layer_1_t *layer = &content_list->hwLayers[i];
+    layer->compositionType = HWC_OVERLAY;
+  }
+}
+
+void HWCDisplay::CloseAcquireFences(hwc_display_contents_1_t *content_list) {
+  for (size_t i = 0; i < content_list->numHwLayers; i++) {
+    if (content_list->hwLayers[i].acquireFenceFd >= 0) {
+      close(content_list->hwLayers[i].acquireFenceFd);
+      content_list->hwLayers[i].acquireFenceFd = -1;
+    }
+  }
+}
+
+uint32_t HWCDisplay::RoundToStandardFPS(uint32_t fps) {
+  static const uint32_t standard_fps[4] = {30, 24, 48, 60};
+
+  int count = INT(sizeof(standard_fps) / sizeof(standard_fps[0]));
+  for (int i = 0; i < count; i++) {
+    if (abs(standard_fps[i] - fps) < 2) {
+      // Most likely used for video, the fps can fluctuate
+      // Ex: b/w 29 and 30 for 30 fps clip
+      return standard_fps[i];
+    }
+  }
+
+  return fps;
+}
+
+void HWCDisplay::ApplyScanAdjustment(hwc_rect_t *display_frame) {
+}
+
+}  // namespace sdm
+
diff --git a/sdm/libs/hwc/hwc_display.h b/sdm/libs/hwc/hwc_display.h
new file mode 100644
index 0000000..2df0928
--- /dev/null
+++ b/sdm/libs/hwc/hwc_display.h
@@ -0,0 +1,149 @@
+/*
+* 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:
+*    * Redistributions of source code must retain the above copyright notice, this list of
+*      conditions and the following disclaimer.
+*    * Redistributions in binary form must reproduce the above copyright notice, this list of
+*      conditions and the following disclaimer in the documentation and/or other materials provided
+*      with the distribution.
+*    * Neither the name of The Linux Foundation nor the names of its contributors may be used to
+*      endorse or promote products derived from this software without specific prior written
+*      permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef __HWC_DISPLAY_H__
+#define __HWC_DISPLAY_H__
+
+#include <hardware/hwcomposer.h>
+#include <core/core_interface.h>
+
+namespace sdm {
+
+class HWCDisplay : public DisplayEventHandler {
+ public:
+  virtual int Init();
+  virtual int Deinit();
+  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 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);
+  virtual int GetActiveConfig();
+  virtual int SetActiveConfig(int index);
+  virtual int SetActiveConfig(hwc_display_contents_1_t *content_list);
+  virtual void SetIdleTimeoutMs(uint32_t timeout_ms);
+  virtual void SetFrameDumpConfig(uint32_t count, uint32_t bit_mask_layer_type);
+  virtual DisplayError SetMaxMixerStages(uint32_t max_mixer_stages);
+  virtual uint32_t GetLastPowerMode();
+  virtual int SetFrameBufferResolution(uint32_t x_pixels, uint32_t y_pixels);
+  virtual void GetFrameBufferResolution(uint32_t *x_pixels, uint32_t *y_pixels);
+  virtual void GetPanelResolution(uint32_t *x_pixels, uint32_t *y_pixels);
+  virtual int SetDisplayStatus(uint32_t display_status);
+
+ protected:
+  enum DisplayStatus {
+    kDisplayStatusOffline = 0,
+    kDisplayStatusOnline,
+    kDisplayStatusPause,
+    kDisplayStatusResume,
+  };
+
+  // Maximum number of layers supported by display manager.
+  static const uint32_t kMaxLayerCount = 32;
+
+  // Structure to track memory allocation for layer stack (layers, rectangles) object.
+  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) { }
+  };
+
+  struct LayerCache {
+    buffer_handle_t handle;
+    LayerComposition composition;
+
+    LayerCache() : handle(NULL), composition(kCompositionGPU) { }
+  };
+
+  struct LayerStackCache {
+    LayerCache layer_cache[kMaxLayerCount];
+    uint32_t layer_count;
+    bool animating;
+
+    LayerStackCache() : layer_count(0), animating(false) { }
+  };
+
+  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);
+  virtual int PostCommitLayerStack(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);
+  int SetFormat(const int32_t &source, const int flags, LayerBufferFormat *target);
+  LayerBufferFormat GetSDMFormat(const int32_t &source, const int flags);
+  void DumpInputBuffers(hwc_display_contents_1_t *content_list);
+  const char *GetHALPixelFormatString(int format);
+  const char *GetDisplayString();
+  void ScaleDisplayFrame(hwc_rect_t *display_frame);
+  bool IsFrameBufferScaled();
+  void MarkLayersForGPUBypass(hwc_display_contents_1_t *content_list);
+  void CloseAcquireFences(hwc_display_contents_1_t *content_list);
+  uint32_t RoundToStandardFPS(uint32_t fps);
+  virtual void ApplyScanAdjustment(hwc_rect_t *display_frame);
+
+  enum {
+    INPUT_LAYER_DUMP,
+    OUTPUT_LAYER_DUMP,
+  };
+
+  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_;
+  bool flush_;
+  LayerBuffer *output_buffer_;
+  uint32_t dump_frame_count_;
+  uint32_t dump_frame_index_;
+  bool dump_input_layers_;
+  uint32_t last_power_mode_;
+  bool swap_interval_zero_;
+  DisplayConfigVariableInfo *framebuffer_config_;
+  bool display_paused_;
+  bool use_metadata_refresh_rate_;
+  uint32_t metadata_refresh_rate_;
+};
+
+}  // namespace sdm
+
+#endif  // __HWC_DISPLAY_H__
+
diff --git a/sdm/libs/hwc/hwc_display_external.cpp b/sdm/libs/hwc/hwc_display_external.cpp
new file mode 100644
index 0000000..52c64d1
--- /dev/null
+++ b/sdm/libs/hwc/hwc_display_external.cpp
@@ -0,0 +1,141 @@
+/*
+* 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:
+*     * 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 <cutils/properties.h>
+#include <utils/constants.h>
+
+#include "hwc_display_external.h"
+#include "hwc_debugger.h"
+
+#define __CLASS__ "HWCDisplayExternal"
+
+namespace sdm {
+
+HWCDisplayExternal::HWCDisplayExternal(CoreInterface *core_intf, hwc_procs_t const **hwc_procs)
+  : HWCDisplay(core_intf, hwc_procs, kHDMI, HWC_DISPLAY_EXTERNAL) {
+}
+
+int HWCDisplayExternal::Init() {
+  int status = 0;
+
+  status = HWCDisplay::Init();
+  if (status != 0) {
+    return status;
+  }
+
+  return status;
+}
+
+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;
+  }
+
+  status = HWCDisplay::PostCommitLayerStack(content_list);
+  if (status) {
+    return status;
+  }
+
+  return 0;
+}
+
+int HWCDisplayExternal::GetDisplayConfigs(uint32_t *configs, size_t *num_configs) {
+  uint32_t config_count = 0;
+  if (*num_configs <= 0) {
+    return -EINVAL;
+  }
+
+  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;
+}
+
+void HWCDisplayExternal::ApplyScanAdjustment(hwc_rect_t *display_frame) {
+  if (display_intf_->IsUnderscanSupported()) {
+    return;
+  }
+
+  // Read user defined width and height ratio
+  char property[PROPERTY_VALUE_MAX];
+  property_get("persist.sys.actionsafe.width", property, "0");
+  float width_ratio = FLOAT(atoi(property)) / 100.0f;
+  property_get("persist.sys.actionsafe.height", property, "0");
+  float height_ratio = FLOAT(atoi(property)) / 100.0f;
+
+  if (width_ratio == 0.0f ||  height_ratio == 0.0f) {
+    return;
+  }
+
+  uint32_t panel_width = 0;
+  uint32_t panel_height = 0;
+  GetPanelResolution(&panel_width, &panel_height);
+
+  if (panel_width == 0 || panel_height == 0) {
+    DLOGV("Invalid panel dimensions (%d, %d)", panel_width, panel_height);
+    return;
+  }
+
+  int x_offset = INT((FLOAT(panel_width) * width_ratio) / 2.0f);
+  int y_offset = INT((FLOAT(panel_height) * height_ratio) / 2.0f);
+
+  display_frame->left = display_frame->left + x_offset;
+  display_frame->top = display_frame->top + y_offset;
+  display_frame->right = display_frame->right - x_offset;
+  display_frame->bottom = display_frame->bottom - y_offset;
+}
+
+}  // namespace sdm
+
diff --git a/sdm/libs/hwc/hwc_display_external.h b/sdm/libs/hwc/hwc_display_external.h
new file mode 100644
index 0000000..6d3e229
--- /dev/null
+++ b/sdm/libs/hwc/hwc_display_external.h
@@ -0,0 +1,46 @@
+/*
+* 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.
+*/
+
+#ifndef __HWC_DISPLAY_EXTERNAL_H__
+#define __HWC_DISPLAY_EXTERNAL_H__
+
+#include "hwc_display.h"
+
+namespace sdm {
+
+class HWCDisplayExternal : public HWCDisplay {
+ public:
+  explicit HWCDisplayExternal(CoreInterface *core_intf, hwc_procs_t const **hwc_procs);
+  virtual int Init();
+  virtual int Prepare(hwc_display_contents_1_t *content_list);
+  virtual int Commit(hwc_display_contents_1_t *content_list);
+  virtual int GetDisplayConfigs(uint32_t *configs, size_t *num_configs);
+ private:
+  virtual void ApplyScanAdjustment(hwc_rect_t *display_frame);
+};
+
+}  // namespace sdm
+
+#endif  // __HWC_DISPLAY_EXTERNAL_H__
+
diff --git a/sdm/libs/hwc/hwc_display_primary.cpp b/sdm/libs/hwc/hwc_display_primary.cpp
new file mode 100644
index 0000000..53110ca
--- /dev/null
+++ b/sdm/libs/hwc/hwc_display_primary.cpp
@@ -0,0 +1,114 @@
+/*
+* 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:
+*     * 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_display_primary.h"
+#include "hwc_debugger.h"
+
+#define __CLASS__ "HWCDisplayPrimary"
+
+namespace sdm {
+
+HWCDisplayPrimary::HWCDisplayPrimary(CoreInterface *core_intf, hwc_procs_t const **hwc_procs)
+  : HWCDisplay(core_intf, hwc_procs, kPrimary, HWC_DISPLAY_PRIMARY) {
+}
+
+int HWCDisplayPrimary::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;
+  }
+
+  if (use_metadata_refresh_rate_) {
+    SetRefreshRate(metadata_refresh_rate_);
+  }
+
+  return 0;
+}
+
+int HWCDisplayPrimary::Commit(hwc_display_contents_1_t *content_list) {
+  int status = 0;
+
+  status = HWCDisplay::CommitLayerStack(content_list);
+  if (status) {
+    return status;
+  }
+
+  status = HWCDisplay::PostCommitLayerStack(content_list);
+  if (status) {
+    return status;
+  }
+
+  return 0;
+}
+
+DisplayError HWCDisplayPrimary::SetDisplayMode(uint32_t mode) {
+  DisplayError error = kErrorNone;
+
+  if (display_intf_) {
+    error = display_intf_->SetDisplayMode(mode);
+  }
+
+  return error;
+}
+
+int HWCDisplayPrimary::SetActiveConfig(uint32_t index) {
+  DisplayError error = kErrorNone;
+
+  if (display_intf_) {
+    error = display_intf_->SetActiveConfig(index);
+  }
+
+  return error;
+}
+
+int HWCDisplayPrimary::SetRefreshRate(uint32_t refresh_rate) {
+  DisplayError error = kErrorNone;
+
+  if (display_intf_) {
+    error = display_intf_->SetRefreshRate(refresh_rate);
+  }
+
+  return error;
+}
+
+void HWCDisplayPrimary::SetMetaDataRefreshRateFlag(bool enable) {
+  use_metadata_refresh_rate_ = enable;
+}
+
+}  // namespace sdm
+
diff --git a/sdm/libs/hwc/hwc_display_primary.h b/sdm/libs/hwc/hwc_display_primary.h
new file mode 100644
index 0000000..e862508
--- /dev/null
+++ b/sdm/libs/hwc/hwc_display_primary.h
@@ -0,0 +1,46 @@
+/*
+* 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.
+*/
+
+#ifndef __HWC_DISPLAY_PRIMARY_H__
+#define __HWC_DISPLAY_PRIMARY_H__
+
+#include "hwc_display.h"
+
+namespace sdm {
+
+class HWCDisplayPrimary : public HWCDisplay {
+ public:
+  explicit HWCDisplayPrimary(CoreInterface *core_intf, hwc_procs_t const **hwc_procs);
+  virtual int Prepare(hwc_display_contents_1_t *content_list);
+  virtual int Commit(hwc_display_contents_1_t *content_list);
+  virtual DisplayError SetDisplayMode(uint32_t mode);
+  virtual int SetActiveConfig(uint32_t index);
+  virtual int SetRefreshRate(uint32_t refresh_rate);
+  virtual void SetMetaDataRefreshRateFlag(bool enable);
+};
+
+}  // namespace sdm
+
+#endif  // __HWC_DISPLAY_PRIMARY_H__
+
diff --git a/sdm/libs/hwc/hwc_display_virtual.cpp b/sdm/libs/hwc/hwc_display_virtual.cpp
new file mode 100644
index 0000000..d36a171
--- /dev/null
+++ b/sdm/libs/hwc/hwc_display_virtual.cpp
@@ -0,0 +1,278 @@
+/*
+* 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:
+*     * 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 <sync/sync.h>
+
+#include "hwc_display_virtual.h"
+#include "hwc_debugger.h"
+
+#define __CLASS__ "HWCDisplayVirtual"
+
+namespace sdm {
+
+HWCDisplayVirtual::HWCDisplayVirtual(CoreInterface *core_intf, hwc_procs_t const **hwc_procs)
+  : HWCDisplay(core_intf, hwc_procs, kVirtual, HWC_DISPLAY_VIRTUAL),
+    dump_output_layer_(false) {
+}
+
+int HWCDisplayVirtual::Init() {
+  int status = 0;
+
+  output_buffer_ = new LayerBuffer();
+  if (!output_buffer_) {
+    return -ENOMEM;
+  }
+
+  return HWCDisplay::Init();
+}
+
+int HWCDisplayVirtual::Deinit() {
+  int status = 0;
+
+  status = HWCDisplay::Deinit();
+  if (status) {
+    return status;
+  }
+
+  if (output_buffer_) {
+    delete output_buffer_;
+  }
+
+  return status;
+}
+
+int HWCDisplayVirtual::Prepare(hwc_display_contents_1_t *content_list) {
+  int status = 0;
+  if (display_paused_) {
+    MarkLayersForGPUBypass(content_list);
+    return status;
+  }
+
+  status = AllocateLayerStack(content_list);
+  if (status) {
+    return status;
+  }
+
+  status = SetOutputBuffer(content_list);
+  if (status) {
+    return status;
+  }
+
+  status = PrepareLayerStack(content_list);
+  if (status) {
+    return status;
+  }
+
+  return 0;
+}
+
+int HWCDisplayVirtual::Commit(hwc_display_contents_1_t *content_list) {
+  int status = 0;
+  if (display_paused_) {
+    if (content_list->outbufAcquireFenceFd >= 0) {
+      // If we do not handle the frame set retireFenceFd to outbufAcquireFenceFd,
+      // which will make sure the framework waits on it and closes it.
+      content_list->retireFenceFd = dup(content_list->outbufAcquireFenceFd);
+      close(content_list->outbufAcquireFenceFd);
+      content_list->outbufAcquireFenceFd = -1;
+    }
+    CloseAcquireFences(content_list);
+
+    DisplayError error = display_intf_->Flush();
+    if (error != kErrorNone) {
+      DLOGE("Flush failed. Error = %d", error);
+    }
+    return status;
+  }
+
+  status = HWCDisplay::CommitLayerStack(content_list);
+  if (status) {
+    return status;
+  }
+
+  DumpOutputBuffer(content_list);
+
+  status = HWCDisplay::PostCommitLayerStack(content_list);
+  if (status) {
+    return status;
+  }
+
+  if (content_list->outbufAcquireFenceFd >= 0) {
+    close(content_list->outbufAcquireFenceFd);
+    content_list->outbufAcquireFenceFd = -1;
+  }
+
+  return 0;
+}
+
+int HWCDisplayVirtual::SetActiveConfig(hwc_display_contents_1_t *content_list) {
+  const private_handle_t *output_handle =
+        static_cast<const private_handle_t *>(content_list->outbuf);
+  DisplayError error = kErrorNone;
+  int status = 0;
+
+  if (output_handle) {
+    LayerBufferFormat format = GetSDMFormat(output_handle->format, output_handle->flags);
+    if (format == kFormatInvalid) {
+      return -EINVAL;
+    }
+
+    int active_width = GetWidth(output_handle);
+    int active_height = GetHeight(output_handle);
+
+    if ((active_width != INT(output_buffer_->width)) ||
+        (active_height!= INT(output_buffer_->height)) ||
+        (format != output_buffer_->format)) {
+      DisplayConfigVariableInfo variable_info;
+      variable_info.x_pixels = active_width;
+      variable_info.y_pixels = active_height;
+      // TODO(user): Need to get the framerate of primary display and update it.
+      variable_info.fps = 60;
+
+      error = display_intf_->SetActiveConfig(&variable_info);
+      if (error != kErrorNone) {
+        return -EINVAL;
+      }
+
+      status = SetOutputBuffer(content_list);
+      if (status) {
+        return status;
+      }
+    }
+  }
+
+  return 0;
+}
+
+int HWCDisplayVirtual::SetOutputBuffer(hwc_display_contents_1_t *content_list) {
+  int status = 0;
+
+  const private_handle_t *output_handle =
+        static_cast<const private_handle_t *>(content_list->outbuf);
+
+  // Fill output buffer parameters (width, height, format, plane information, fence)
+  output_buffer_->acquire_fence_fd = content_list->outbufAcquireFenceFd;
+
+  if (output_handle) {
+    output_buffer_->format = GetSDMFormat(output_handle->format, output_handle->flags);
+    if (output_buffer_->format == kFormatInvalid) {
+      return -EINVAL;
+    }
+
+    output_buffer_->width = GetWidth(output_handle);
+    output_buffer_->height = GetHeight(output_handle);
+    output_buffer_->flags.secure = 0;
+    output_buffer_->flags.video = 0;
+
+    // ToDo: Need to extend for non-RGB formats
+    output_buffer_->planes[0].fd = output_handle->fd;
+    output_buffer_->planes[0].offset = output_handle->offset;
+    output_buffer_->planes[0].stride = output_handle->width;
+  }
+
+  layer_stack_.output_buffer = output_buffer_;
+
+  return status;
+}
+
+void HWCDisplayVirtual::DumpOutputBuffer(hwc_display_contents_1_t *content_list) {
+  const private_handle_t *output_handle = (const private_handle_t *)(content_list->outbuf);
+  char dir_path[PATH_MAX];
+
+  if (!dump_frame_count_ || flush_ || !dump_output_layer_) {
+    return;
+  }
+
+  snprintf(dir_path, sizeof(dir_path), "/data/misc/display/frame_dump_%s", GetDisplayString());
+
+  if (mkdir(dir_path, 777) != 0 && errno != EEXIST) {
+    DLOGW("Failed to create %s directory errno = %d, desc = %s", dir_path, errno, strerror(errno));
+    return;
+  }
+
+  // if directory exists already, need to explicitly change the permission.
+  if (errno == EEXIST && chmod(dir_path, 0777) != 0) {
+    DLOGW("Failed to change permissions on %s directory", dir_path);
+    return;
+  }
+
+  if (output_handle && output_handle->base) {
+    char dump_file_name[PATH_MAX];
+    size_t result = 0;
+
+    if (content_list->outbufAcquireFenceFd >= 0) {
+      int error = sync_wait(content_list->outbufAcquireFenceFd, 1000);
+      if (error < 0) {
+        DLOGW("sync_wait error errno = %d, desc = %s", errno,  strerror(errno));
+        return;
+      }
+    }
+
+    snprintf(dump_file_name, sizeof(dump_file_name), "%s/output_layer_%dx%d_%s_frame%d.raw",
+             dir_path, output_handle->width, output_handle->height,
+             GetHALPixelFormatString(output_handle->format), dump_frame_index_);
+
+    FILE* fp = fopen(dump_file_name, "w+");
+    if (fp) {
+      result = fwrite(reinterpret_cast<void *>(output_handle->base), output_handle->size, 1, fp);
+      fclose(fp);
+    }
+
+    DLOGI("Frame Dump of %s is %s", dump_file_name, result ? "Successful" : "Failed");
+  }
+}
+
+void HWCDisplayVirtual::SetFrameDumpConfig(uint32_t count, uint32_t bit_mask_layer_type) {
+  HWCDisplay::SetFrameDumpConfig(count, bit_mask_layer_type);
+  dump_output_layer_ = ((bit_mask_layer_type & (1 << OUTPUT_LAYER_DUMP)) != 0);
+
+  DLOGI("output_layer_dump_enable %d", dump_output_layer_);
+}
+
+int HWCDisplayVirtual::GetWidth(const private_handle_t* handle) {
+  MetaData_t *metadata = reinterpret_cast<MetaData_t *>(handle->base_metadata);
+  if (metadata && metadata->operation & UPDATE_BUFFER_GEOMETRY) {
+    return metadata->bufferDim.sliceWidth;
+  }
+
+  return handle->width;
+}
+
+int HWCDisplayVirtual::GetHeight(const private_handle_t* handle) {
+  MetaData_t *metadata = reinterpret_cast<MetaData_t *>(handle->base_metadata);
+  if (metadata && metadata->operation & UPDATE_BUFFER_GEOMETRY) {
+    return metadata->bufferDim.sliceHeight;
+  }
+
+  return handle->height;
+}
+
+}  // namespace sdm
+
diff --git a/sdm/libs/hwc/hwc_display_virtual.h b/sdm/libs/hwc/hwc_display_virtual.h
new file mode 100644
index 0000000..74285d7
--- /dev/null
+++ b/sdm/libs/hwc/hwc_display_virtual.h
@@ -0,0 +1,56 @@
+/*
+* 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.
+*/
+
+#ifndef __HWC_DISPLAY_VIRTUAL_H__
+#define __HWC_DISPLAY_VIRTUAL_H__
+
+#include <qdMetaData.h>
+#include <gralloc_priv.h>
+#include "hwc_display.h"
+
+namespace sdm {
+
+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 SetActiveConfig(hwc_display_contents_1_t *content_list);
+  virtual void SetFrameDumpConfig(uint32_t count, uint32_t bit_mask_layer_type);
+
+ private:
+  int SetOutputBuffer(hwc_display_contents_1_t *content_list);
+  void DumpOutputBuffer(hwc_display_contents_1_t *content_list);
+  int GetWidth(const private_handle_t* handle);
+  int GetHeight(const private_handle_t* handle);
+
+  bool dump_output_layer_;
+};
+
+}  // namespace sdm
+
+#endif  // __HWC_DISPLAY_VIRTUAL_H__
+
diff --git a/sdm/libs/hwc/hwc_session.cpp b/sdm/libs/hwc/hwc_session.cpp
new file mode 100644
index 0000000..e5ffda9
--- /dev/null
+++ b/sdm/libs/hwc/hwc_session.cpp
@@ -0,0 +1,1004 @@
+/*
+* 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:
+*     * 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 <core/dump_interface.h>
+#include <core/buffer_allocator.h>
+#include <utils/constants.h>
+#include <utils/String16.h>
+#include <cutils/properties.h>
+#include <hardware_legacy/uevent.h>
+#include <sys/resource.h>
+#include <sys/prctl.h>
+#include <binder/Parcel.h>
+#include <QService.h>
+#include <gr.h>
+#include <gralloc_priv.h>
+#include <display_config.h>
+
+#include "hwc_buffer_allocator.h"
+#include "hwc_buffer_sync_handler.h"
+#include "hwc_session.h"
+#include "hwc_debugger.h"
+
+#define __CLASS__ "HWCSession"
+
+#define HWC_UEVENT_SWITCH_HDMI "change@/devices/virtual/switch/hdmi"
+#define HWC_UEVENT_GRAPHICS_FB0 "change@/devices/virtual/graphics/fb0"
+
+static sdm::HWCSession::HWCModuleMethods g_hwc_module_methods;
+
+hwc_module_t HAL_MODULE_INFO_SYM = {
+  common: {
+    tag: HARDWARE_MODULE_TAG,
+    version_major: 2,
+    version_minor: 0,
+    id: HWC_HARDWARE_MODULE_ID,
+    name: "QTI Hardware Composer Module",
+    author: "CodeAurora Forum",
+    methods: &g_hwc_module_methods,
+    dso: 0,
+    reserved: {0},
+  }
+};
+
+namespace sdm {
+
+Locker HWCSession::locker_;
+bool HWCSession::reset_panel_ = false;
+
+HWCSession::HWCSession(const hw_module_t *module) : core_intf_(NULL), hwc_procs_(NULL),
+            display_primary_(NULL), display_external_(NULL), display_virtual_(NULL),
+            uevent_thread_exit_(false), uevent_thread_name_("HWC_UeventThread") {
+  hwc_composer_device_1_t::common.tag = HARDWARE_DEVICE_TAG;
+  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::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() {
+  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(android::sp<qClient::IQClient>(this));
+  } else {
+    DLOGE("Failed to acquire %s", qservice_name);
+    return -EINVAL;
+  }
+
+  buffer_allocator_ = new HWCBufferAllocator();
+  if (buffer_allocator_ == NULL) {
+    DLOGE("Display core initialization failed due to no memory");
+    return -ENOMEM;
+  }
+
+  buffer_sync_handler_ = new HWCBufferSyncHandler();
+  if (buffer_sync_handler_ == NULL) {
+    DLOGE("Display core initialization failed due to no memory");
+    return -ENOMEM;
+  }
+
+  DisplayError error = CoreInterface::CreateCore(this, HWCDebugHandler::Get(), buffer_allocator_,
+                                                 buffer_sync_handler_, &core_intf_);
+  if (error != kErrorNone) {
+    DLOGE("Display core initialization failed. Error = %d", error);
+    return -EINVAL;
+  }
+
+  // Create and power on primary display
+  display_primary_ = new HWCDisplayPrimary(core_intf_, &hwc_procs_);
+  if (!display_primary_) {
+    CoreInterface::DestroyCore();
+    return -ENOMEM;
+  }
+
+  status = display_primary_->Init();
+  if (status) {
+    CoreInterface::DestroyCore();
+    delete display_primary_;
+    return status;
+  }
+
+  status = display_primary_->SetPowerMode(HWC_POWER_MODE_NORMAL);
+  if (status) {
+    display_primary_->Deinit();
+    delete display_primary_;
+    CoreInterface::DestroyCore();
+    return status;
+  }
+
+  if (pthread_create(&uevent_thread_, NULL, &HWCUeventThread, this) < 0) {
+    DLOGE("Failed to start = %s, error = %s", uevent_thread_name_);
+    display_primary_->Deinit();
+    delete display_primary_;
+    CoreInterface::DestroyCore();
+    return -errno;
+  }
+
+  SetFrameBufferResolution(HWC_DISPLAY_PRIMARY, NULL);
+
+  return 0;
+}
+
+int HWCSession::Deinit() {
+  display_primary_->SetPowerMode(HWC_POWER_MODE_OFF);
+  display_primary_->Deinit();
+  delete display_primary_;
+  uevent_thread_exit_ = true;
+  pthread_join(uevent_thread_, NULL);
+
+  DisplayError error = CoreInterface::DestroyCore();
+  if (error != kErrorNone) {
+    DLOGE("Display core de-initialization failed. Error = %d", error);
+  }
+
+  return 0;
+}
+
+int HWCSession::Open(const hw_module_t *module, const char *name, hw_device_t **device) {
+  if (!module || !name || !device) {
+    DLOGE("Invalid parameters.");
+    return -EINVAL;
+  }
+
+  if (!strcmp(name, HWC_HARDWARE_COMPOSER)) {
+    HWCSession *hwc_session = new HWCSession(module);
+    if (!hwc_session) {
+      return -ENOMEM;
+    }
+
+    int status = hwc_session->Init();
+    if (status != 0) {
+      delete hwc_session;
+      return status;
+    }
+
+    hwc_composer_device_1_t *composer_device = hwc_session;
+    *device = reinterpret_cast<hw_device_t *>(composer_device);
+  }
+
+  return 0;
+}
+
+int HWCSession::Close(hw_device_t *device) {
+  if (!device) {
+    return -EINVAL;
+  }
+
+  hwc_composer_device_1_t *composer_device = reinterpret_cast<hwc_composer_device_1_t *>(device);
+  HWCSession *hwc_session = static_cast<HWCSession *>(composer_device);
+
+  hwc_session->Deinit();
+  delete hwc_session;
+
+  return 0;
+}
+
+int HWCSession::Prepare(hwc_composer_device_1 *device, size_t num_displays,
+                        hwc_display_contents_1_t **displays) {
+  DTRACE_SCOPED();
+
+  SEQUENCE_ENTRY_SCOPE_LOCK(locker_);
+
+  if (!device || !displays) {
+    return -EINVAL;
+  }
+
+  HWCSession *hwc_session = static_cast<HWCSession *>(device);
+
+  if (reset_panel_) {
+    DLOGW("panel is in bad state, resetting the panel");
+    hwc_session->ResetPanel();
+  }
+
+  for (ssize_t i = (num_displays-1); i >= 0; i--) {
+    hwc_display_contents_1_t *content_list = displays[i];
+
+    switch (i) {
+    case HWC_DISPLAY_PRIMARY:
+      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:
+      if (hwc_session->display_external_) {
+        break;
+      }
+      if (hwc_session->ValidateContentList(content_list)) {
+        hwc_session->CreateVirtualDisplay(content_list);
+      } else {
+        hwc_session->DestroyVirtualDisplay();
+      }
+
+      if (hwc_session->display_virtual_) {
+        hwc_session->display_virtual_->Prepare(content_list);
+      }
+      break;
+    default:
+      break;
+    }
+  }
+
+  // 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) {
+  DTRACE_SCOPED();
+
+  SEQUENCE_EXIT_SCOPE_LOCK(locker_);
+
+  if (!device || !displays) {
+    return -EINVAL;
+  }
+
+  HWCSession *hwc_session = static_cast<HWCSession *>(device);
+
+  for (size_t i = 0; i < num_displays; i++) {
+    hwc_display_contents_1_t *content_list = displays[i];
+
+    switch (i) {
+    case HWC_DISPLAY_PRIMARY:
+      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:
+      if (hwc_session->display_external_) {
+        if (content_list) {
+          for (size_t i = 0; i < content_list->numHwLayers; i++) {
+            if (content_list->hwLayers[i].acquireFenceFd >= 0) {
+              close(content_list->hwLayers[i].acquireFenceFd);
+              content_list->hwLayers[i].acquireFenceFd = -1;
+            }
+          }
+          if (content_list->outbufAcquireFenceFd >= 0) {
+            close(content_list->outbufAcquireFenceFd);
+            content_list->outbufAcquireFenceFd = -1;
+          }
+          content_list->retireFenceFd = -1;
+        }
+      }
+      if (hwc_session->display_virtual_) {
+        hwc_session->display_virtual_->Commit(content_list);
+      }
+      break;
+    default:
+      break;
+    }
+  }
+
+  // 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) {
+  SEQUENCE_WAIT_SCOPE_LOCK(locker_);
+
+  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_->EventControl(event, enable);
+    break;
+  case HWC_DISPLAY_EXTERNAL:
+    if (hwc_session->display_external_) {
+      status = hwc_session->display_external_->EventControl(event, enable);
+    }
+    break;
+  case HWC_DISPLAY_VIRTUAL:
+    break;
+  default:
+    status = -EINVAL;
+  }
+
+  return status;
+}
+
+int HWCSession::SetPowerMode(hwc_composer_device_1 *device, int disp, int mode) {
+  SEQUENCE_WAIT_SCOPE_LOCK(locker_);
+
+  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_->SetPowerMode(mode);
+  // Set the power mode for virtual display while setting power mode for primary, as surfaceflinger
+  // does not invoke SetPowerMode() for virtual display.
+  case HWC_DISPLAY_VIRTUAL:
+    if (hwc_session->display_virtual_) {
+      status = hwc_session->display_virtual_->SetPowerMode(mode);
+    }
+    break;
+  case HWC_DISPLAY_EXTERNAL:
+    if (hwc_session->display_external_) {
+      status = hwc_session->display_external_->SetPowerMode(mode);
+    }
+    break;
+  default:
+    status = -EINVAL;
+  }
+
+  return status;
+}
+
+int HWCSession::Query(hwc_composer_device_1 *device, int param, int *value) {
+  SEQUENCE_WAIT_SCOPE_LOCK(locker_);
+
+  if (!device || !value) {
+    return -EINVAL;
+  }
+
+  return -EINVAL;
+}
+
+void HWCSession::RegisterProcs(hwc_composer_device_1 *device, hwc_procs_t const *procs) {
+  if (!device || !procs) {
+    return;
+  }
+
+  HWCSession *hwc_session = static_cast<HWCSession *>(device);
+  hwc_session->hwc_procs_ = procs;
+}
+
+void HWCSession::Dump(hwc_composer_device_1 *device, char *buffer, int length) {
+  SEQUENCE_WAIT_SCOPE_LOCK(locker_);
+
+  if (!device || !buffer || !length) {
+    return;
+  }
+
+  DumpInterface::GetDump(buffer, length);
+}
+
+int HWCSession::GetDisplayConfigs(hwc_composer_device_1 *device, int disp, uint32_t *configs,
+                                  size_t *num_configs) {
+  SEQUENCE_WAIT_SCOPE_LOCK(locker_);
+
+  if (!device || !configs || !num_configs) {
+    return -EINVAL;
+  }
+
+  HWCSession *hwc_session = static_cast<HWCSession *>(device);
+  int status = -EINVAL;
+
+  switch (disp) {
+  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;
+  case HWC_DISPLAY_VIRTUAL:
+    if (hwc_session->display_virtual_) {
+      status = hwc_session->display_virtual_->GetDisplayConfigs(configs, num_configs);
+    }
+    break;
+  default:
+    status = -EINVAL;
+  }
+
+  return status;
+}
+
+int HWCSession::GetDisplayAttributes(hwc_composer_device_1 *device, int disp, uint32_t config,
+                                     const uint32_t *attributes, int32_t *values) {
+  SEQUENCE_WAIT_SCOPE_LOCK(locker_);
+
+  if (!device || !attributes || !values) {
+    return -EINVAL;
+  }
+
+  HWCSession *hwc_session = static_cast<HWCSession *>(device);
+  int status = -EINVAL;
+
+  switch (disp) {
+  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;
+  case HWC_DISPLAY_VIRTUAL:
+    if (hwc_session->display_virtual_) {
+      status = hwc_session->display_virtual_->GetDisplayAttributes(config, attributes, values);
+    }
+    break;
+  default:
+    status = -EINVAL;
+  }
+
+  return status;
+}
+
+int HWCSession::GetActiveConfig(hwc_composer_device_1 *device, int disp) {
+  SEQUENCE_WAIT_SCOPE_LOCK(locker_);
+
+  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;
+  case HWC_DISPLAY_VIRTUAL:
+    if (hwc_session->display_virtual_) {
+      active_config = hwc_session->display_virtual_->GetActiveConfig();
+    }
+    break;
+  default:
+    active_config = -1;
+  }
+
+  return active_config;
+}
+
+int HWCSession::SetActiveConfig(hwc_composer_device_1 *device, int disp, int index) {
+  SEQUENCE_WAIT_SCOPE_LOCK(locker_);
+
+  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;
+  case HWC_DISPLAY_VIRTUAL:
+    break;
+  default:
+    status = -EINVAL;
+  }
+
+  return status;
+}
+
+bool HWCSession::ValidateContentList(hwc_display_contents_1_t *content_list) {
+  return (content_list && content_list->numHwLayers > 0 && content_list->outbuf);
+}
+
+int HWCSession::CreateVirtualDisplay(hwc_display_contents_1_t *content_list) {
+  int status = 0;
+
+  if (!display_virtual_) {
+    // Create virtual display device
+    display_virtual_ = new HWCDisplayVirtual(core_intf_, &hwc_procs_);
+    if (!display_virtual_) {
+      // This is not catastrophic. Leave a warning message for now.
+      DLOGW("Virtual Display creation failed");
+      return -ENOMEM;
+    }
+
+    status = display_virtual_->Init();
+    if (status) {
+      goto CleanupOnError;
+    }
+
+    status = display_virtual_->SetPowerMode(HWC_POWER_MODE_NORMAL);
+    if (status) {
+      goto CleanupOnError;
+    }
+  }
+
+  if (display_virtual_) {
+    SetFrameBufferResolution(HWC_DISPLAY_VIRTUAL, content_list);
+    status = display_virtual_->SetActiveConfig(content_list);
+  }
+
+  return status;
+
+CleanupOnError:
+  return DestroyVirtualDisplay();
+}
+
+int HWCSession::DestroyVirtualDisplay() {
+  int status = 0;
+
+  if (display_virtual_) {
+    status = display_virtual_->Deinit();
+    if (!status) {
+      delete display_virtual_;
+      display_virtual_ = NULL;
+      // Signal the HotPlug thread to continue with the external display connection
+      locker_.Signal();
+    }
+  }
+
+  return status;
+}
+
+DisplayError HWCSession::Hotplug(const CoreEventHotplug &hotplug) {
+  return kErrorNone;
+}
+
+android::status_t HWCSession::notifyCallback(uint32_t command, const android::Parcel *input_parcel,
+                                             android::Parcel */*output_parcel*/) {
+  SEQUENCE_WAIT_SCOPE_LOCK(locker_);
+
+  android::status_t status = 0;
+
+  switch (command) {
+  case qService::IQService::DYNAMIC_DEBUG:
+    DynamicDebug(input_parcel);
+    break;
+
+  case qService::IQService::SCREEN_REFRESH:
+    hwc_procs_->invalidate(hwc_procs_);
+    break;
+
+  case qService::IQService::SET_IDLE_TIMEOUT:
+    if (display_primary_) {
+      uint32_t timeout = UINT32(input_parcel->readInt32());
+      display_primary_->SetIdleTimeoutMs(timeout);
+    }
+    break;
+
+  case qService::IQService::SET_FRAME_DUMP_CONFIG:
+    SetFrameDumpConfig(input_parcel);
+    break;
+
+  case qService::IQService::SET_MAX_PIPES_PER_MIXER:
+    status = SetMaxMixerStages(input_parcel);
+    break;
+
+  case qService::IQService::SET_DISPLAY_MODE:
+    status = SetDisplayMode(input_parcel);
+    break;
+  case qService::IQService::SET_SECONDARY_DISPLAY_STATUS:
+    status = SetSecondaryDisplayStatus(input_parcel);
+    break;
+
+  case qService::IQService::CONFIGURE_DYN_REFRESH_RATE:
+    status = ConfigureRefreshRate(input_parcel);
+    break;
+
+  default:
+    DLOGW("QService command = %d is not supported", command);
+    return -EINVAL;
+  }
+
+  return status;
+}
+
+android::status_t HWCSession::SetSecondaryDisplayStatus(const android::Parcel *input_parcel) {
+  uint32_t display_id = UINT32(input_parcel->readInt32());
+  uint32_t display_status = UINT32(input_parcel->readInt32());
+  HWCDisplay *display = NULL;
+
+  DLOGI("Display %d Status %d", display_id, display_status);
+  switch (display_id) {
+  case HWC_DISPLAY_EXTERNAL:
+    display = display_external_;
+    break;
+  case HWC_DISPLAY_VIRTUAL:
+    display = display_virtual_;
+    break;
+  default:
+    DLOGW("Not supported for display %d", display_id);
+    return -EINVAL;
+  }
+
+  return display->SetDisplayStatus(display_status);
+}
+
+android::status_t HWCSession::ConfigureRefreshRate(const android::Parcel *input_parcel) {
+  uint32_t operation = UINT32(input_parcel->readInt32());
+
+  switch (operation) {
+  case qdutils::DISABLE_METADATA_DYN_REFRESH_RATE:
+    display_primary_->SetMetaDataRefreshRateFlag(false);
+    break;
+
+  case qdutils::ENABLE_METADATA_DYN_REFRESH_RATE:
+    display_primary_->SetMetaDataRefreshRateFlag(true);
+    break;
+
+  case qdutils::SET_BINDER_DYN_REFRESH_RATE:
+  {
+    uint32_t refresh_rate = UINT32(input_parcel->readInt32());
+
+    display_primary_->SetRefreshRate(refresh_rate);
+    break;
+  }
+
+  default:
+    DLOGW("Invalid operation %d", operation);
+    return -EINVAL;
+  }
+
+  return 0;
+}
+
+android::status_t HWCSession::SetDisplayMode(const android::Parcel *input_parcel) {
+  DisplayError error = kErrorNone;
+  uint32_t mode = UINT32(input_parcel->readInt32());
+
+  error = display_primary_->SetDisplayMode(mode);
+  if (error != kErrorNone) {
+    return -EINVAL;
+  }
+
+  return 0;
+}
+
+android::status_t HWCSession::SetMaxMixerStages(const android::Parcel *input_parcel) {
+  DisplayError error = kErrorNone;
+  uint32_t bit_mask_display_type = UINT32(input_parcel->readInt32());
+  uint32_t max_mixer_stages = UINT32(input_parcel->readInt32());
+
+  if (IS_BIT_SET(bit_mask_display_type, HWC_DISPLAY_PRIMARY)) {
+    if (display_primary_) {
+      error = display_primary_->SetMaxMixerStages(max_mixer_stages);
+      if (error != kErrorNone) {
+        return -EINVAL;
+      }
+    }
+  }
+
+  if (IS_BIT_SET(bit_mask_display_type, HWC_DISPLAY_EXTERNAL)) {
+    if (display_external_) {
+      error = display_external_->SetMaxMixerStages(max_mixer_stages);
+      if (error != kErrorNone) {
+        return -EINVAL;
+      }
+    }
+  }
+
+  if (IS_BIT_SET(bit_mask_display_type, HWC_DISPLAY_VIRTUAL)) {
+    if (display_virtual_) {
+      error = display_virtual_->SetMaxMixerStages(max_mixer_stages);
+      if (error != kErrorNone) {
+        return -EINVAL;
+      }
+    }
+  }
+
+  return 0;
+}
+
+void HWCSession::SetFrameDumpConfig(const android::Parcel *input_parcel) {
+  uint32_t frame_dump_count = UINT32(input_parcel->readInt32());
+  uint32_t bit_mask_display_type = UINT32(input_parcel->readInt32());
+  uint32_t bit_mask_layer_type = UINT32(input_parcel->readInt32());
+
+  if (IS_BIT_SET(bit_mask_display_type, HWC_DISPLAY_PRIMARY)) {
+    if (display_primary_) {
+      display_primary_->SetFrameDumpConfig(frame_dump_count, bit_mask_layer_type);
+    }
+  }
+
+  if (IS_BIT_SET(bit_mask_display_type, HWC_DISPLAY_EXTERNAL)) {
+    if (display_external_) {
+      display_external_->SetFrameDumpConfig(frame_dump_count, bit_mask_layer_type);
+    }
+  }
+
+  if (IS_BIT_SET(bit_mask_display_type, HWC_DISPLAY_VIRTUAL)) {
+    if (display_virtual_) {
+      display_virtual_->SetFrameDumpConfig(frame_dump_count, bit_mask_layer_type);
+    }
+  }
+}
+
+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:
+    HWCDebugHandler::DebugAll(enable);
+    break;
+
+  case qService::IQService::DEBUG_MDPCOMP:
+    HWCDebugHandler::DebugStrategy(enable);
+    HWCDebugHandler::DebugCompManager(enable);
+    break;
+
+  case qService::IQService::DEBUG_PIPE_LIFECYCLE:
+    HWCDebugHandler::DebugResources(enable);
+    break;
+
+  case qService::IQService::DEBUG_DRIVER_CONFIG:
+    HWCDebugHandler::DebugDriverConfig(enable);
+    break;
+
+  case qService::IQService::DEBUG_ROTATOR:
+    HWCDebugHandler::DebugResources(enable);
+    HWCDebugHandler::DebugDriverConfig(enable);
+    HWCDebugHandler::DebugRotator(enable);
+    break;
+
+  default:
+    DLOGW("type = %d is not supported", type);
+  }
+}
+
+void* HWCSession::HWCUeventThread(void *context) {
+  if (context) {
+    return reinterpret_cast<HWCSession *>(context)->HWCUeventThreadHandler();
+  }
+
+  return NULL;
+}
+
+void* HWCSession::HWCUeventThreadHandler() {
+  static char uevent_data[PAGE_SIZE];
+  int length = 0;
+  prctl(PR_SET_NAME, uevent_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 (!uevent_thread_exit_) {
+    // keep last 2 zeroes to ensure double 0 termination
+    length = uevent_next_event(uevent_data, INT32(sizeof(uevent_data)) - 2);
+
+    if (strcasestr(HWC_UEVENT_SWITCH_HDMI, uevent_data)) {
+      DLOGI("Uevent HDMI = %s", uevent_data);
+      int connected = GetEventValue(uevent_data, length, "SWITCH_STATE=");
+      if (connected >= 0) {
+        DLOGI("HDMI = %s", connected ? "connected" : "disconnected");
+        if (HotPlugHandler(connected) == -1) {
+          DLOGE("Failed handling Hotplug = %s", connected ? "connected" : "disconnected");
+        }
+      }
+    } else if (strcasestr(HWC_UEVENT_GRAPHICS_FB0, uevent_data)) {
+      DLOGI("Uevent FB0 = %s", uevent_data);
+      int panel_reset = GetEventValue(uevent_data, length, "PANEL_ALIVE=");
+      if (panel_reset == 0) {
+        if (hwc_procs_) {
+          reset_panel_ = true;
+          hwc_procs_->invalidate(hwc_procs_);
+        } else {
+          DLOGW("Ignore resetpanel - hwc_proc not registered");
+        }
+      }
+    }
+  }
+  pthread_exit(0);
+
+  return NULL;
+}
+
+int HWCSession::GetEventValue(const char *uevent_data, int length, const char *event_info) {
+  const char *iterator_str = uevent_data;
+  while (((iterator_str - uevent_data) <= length) && (*iterator_str)) {
+    char *pstr = strstr(iterator_str, event_info);
+    if (pstr != NULL) {
+      return (atoi(iterator_str + strlen(event_info)));
+    }
+    iterator_str += strlen(iterator_str) + 1;
+  }
+
+  return -1;
+}
+
+void HWCSession::ResetPanel() {
+  int status = -EINVAL;
+
+  DLOGI("Powering off primary");
+  status = display_primary_->SetPowerMode(HWC_POWER_MODE_OFF);
+  if (status) {
+    DLOGE("power-off on primary failed with error = %d", status);
+  }
+
+  DLOGI("Restoring power mode on primary");
+  uint32_t mode = display_primary_->GetLastPowerMode();
+  status = display_primary_->SetPowerMode(mode);
+  if (status) {
+    DLOGE("Setting power mode = %d on primary failed with error = %d", mode, status);
+  }
+
+  status = display_primary_->EventControl(HWC_EVENT_VSYNC, 1);
+  if (status) {
+    DLOGE("enabling vsync failed for primary with error = %d", status);
+  }
+
+  reset_panel_ = false;
+}
+
+int HWCSession::HotPlugHandler(bool connected) {
+  if (!hwc_procs_) {
+     DLOGW("Ignore hotplug - hwc_proc not registered");
+    return -1;
+  }
+
+  if (connected) {
+    SEQUENCE_WAIT_SCOPE_LOCK(locker_);
+    if (display_virtual_) {
+      // Wait for the virtual display to tear down
+      int status = locker_.WaitFinite(kExternalConnectionTimeoutMs);
+      if (status != 0) {
+        DLOGE("Timed out while waiting for virtual display to tear down.");
+        return -1;
+      }
+    }
+    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;
+    }
+    SetFrameBufferResolution(HWC_DISPLAY_EXTERNAL, NULL);
+  } else {
+    SEQUENCE_WAIT_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;
+}
+
+void HWCSession::SetFrameBufferResolution(int disp, hwc_display_contents_1_t *content_list) {
+  char property[PROPERTY_VALUE_MAX];
+  uint32_t primary_width = 0;
+  uint32_t primary_height = 0;
+
+  switch (disp) {
+  case HWC_DISPLAY_PRIMARY:
+  {
+    display_primary_->GetPanelResolution(&primary_width, &primary_height);
+    if (property_get("debug.hwc.fbsize", property, NULL) > 0) {
+      char *yptr = strcasestr(property, "x");
+      primary_width = atoi(property);
+      primary_height = atoi(yptr + 1);
+    }
+    display_primary_->SetFrameBufferResolution(primary_width, primary_height);
+    break;
+  }
+
+  case HWC_DISPLAY_EXTERNAL:
+  {
+    uint32_t external_width = 0;
+    uint32_t external_height = 0;
+    display_external_->GetPanelResolution(&external_width, &external_height);
+
+    if (property_get("sys.hwc.mdp_downscale_enabled", property, "false") &&
+        !strcmp(property, "true")) {
+      display_primary_->GetFrameBufferResolution(&primary_width, &primary_height);
+      uint32_t primary_area = primary_width * primary_height;
+      uint32_t external_area = external_width * external_height;
+
+      if (primary_area > external_area) {
+        if (primary_height > primary_width) {
+          Swap(primary_height, primary_width);
+        }
+        AdjustSourceResolution(primary_width, primary_height,
+                               &external_width, &external_height);
+      }
+    }
+    display_external_->SetFrameBufferResolution(external_width, external_height);
+    break;
+  }
+
+  case HWC_DISPLAY_VIRTUAL:
+  {
+    if (ValidateContentList(content_list)) {
+      const private_handle_t *output_handle =
+              static_cast<const private_handle_t *>(content_list->outbuf);
+      int virtual_width = 0;
+      int virtual_height = 0;
+      getBufferSizeAndDimensions(output_handle->width, output_handle->height, output_handle->format,
+                                 virtual_width, virtual_height);
+      display_virtual_->SetFrameBufferResolution(virtual_width, virtual_height);
+    }
+    break;
+  }
+
+  default:
+    break;
+  }
+}
+
+void HWCSession::AdjustSourceResolution(uint32_t dst_width, uint32_t dst_height,
+                                        uint32_t *src_width, uint32_t *src_height) {
+  *src_height = (dst_width * (*src_height)) / (*src_width);
+  *src_width = dst_width;
+}
+
+}  // namespace sdm
+
diff --git a/sdm/libs/hwc/hwc_session.h b/sdm/libs/hwc/hwc_session.h
new file mode 100644
index 0000000..15b762c
--- /dev/null
+++ b/sdm/libs/hwc/hwc_session.h
@@ -0,0 +1,116 @@
+/*
+* 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:
+*    * Redistributions of source code must retain the above copyright notice, this list of
+*      conditions and the following disclaimer.
+*    * Redistributions in binary form must reproduce the above copyright notice, this list of
+*      conditions and the following disclaimer in the documentation and/or other materials provided
+*      with the distribution.
+*    * Neither the name of The Linux Foundation nor the names of its contributors may be used to
+*      endorse or promote products derived from this software without specific prior written
+*      permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef __HWC_SESSION_H__
+#define __HWC_SESSION_H__
+
+#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"
+#include "hwc_display_virtual.h"
+
+namespace sdm {
+
+class HWCSession : hwc_composer_device_1_t, CoreEventHandler, public qClient::BnQClient {
+ public:
+  struct HWCModuleMethods : public hw_module_methods_t {
+    HWCModuleMethods() {
+      hw_module_methods_t::open = HWCSession::Open;
+    }
+  };
+
+  explicit HWCSession(const hw_module_t *module);
+  int Init();
+  int Deinit();
+
+ private:
+  static const int kExternalConnectionTimeoutMs = 500;
+
+  // hwc methods
+  static int Open(const hw_module_t *module, const char* name, hw_device_t **device);
+  static int Close(hw_device_t *device);
+  static int Prepare(hwc_composer_device_1 *device, size_t num_displays,
+                     hwc_display_contents_1_t **displays);
+  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 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);
+  static int GetDisplayConfigs(hwc_composer_device_1 *device, int disp, uint32_t *configs,
+                               size_t *numConfigs);
+  static int GetDisplayAttributes(hwc_composer_device_1 *device, int disp, uint32_t config,
+                                  const uint32_t *attributes, int32_t *values);
+  static int GetActiveConfig(hwc_composer_device_1 *device, int disp);
+  static int SetActiveConfig(hwc_composer_device_1 *device, int disp, int index);
+
+  // Uevent thread
+  static void* HWCUeventThread(void *context);
+  void* HWCUeventThreadHandler();
+  int GetEventValue(const char *uevent_data, int length, const char *event_info);
+  int HotPlugHandler(bool connected);
+  void ResetPanel();
+  bool ValidateContentList(hwc_display_contents_1_t *content_list);
+  int CreateVirtualDisplay(hwc_display_contents_1_t *content_list);
+  int DestroyVirtualDisplay();
+
+  // 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);
+  void SetFrameDumpConfig(const android::Parcel *input_parcel);
+  android::status_t SetMaxMixerStages(const android::Parcel *input_parcel);
+  android::status_t SetDisplayMode(const android::Parcel *input_parcel);
+  android::status_t SetSecondaryDisplayStatus(const android::Parcel *input_parcel);
+  void SetFrameBufferResolution(int disp, hwc_display_contents_1_t *content_list);
+  void AdjustSourceResolution(uint32_t dst_width, uint32_t dst_height,
+                              uint32_t *src_width, uint32_t *src_height);
+  android::status_t ConfigureRefreshRate(const android::Parcel *input_parcel);
+
+  static Locker locker_;
+  CoreInterface *core_intf_;
+  hwc_procs_t const *hwc_procs_;
+  HWCDisplayPrimary *display_primary_;
+  HWCDisplayExternal *display_external_;
+  HWCDisplayVirtual *display_virtual_;
+  pthread_t uevent_thread_;
+  bool uevent_thread_exit_;
+  static bool reset_panel_;
+  const char *uevent_thread_name_;
+  HWCBufferAllocator *buffer_allocator_;
+  HWCBufferSyncHandler *buffer_sync_handler_;
+};
+
+}  // namespace sdm
+
+#endif  // __HWC_SESSION_H__
+
diff --git a/sdm/libs/utils/Android.mk b/sdm/libs/utils/Android.mk
new file mode 100644
index 0000000..57c2088
--- /dev/null
+++ b/sdm/libs/utils/Android.mk
@@ -0,0 +1,13 @@
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE                  := libsdmutils
+LOCAL_MODULE_TAGS             := optional
+LOCAL_C_INCLUDES              := hardware/qcom/display/sdm/include/
+LOCAL_CFLAGS                  := -Wno-missing-field-initializers -Wno-unused-parameter \
+                                 -Wconversion -Wall -Werror \
+                                 -DLOG_TAG=\"SDM\"
+LOCAL_SHARED_LIBRARIES        := libcutils
+LOCAL_SRC_FILES               := debug_android.cpp rect.cpp
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/sdm/libs/utils/debug_android.cpp b/sdm/libs/utils/debug_android.cpp
new file mode 100644
index 0000000..f57d04d
--- /dev/null
+++ b/sdm/libs/utils/debug_android.cpp
@@ -0,0 +1,103 @@
+/*
+* 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:
+*     * 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 <stdlib.h>
+#include <utils/debug.h>
+#include <utils/constants.h>
+#include <cutils/log.h>
+#include <cutils/properties.h>
+
+namespace sdm {
+
+Debug Debug::debug_;
+
+Debug::Debug() : debug_handler_(&default_debug_handler_), virtual_driver_(false) {
+  char property[PROPERTY_VALUE_MAX];
+  if (property_get("displaycore.virtualdriver", property, NULL) > 0) {
+    virtual_driver_ = (atoi(property) == 1);
+  }
+}
+
+uint32_t Debug::GetSimulationFlag() {
+  char property[PROPERTY_VALUE_MAX];
+  if (property_get("debug.hwc.simulate", property, NULL) > 0) {
+    return atoi(property);
+  }
+
+  return 0;
+}
+
+uint32_t Debug::GetHDMIResolution() {
+  char property[PROPERTY_VALUE_MAX];
+  if (property_get("hw.hdmi.resolution", property, NULL) > 0) {
+    return atoi(property);
+  }
+
+  return 0;
+}
+
+uint32_t Debug::GetIdleTimeoutMs() {
+  char property[PROPERTY_VALUE_MAX];
+  if (property_get("debug.mdpcomp.idletime", property, NULL) > 0) {
+    return atoi(property);
+  }
+
+  return IDLE_TIMEOUT_DEFAULT_MS;
+}
+
+bool Debug::IsRotatorDownScaleDisabled() {
+  char property[PROPERTY_VALUE_MAX];
+  if (property_get("sdm.disable_rotator_downscaling", property, NULL) > 0) {
+    return (atoi(property) ? 0 : false, true);
+  }
+
+  return false;
+}
+
+bool Debug::IsDecimationDisabled() {
+  char property[PROPERTY_VALUE_MAX];
+  if (property_get("sdm.disable_decimation", property, NULL) > 0) {
+    return (atoi(property) ? 0 : false, true);
+  }
+
+  return false;
+}
+
+// This property serves to disable/enable partial update
+bool Debug::IsPartialUpdateEnabled() {
+  char property[PROPERTY_VALUE_MAX];
+  if (property_get("sdm.hwc.partial_update", property, NULL) > 0) {
+    return (atoi(property) ? 1 : true, false);
+  }
+
+  return false;
+}
+
+}  // namespace sdm
+
diff --git a/sdm/libs/utils/rect.cpp b/sdm/libs/utils/rect.cpp
new file mode 100644
index 0000000..9edc4f4
--- /dev/null
+++ b/sdm/libs/utils/rect.cpp
@@ -0,0 +1,142 @@
+/*
+* Copyright (c) 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:
+*   * 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 <math.h>
+#include <utils/rect.h>
+#include <utils/constants.h>
+
+#define __CLASS__ "RectUtils"
+
+namespace sdm {
+
+bool IsValid(const LayerRect &rect) {
+  return ((rect.bottom > rect.top) && (rect.right > rect.left));
+}
+
+bool IsCongruent(const LayerRect &rect1, const LayerRect &rect2) {
+  return ((rect1.left == rect2.left) &&
+          (rect1.top == rect2.top) &&
+          (rect1.right == rect2.right) &&
+          (rect1.bottom == rect2.bottom));
+}
+
+void Log(DebugTag debug_tag, const char *prefix, const LayerRect &roi) {
+  DLOGV_IF(debug_tag, "%s: left = %.0f, top = %.0f, right = %.0f, bottom = %.0f",
+           prefix, roi.left, roi.top, roi.right, roi.bottom);
+}
+
+void Normalize(const uint32_t &align_x, const uint32_t &align_y, LayerRect *rect) {
+    rect->left = ROUND_UP_ALIGN_UP(rect->left, align_x);
+    rect->right = ROUND_UP_ALIGN_DOWN(rect->right, align_x);
+    rect->top = ROUND_UP_ALIGN_UP(rect->top, align_y);
+    rect->bottom = ROUND_UP_ALIGN_DOWN(rect->bottom, align_y);
+}
+
+LayerRect Intersection(const LayerRect &rect1, const LayerRect &rect2) {
+  LayerRect res;
+
+  if (!IsValid(rect1) || !IsValid(rect2)) {
+    return LayerRect();
+  }
+
+  res.left = MAX(rect1.left, rect2.left);
+  res.top = MAX(rect1.top, rect2.top);
+  res.right = MIN(rect1.right, rect2.right);
+  res.bottom = MIN(rect1.bottom, rect2.bottom);
+
+  if (!IsValid(res)) {
+    return LayerRect();
+  }
+
+  return res;
+}
+
+LayerRect Reposition(const LayerRect &rect, const int &x_offset, const int &y_offset) {
+  LayerRect res;
+
+  if (!IsValid(rect)) {
+    return LayerRect();
+  }
+
+  res.left = rect.left + FLOAT(x_offset);
+  res.top = rect.top + FLOAT(y_offset);
+  res.right = rect.right + FLOAT(x_offset);
+  res.bottom = rect.bottom + FLOAT(y_offset);
+
+  return res;
+}
+
+// Not a geometrical rect deduction. Deducts rect2 from rect1 only if it results a single rect
+LayerRect Subtract(const LayerRect &rect1, const LayerRect &rect2) {
+  LayerRect res;
+
+  res = rect1;
+
+  if ((rect1.left == rect2.left) && (rect1.right == rect2.right)) {
+    if ((rect1.top == rect2.top) && (rect2.bottom <= rect1.bottom)) {
+      res.top = rect2.bottom;
+    } else if ((rect1.bottom == rect2.bottom) && (rect2.top >= rect1.top)) {
+      res.bottom = rect2.top;
+    }
+  } else if ((rect1.top == rect2.top) && (rect1.bottom == rect2.bottom)) {
+    if ((rect1.left == rect2.left) && (rect2.right <= rect1.right)) {
+      res.left = rect2.right;
+    } else if ((rect1.right == rect2.right) && (rect2.left >= rect1.left)) {
+      res.right = rect2.left;
+    }
+  }
+
+  return res;
+}
+
+LayerRect Union(const LayerRect &rect1, const LayerRect &rect2) {
+  LayerRect res;
+
+  if (!IsValid(rect1) && !IsValid(rect2)) {
+    return LayerRect();
+  }
+
+  if (!IsValid(rect1)) {
+    return rect2;
+  }
+
+  if (!IsValid(rect2)) {
+    return rect1;
+  }
+
+  res.left = MIN(rect1.left, rect2.left);
+  res.top = MIN(rect1.top, rect2.top);
+  res.right = MAX(rect1.right, rect2.right);
+  res.bottom = MAX(rect1.bottom, rect2.bottom);
+
+  return res;
+}
+
+}  // namespace sdm
+